Skip to content

Commit 6331fcf

Browse files
hyperpolymathclaude
andcommitted
chore: OpenSSF workflows and compliance updates
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent cd1b23b commit 6331fcf

19 files changed

Lines changed: 2255 additions & 14 deletions
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# SPDX-License-Identifier: PMPL-1.0-or-later
2+
# Conformance: add{} block (JTV data injection)
3+
4+
def x = add{ 1 + 2 + 3 }
5+
assert x == 6
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# SPDX-License-Identifier: PMPL-1.0-or-later
2+
# Conformance: weave as expression (inside def body)
3+
4+
def simple_crossing =
5+
weave strands a:Q, b:Q into
6+
(a > b)
7+
yield strands b:Q, a:Q
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# SPDX-License-Identifier: PMPL-1.0-or-later
2+
# Conformance: recursive function with pattern matching (Turing completeness)
3+
4+
def length(w) = match w with
5+
| identity => 0
6+
| s1 . rest => 1 + length(rest)
7+
| s2 . rest => 1 + length(rest)
8+
| _ => 0
9+
end
10+
11+
assert length(braid[s1, s1, s1]) == 3
12+
assert length(identity) == 0
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# SPDX-License-Identifier: PMPL-1.0-or-later
2+
# Conformance: simplify (Reidemeister moves) and isotopy
3+
4+
assert simplify(braid[s1, s1^-1]) == identity
5+
assert braid[s1, s1^-1] ~ identity
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# SPDX-License-Identifier: PMPL-1.0-or-later
2+
# Conformance: horizontal tensor (|) with index shifting
3+
4+
assert (braid[s1] | braid[s1]) == braid[s1, s3]
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# SPDX-License-Identifier: PMPL-1.0-or-later
2+
# Conformance: close, mirror, reverse operations
3+
4+
def trefoil = braid[s1, s1, s1]
5+
6+
assert mirror(trefoil) == braid[s1^-1, s1^-1, s1^-1]
7+
assert reverse(braid[s1, s2]) == braid[s2, s1]
8+
9+
compute writhe(close(trefoil))

editors/tangle.tmLanguage.json

Lines changed: 86 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
{
22
"$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
33
"_comment": "SPDX-License-Identifier: PMPL-1.0-or-later",
4+
"_description": "TextMate grammar for TANGLE — Turing-complete topological programming language",
45
"name": "Tangle",
56
"scopeName": "source.tangle",
67
"fileTypes": [
7-
"tangle"
8+
"tangle",
9+
"tgl"
810
],
911
"patterns": [
1012
{
@@ -19,6 +21,9 @@
1921
{
2022
"include": "#constants"
2123
},
24+
{
25+
"include": "#jtv-blocks"
26+
},
2227
{
2328
"include": "#keywords"
2429
},
@@ -42,13 +47,13 @@
4247
"comments": {
4348
"patterns": [
4449
{
45-
"name": "comment.line.double-dash.tangle",
46-
"match": "--.*$"
50+
"name": "comment.line.hash.tangle",
51+
"match": "#.*$"
4752
},
4853
{
4954
"name": "comment.block.tangle",
50-
"begin": "\\{-",
51-
"end": "-\\}",
55+
"begin": "\\(\\*",
56+
"end": "\\*\\)",
5257
"patterns": [
5358
{
5459
"include": "#comments"
@@ -74,9 +79,17 @@
7479
},
7580
"numbers": {
7681
"patterns": [
82+
{
83+
"name": "constant.numeric.hex.tangle",
84+
"match": "\\b0x[0-9a-fA-F]+\\b"
85+
},
86+
{
87+
"name": "constant.numeric.binary.tangle",
88+
"match": "\\b0b[01]+\\b"
89+
},
7790
{
7891
"name": "constant.numeric.float.tangle",
79-
"match": "\\b[0-9]+\\.[0-9]+\\b"
92+
"match": "\\b[0-9]+\\.[0-9]+([eE][+-]?[0-9]+)?\\b"
8093
},
8194
{
8295
"name": "constant.numeric.integer.tangle",
@@ -89,6 +102,68 @@
89102
{
90103
"name": "constant.language.boolean.tangle",
91104
"match": "\\b(true|false)\\b"
105+
},
106+
{
107+
"name": "constant.language.identity.tangle",
108+
"match": "\\bidentity\\b"
109+
}
110+
]
111+
},
112+
"jtv-blocks": {
113+
"patterns": [
114+
{
115+
"name": "meta.block.add.tangle",
116+
"begin": "\\b(add)\\s*(\\{)",
117+
"beginCaptures": {
118+
"1": { "name": "keyword.control.jtv.tangle" },
119+
"2": { "name": "punctuation.definition.block.begin.tangle" }
120+
},
121+
"end": "\\}",
122+
"endCaptures": {
123+
"0": { "name": "punctuation.definition.block.end.tangle" }
124+
},
125+
"patterns": [
126+
{ "include": "#strings" },
127+
{ "include": "#numbers" },
128+
{ "include": "#constants" },
129+
{ "include": "#identifiers" }
130+
]
131+
},
132+
{
133+
"name": "meta.block.harvard.tangle",
134+
"begin": "\\b(harvard)\\s*(\\{)",
135+
"beginCaptures": {
136+
"1": { "name": "keyword.control.jtv.tangle" },
137+
"2": { "name": "punctuation.definition.block.begin.tangle" }
138+
},
139+
"end": "\\}",
140+
"endCaptures": {
141+
"0": { "name": "punctuation.definition.block.end.tangle" }
142+
},
143+
"patterns": [
144+
{ "include": "#jtv-keywords" },
145+
{ "include": "#jtv-purity" },
146+
{ "include": "#strings" },
147+
{ "include": "#numbers" },
148+
{ "include": "#constants" },
149+
{ "include": "#identifiers" }
150+
]
151+
}
152+
]
153+
},
154+
"jtv-keywords": {
155+
"patterns": [
156+
{
157+
"name": "keyword.control.jtv.tangle",
158+
"match": "\\b(fn|if|else|while|for|return|print|module|import|as|then|reverse)\\b"
159+
}
160+
]
161+
},
162+
"jtv-purity": {
163+
"patterns": [
164+
{
165+
"name": "storage.modifier.purity.tangle",
166+
"match": "@(pure|total)\\b"
92167
}
93168
]
94169
},
@@ -100,7 +175,7 @@
100175
},
101176
{
102177
"name": "keyword.declaration.tangle",
103-
"match": "\\b(def|weave|into|strands|compute|assert|identity)\\b"
178+
"match": "\\b(def|weave|into|strands|compute|assert)\\b"
104179
},
105180
{
106181
"name": "keyword.other.topology.tangle",
@@ -134,10 +209,6 @@
134209
"name": "keyword.operator.pipeline.tangle",
135210
"match": ">>"
136211
},
137-
{
138-
"name": "keyword.operator.crossing.tangle",
139-
"match": ">|<"
140-
},
141212
{
142213
"name": "keyword.operator.isotopy.tangle",
143214
"match": "~"
@@ -150,6 +221,10 @@
150221
"name": "keyword.operator.assignment.tangle",
151222
"match": "="
152223
},
224+
{
225+
"name": "keyword.operator.crossing.tangle",
226+
"match": "[><]"
227+
},
153228
{
154229
"name": "keyword.operator.tensor.tangle",
155230
"match": "\\|"

examples/braids_as_data.tangle

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# SPDX-License-Identifier: PMPL-1.0-or-later
2+
# braids_as_data.tangle — Braid words as an algebraic data structure
3+
#
4+
# Tangle's most distinctive feature: braid words ARE the data structure.
5+
# identity = nil, s_i = constructor, `.` = cons, pattern matching = destruct.
6+
#
7+
# This means recursive algorithms over braids look like list algorithms,
8+
# but the data they process has intrinsic topological meaning.
9+
#
10+
# Demonstrates:
11+
# - Pattern matching on braid structure (D1.3)
12+
# - Recursion on Words (D1.3)
13+
# - Turing completeness via pattern matching + recursion (D1.24)
14+
# - Multiple generator matching
15+
# - The Word/Tangle distinction (D1.1)
16+
17+
# --- Count the total number of generators ---
18+
19+
def length(w) = match w with
20+
| identity => 0
21+
| s1 . rest => 1 + length(rest)
22+
| s2 . rest => 1 + length(rest)
23+
| s3 . rest => 1 + length(rest)
24+
| _ => 0
25+
end
26+
27+
# --- Count only positive crossings (writhe contribution) ---
28+
29+
def positive_count(w) = match w with
30+
| identity => 0
31+
| s1 . rest => 1 + positive_count(rest)
32+
| s2 . rest => 1 + positive_count(rest)
33+
| _ => positive_count(identity)
34+
end
35+
36+
# --- Check if a word starts with a specific generator ---
37+
38+
def starts_with_s1(w) = match w with
39+
| s1 . rest => true
40+
| _ => false
41+
end
42+
43+
# --- Test the recursive functions ---
44+
45+
def three_strand = braid[s1, s2, s1, s2]
46+
47+
assert length(three_strand) == 4
48+
assert starts_with_s1(three_strand) == true
49+
assert starts_with_s1(braid[s2]) == false
50+
assert starts_with_s1(identity) == false
51+
52+
# --- Composition is concatenation ---
53+
54+
def a = braid[s1, s1]
55+
def b = braid[s2, s2]
56+
def ab = a . b
57+
58+
assert ab == braid[s1, s1, s2, s2]
59+
assert length(ab) == 4
60+
61+
# --- Identity is the unit ---
62+
63+
assert identity . a == a
64+
assert a . identity == a
65+
66+
# --- Simplification cancels adjacent inverses ---
67+
68+
def redundant = braid[s1, s2, s2^-1, s1]
69+
assert simplify(redundant) == braid[s1, s1]

examples/isotopy.tangle

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# SPDX-License-Identifier: PMPL-1.0-or-later
2+
# isotopy.tangle — Exploring isotopy equivalence
3+
#
4+
# The key insight of TANGLE: two braids can be structurally different
5+
# (different sequences of generators) but topologically equivalent
6+
# (same knot/link when closed). The `~` operator checks this.
7+
#
8+
# Demonstrates:
9+
# - Isotopy equivalence vs structural equality (D1.2)
10+
# - Reidemeister moves (D1.16)
11+
# - The deep duality between syntax and topology
12+
13+
# --- Reidemeister II: inverse cancellation ---
14+
15+
# s1 followed by s1^-1 is isotopic to doing nothing
16+
assert braid[s1, s1^-1] ~ identity
17+
18+
# This works at any position in the word
19+
assert braid[s2, s1, s1^-1, s2] ~ braid[s2, s2]
20+
21+
# But structurally they are NOT equal
22+
assert braid[s1, s1^-1] == braid[s1, s1^-1]
23+
24+
# --- Far commutativity ---
25+
# Generators on distant strands can commute: s1 s3 = s3 s1
26+
# (because |1-3| >= 2)
27+
28+
# s1 and s3 commute, so s1 s3 s1^-1 ~ s3
29+
assert simplify(braid[s1, s3, s1^-1]) ~ braid[s3]
30+
31+
# --- Self-isotopy ---
32+
# Every braid is isotopic to itself
33+
assert braid[s1, s2, s1] ~ braid[s1, s2, s1]
34+
assert identity ~ identity
35+
36+
# --- Isotopy of closed braids ---
37+
# The closure of isotopic braids gives the same knot
38+
assert close(braid[s1, s1^-1]) ~ close(identity)
39+
40+
# --- Pipeline and composition are isotopic ---
41+
# >> is syntactic sugar for . (D1.20)
42+
assert (braid[s1] >> braid[s2]) ~ (braid[s1] . braid[s2])

examples/tensor_product.tangle

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# SPDX-License-Identifier: PMPL-1.0-or-later
2+
# tensor_product.tangle — Horizontal tensor and multi-strand braids
3+
#
4+
# The tensor product (|) places two braids side by side, shifting
5+
# the second braid's strand indices by the width of the first.
6+
# This is the monoidal structure of the braid category.
7+
#
8+
# Demonstrates:
9+
# - Horizontal tensor operator (D1.8)
10+
# - Auto-widening on composition (D1.8.5)
11+
# - Multi-strand braid construction
12+
# - The categorical structure of Tangle
13+
14+
# --- Basic tensor ---
15+
# braid[s1] acts on strands 1,2 (width 2)
16+
# Tensoring with another braid[s1] shifts the second to strands 3,4
17+
18+
def crossing_12 = braid[s1]
19+
def crossing_34 = crossing_12 | crossing_12
20+
21+
# The tensor should produce s1 followed by s3
22+
# (s1 on strands 1-2, then s1 shifted by 2 = s3 on strands 3-4)
23+
assert crossing_34 == braid[s1, s3]
24+
25+
# --- Building complex braids via tensor ---
26+
27+
def left = braid[s1, s1]
28+
def right = braid[s1]
29+
30+
# Left on strands 1-2, right on strands 3-4
31+
def both = left | right
32+
assert both == braid[s1, s1, s3]
33+
34+
# --- Composition after tensor ---
35+
# After tensoring, we can compose vertically to interleave
36+
37+
def interleaved = both . braid[s2]
38+
assert interleaved == braid[s1, s1, s3, s2]
39+
40+
# --- Tensor width tracking ---
41+
42+
def w2 = braid[s1]
43+
def w3 = braid[s2]
44+
45+
# w2 has width 2, w3 has width 3
46+
# Tensor: w3 shifts by width(w2) = 2, so s2 becomes s4
47+
def tensored = w2 | w3
48+
assert tensored == braid[s1, s4]
49+
50+
# --- Identity tensor ---
51+
# identity has width 0, so tensoring with it changes nothing
52+
53+
assert (identity | braid[s1]) == braid[s1]
54+
assert (braid[s1] | identity) == braid[s1]
55+
56+
# --- Writhe of tensor products ---
57+
58+
compute writhe(crossing_34)
59+
compute writhe(both)

0 commit comments

Comments
 (0)