speckl: TypeScript state machine generator + Forgejo issue workflow spec
Some checks failed
Deploy Landing Page to Storj / deploy (push) Failing after 2s

Adds a first-class TypeScript code generator to speckl-compile that emits:
- Const enum for workflow states (IssueWorkflowState)
- Strongly-typed class with guards, state transitions, decision log
- Proper this. prefixing (state vars only, not local params)
- Enum references instead of string literals for state comparisons
- Clean tsc --noEmit compilation

Also includes:
- specs/forgejo-issue-workflow.speckdl — full workflow with 9 actions,
  8 constraints, 5 temporal verifications
- Generator deduplication of duplicate AST nodes
- Support for init block initialization of state variables

The generator was validated against the Forgejo issue workflow spec,
producing IssueWorkflow.ts that compiles with zero errors.

Refs: heartbeat conversation re: speckl-compile extensibility
This commit is contained in:
Scott Scoble 2026-05-03 12:23:33 -07:00
parent cbee677a11
commit 7ffd65f6b3
18 changed files with 2272 additions and 107 deletions

View file

@ -12,22 +12,22 @@
"@type": "prov:Generation",
"prov:activity": {
"@type": "prov:Activity",
"prov:startTime": "2026-04-29T22:11:59.830Z"
"prov:startTime": "2026-05-03T18:51:34.102Z"
}
},
"rdfs:label": "RetryHandler",
"prov:wasDerivedFrom": {
"@id": "speck:FaultHandler"
},
"rdfs:comment": "\"",
"rdfs:comment": "specialization for retry logic",
"speckl:satisfies": {
"@id": "requirement:RESILIENCE"
"@id": "requirement:RESILIENCE-REQ-01"
},
"prov:wasAttributedTo": {
"@id": "agent:\""
"@id": "agent:Scott Scoble"
},
"prov:wasInformedBy": {
"@id": "source:architecture_review:\""
"@id": "source:architecture_review:AR-2024-0215"
}
},
{
@ -36,25 +36,26 @@
},
{
"@type": "prov:Entity",
"@id": "requirement:RESILIENCE",
"rdfs:label": "RESILIENCE"
"@id": "requirement:RESILIENCE-REQ-01",
"rdfs:label": "RESILIENCE-REQ-01",
"speckl:clause": "3.1.2"
},
{
"@type": "prov:Entity",
"@id": "requirement:RESILIENCE",
"rdfs:label": "RESILIENCE"
"@id": "requirement:RESILIENCE-REQ-02",
"rdfs:label": "RESILIENCE-REQ-02"
},
{
"@type": "prov:Agent",
"@id": "agent:\"",
"rdfs:label": "\"",
"foaf:email": "Scott Scoble"
"@id": "agent:Scott Scoble",
"rdfs:label": "Scott Scoble",
"foaf:email": "scott@scoble.me"
},
{
"@type": "prov:Activity",
"@id": "source:architecture_review:\"",
"@id": "source:architecture_review:AR-2024-0215",
"prov:type": "architecture_review",
"rdfs:label": "architecture_review - \""
"rdfs:label": "architecture_review - AR-2024-0215"
}
]
}

View file

@ -15,11 +15,11 @@
},
{
"name": "speckl:satisfies",
"value": "RESILIENCE"
"value": "RESILIENCE-REQ-01 clause 3.1.2"
},
{
"name": "speckl:satisfies",
"value": "RESILIENCE"
"value": "RESILIENCE-REQ-02"
}
]
}
@ -35,10 +35,10 @@
}
],
"author": {
"name": "\"",
"email": "Scott Scoble"
"name": "Scott Scoble",
"email": "scott@scoble.me"
},
"timestamp": "2026-04-29T22:11:59.832Z"
"timestamp": "2026-05-03T18:51:34.104Z"
},
{
"subject": "speck:RetryHandler",
@ -53,7 +53,7 @@
"name": "Speckl Compiler",
"email": "compiler@speckl.scoble.me"
},
"timestamp": "2026-04-29T22:11:59.832Z"
"timestamp": "2026-05-03T18:51:34.104Z"
},
{
"subject": "speck:RetryHandler",
@ -68,7 +68,7 @@
"name": "Speckl Compiler",
"email": "compiler@speckl.scoble.me"
},
"timestamp": "2026-04-29T22:11:59.832Z"
"timestamp": "2026-05-03T18:51:34.104Z"
}
]
}

View file

@ -13,7 +13,7 @@
"spdxVersion": "3.0.1",
"dataLicense": "CC0-1.0",
"creationInfo": {
"created": "2026-04-29T22:11:59.833Z",
"created": "2026-05-03T18:51:34.105Z",
"createdBy": [
"Organization: Speckl",
"tool: speckl-compile-0.2.0"
@ -27,7 +27,7 @@
"@type": "spdx:Tool",
"name": "speckl-compile"
},
"timestamp": "2026-04-29T22:11:59.833Z",
"timestamp": "2026-05-03T18:51:34.105Z",
"comment": "Review type: manual"
}
]
@ -48,7 +48,22 @@
"@id": "spdx:RetryHandler"
},
"to": {
"@id": "spdx:requirement:RESILIENCE"
"@id": "spdx:requirement:RESILIENCE-REQ-01"
},
"relationshipType": "speckl:satisfies",
"additionalProperties": [
{
"name": "speckl:clause",
"value": "3.1.2"
}
]
},
{
"from": {
"@id": "spdx:RetryHandler"
},
"to": {
"@id": "spdx:requirement:RESILIENCE-REQ-02"
},
"relationshipType": "speckl:satisfies"
},
@ -57,16 +72,7 @@
"@id": "spdx:RetryHandler"
},
"to": {
"@id": "spdx:requirement:RESILIENCE"
},
"relationshipType": "speckl:satisfies"
},
{
"from": {
"@id": "spdx:RetryHandler"
},
"to": {
"@id": "spdx:agent:\""
"@id": "spdx:agent:Scott Scoble"
},
"relationshipType": "spdx:wasAttributedTo"
},
@ -75,7 +81,7 @@
"@id": "spdx:RetryHandler"
},
"to": {
"@id": "spdx:source:architecture_review:\""
"@id": "spdx:source:architecture_review:AR-2024-0215"
},
"relationshipType": "spdx:wasInformedBy"
}
@ -83,24 +89,24 @@
"elements": [
{
"@type": "spdx:Requirement",
"@id": "spdx:requirement:RESILIENCE",
"name": "RESILIENCE"
"@id": "spdx:requirement:RESILIENCE-REQ-01",
"name": "RESILIENCE-REQ-01"
},
{
"@type": "spdx:Requirement",
"@id": "spdx:requirement:RESILIENCE",
"name": "RESILIENCE"
"@id": "spdx:requirement:RESILIENCE-REQ-02",
"name": "RESILIENCE-REQ-02"
},
{
"@type": "spdx:Person",
"@id": "spdx:agent:\"",
"name": "\"",
"email": "Scott Scoble"
"@id": "spdx:agent:Scott Scoble",
"name": "Scott Scoble",
"email": "scott@scoble.me"
},
{
"@type": "spdx:Activity",
"@id": "spdx:source:architecture_review:\"",
"name": "architecture_review - \"",
"@id": "spdx:source:architecture_review:AR-2024-0215",
"name": "architecture_review - AR-2024-0215",
"type": "architecture_review"
}
]