@gobing-ai/spur 0.3.85 → 0.3.86

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/config/pipeline-budgets.json +0 -25
  3. package/config/plugin-scripts.json +0 -5
  4. package/config/rules/boundary/env-var-hygiene.yaml +41 -0
  5. package/config/transition-shims.json +1 -1
  6. package/config/workflow-candidates.json +41 -0
  7. package/config/workflows/feature-lifecycle.yaml +4 -2
  8. package/config/workflows/feature-verification.yaml +70 -0
  9. package/config/workflows/idea-pipeline.yaml +24 -12
  10. package/config/workflows/task-pipeline.yaml +43 -12
  11. package/config/workflows/wrapup-pipeline.yaml +70 -7
  12. package/package.json +9 -9
  13. package/plugins/sp/README.md +0 -3
  14. package/plugins/sp/hooks/agent-hint.ts +5 -4
  15. package/plugins/sp/hooks/careful-guard.ts +3 -1
  16. package/plugins/sp/hooks/context-post-tool.ts +2 -1
  17. package/plugins/sp/hooks/context-session-start.ts +4 -3
  18. package/plugins/sp/hooks/context-session-stop.ts +2 -1
  19. package/plugins/sp/hooks/pi/guard-extension.ts +4 -3
  20. package/plugins/sp/hooks/task-write-guard.ts +4 -3
  21. package/plugins/sp/lib/idea-handoff.generated.mjs +260 -260
  22. package/plugins/sp/plugin.json +1 -1
  23. package/plugins/sp/scripts/daily-summary/daily-summary.mjs +13 -4
  24. package/plugins/sp/scripts/daily-summary/daily-summary.ts +6 -4
  25. package/plugins/sp/scripts/feature-sync-bounded.mjs +10 -2
  26. package/plugins/sp/scripts/feature-sync-bounded.ts +2 -1
  27. package/plugins/sp/scripts/idea-handoff.mjs +6 -1
  28. package/plugins/sp/scripts/idea-handoff.ts +4 -1
  29. package/plugins/sp/scripts/inline-pipeline-parity-check.ts +1 -1
  30. package/plugins/sp/scripts/inline-run-setup.ts +185 -2
  31. package/plugins/sp/scripts/pr-reviewing.mjs +8 -1
  32. package/plugins/sp/scripts/pr-reviewing.ts +2 -1
  33. package/plugins/sp/scripts/quality-gate.mjs +8 -1
  34. package/plugins/sp/scripts/quality-gate.ts +2 -1
  35. package/plugins/sp/scripts/surface-drift-inventory.ts +1 -4
  36. package/plugins/sp/scripts/task-evidence-precheck.ts +2 -1
  37. package/plugins/sp/scripts/task-size-precheck.ts +6 -4
  38. package/plugins/sp/scripts/verify-answer-lint.ts +2 -1
  39. package/plugins/sp/scripts/workflow-step-profile.mjs +10 -2
  40. package/plugins/sp/scripts/workflow-step-profile.ts +2 -1
  41. package/plugins/sp/scripts/wrapup-steps.mjs +8 -1
  42. package/plugins/sp/scripts/wrapup-steps.ts +2 -1
  43. package/plugins/sp/skills/spur-cli/references/workflows.md +8 -7
  44. package/plugins/sp/skills/spur-dev/references/cross-cutting.md +4 -5
  45. package/plugins/sp/skills/spur-dev/references/done-housekeeping.md +1 -1
  46. package/plugins/sp/skills/spur-dev/references/gate-checklists.md +2 -2
  47. package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +59 -1
  48. package/schemas/state-machine-workflow.schema.json +5 -0
  49. package/schemas/transition-flow-workflow.schema.json +5 -0
  50. package/spur.js +20988 -20652
  51. package/web/_astro/BoardApp.CJiqp5pS.js +1 -0
  52. package/web/_astro/{BoardApp.yW425dRZ.js → BoardApp.yBBcFXWP.js} +4 -4
  53. package/web/_astro/{TaskDetail.CGwJAinW.js → TaskDetail.DqFJbRFc.js} +1 -1
  54. package/web/_astro/{arc.B-qNXzSO.js → arc.DL-BpHoi.js} +1 -1
  55. package/web/_astro/{architectureDiagram-3BPJPVTR.Bdg-xiji.js → architectureDiagram-3BPJPVTR.9IdQYyDq.js} +1 -1
  56. package/web/_astro/{blockDiagram-GPEHLZMM.DFArg3Kp.js → blockDiagram-GPEHLZMM.BKsFCqTl.js} +1 -1
  57. package/web/_astro/{c4Diagram-AAUBKEIU.BkOLcjyx.js → c4Diagram-AAUBKEIU.DhwI0dh1.js} +1 -1
  58. package/web/_astro/channel.CX5453qQ.js +1 -0
  59. package/web/_astro/{chunk-2J33WTMH.DN3c20V4.js → chunk-2J33WTMH.B3QVmQ9S.js} +1 -1
  60. package/web/_astro/{chunk-4BX2VUAB.B64K0Ttd.js → chunk-4BX2VUAB.DBSuqs9F.js} +1 -1
  61. package/web/_astro/{chunk-55IACEB6.C-AJvNwa.js → chunk-55IACEB6.BSYTWAYD.js} +1 -1
  62. package/web/_astro/{chunk-727SXJPM.DMkr46uS.js → chunk-727SXJPM.cWVuxXfS.js} +1 -1
  63. package/web/_astro/{chunk-AQP2D5EJ.4_WGbI64.js → chunk-AQP2D5EJ.DpU_Ob3d.js} +1 -1
  64. package/web/_astro/{chunk-FMBD7UC4.cbFW_lVE.js → chunk-FMBD7UC4.BykFkyji.js} +1 -1
  65. package/web/_astro/{chunk-ND2GUHAM.CDW_-2O1.js → chunk-ND2GUHAM.DwgHlMdY.js} +1 -1
  66. package/web/_astro/{chunk-QZHKN3VN.BoYOt_yg.js → chunk-QZHKN3VN.CusXUGWM.js} +1 -1
  67. package/web/_astro/{classDiagram-4FO5ZUOK.BNT6XpHQ.js → classDiagram-4FO5ZUOK.fx0ObzkN.js} +1 -1
  68. package/web/_astro/{classDiagram-v2-Q7XG4LA2.BNT6XpHQ.js → classDiagram-v2-Q7XG4LA2.fx0ObzkN.js} +1 -1
  69. package/web/_astro/{cose-bilkent-S5V4N54A.CI1DQxR3.js → cose-bilkent-S5V4N54A.Z4HgOlsd.js} +1 -1
  70. package/web/_astro/{cynefin-OW5HDTMX.A8ARH61p.js → cynefin-OW5HDTMX.B5dIZHJu.js} +1 -1
  71. package/web/_astro/{dagre-BM42HDAG.u28ZmqwR.js → dagre-BM42HDAG.DT70Q_Yw.js} +1 -1
  72. package/web/_astro/{diagram-2AECGRRQ.Dx8JcrGc.js → diagram-2AECGRRQ.DqHA3XBF.js} +1 -1
  73. package/web/_astro/{diagram-5GNKFQAL.BXJUG9GY.js → diagram-5GNKFQAL.BmCem957.js} +1 -1
  74. package/web/_astro/{diagram-KO2AKTUF.BtlMuWqW.js → diagram-KO2AKTUF.sn0-hrE0.js} +1 -1
  75. package/web/_astro/{diagram-LMA3HP47.C4T7qaAy.js → diagram-LMA3HP47.BSHe9tVc.js} +1 -1
  76. package/web/_astro/{diagram-OG6HWLK6.D5HECE10.js → diagram-OG6HWLK6.DHIc-86k.js} +1 -1
  77. package/web/_astro/{erDiagram-TEJ5UH35.B_hMR3yw.js → erDiagram-TEJ5UH35.Bxayrs7v.js} +1 -1
  78. package/web/_astro/{flowDiagram-I6XJVG4X.BAmpcYl3.js → flowDiagram-I6XJVG4X.BkzoE_5I.js} +1 -1
  79. package/web/_astro/{ganttDiagram-6RSMTGT7.DV1bSWK-.js → ganttDiagram-6RSMTGT7.okT6CvTo.js} +1 -1
  80. package/web/_astro/{gitGraphDiagram-PVQCEYII.DxYKkKrJ.js → gitGraphDiagram-PVQCEYII.CJuYbhC7.js} +1 -1
  81. package/web/_astro/{infoDiagram-5YYISTIA.BAWY2xMb.js → infoDiagram-5YYISTIA.RqLy7nBo.js} +1 -1
  82. package/web/_astro/{ishikawaDiagram-YF4QCWOH.CZssRn6V.js → ishikawaDiagram-YF4QCWOH.BwIcoagw.js} +1 -1
  83. package/web/_astro/{journeyDiagram-JHISSGLW.C--muARd.js → journeyDiagram-JHISSGLW.UB1VbWtH.js} +1 -1
  84. package/web/_astro/{kanban-definition-UN3LZRKU.D_QCK4et.js → kanban-definition-UN3LZRKU.AaxMKpTk.js} +1 -1
  85. package/web/_astro/{linear.DzrmTtZ0.js → linear.Nv_xOUjP.js} +1 -1
  86. package/web/_astro/{mermaid.core.Da03W3iu.js → mermaid.core.Bc4LqQgX.js} +4 -4
  87. package/web/_astro/{mindmap-definition-RKZ34NQL.6cy-8hR_.js → mindmap-definition-RKZ34NQL.oKUvU_qi.js} +1 -1
  88. package/web/_astro/{pieDiagram-4H26LBE5.C5rS1pdU.js → pieDiagram-4H26LBE5.DQk0oo03.js} +1 -1
  89. package/web/_astro/{quadrantDiagram-W4KKPZXB.w56GZZ6Q.js → quadrantDiagram-W4KKPZXB.BdDjESDa.js} +1 -1
  90. package/web/_astro/{requirementDiagram-4Y6WPE33.CipX3Pwu.js → requirementDiagram-4Y6WPE33.C2u9hUeH.js} +1 -1
  91. package/web/_astro/{sankeyDiagram-5OEKKPKP.C0VVzgJm.js → sankeyDiagram-5OEKKPKP.CDEoiJST.js} +1 -1
  92. package/web/_astro/{sequenceDiagram-3UESZ5HK.BX2dUUbF.js → sequenceDiagram-3UESZ5HK.D_hT_GAT.js} +1 -1
  93. package/web/_astro/{stateDiagram-AJRCARHV.ypCdgODQ.js → stateDiagram-AJRCARHV.DI8RYG0b.js} +1 -1
  94. package/web/_astro/{stateDiagram-v2-BHNVJYJU.In0baEtg.js → stateDiagram-v2-BHNVJYJU.Bkxz4DnP.js} +1 -1
  95. package/web/_astro/{timeline-definition-PNZ67QCA.CJN4Vkvl.js → timeline-definition-PNZ67QCA.DSY-kH3-.js} +1 -1
  96. package/web/_astro/{vennDiagram-CIIHVFJN.Cf8KkIPY.js → vennDiagram-CIIHVFJN.CpaDtuGr.js} +1 -1
  97. package/web/_astro/{wardleyDiagram-YWT4CUSO.DCZBo9xw.js → wardleyDiagram-YWT4CUSO.DujQWvo8.js} +1 -1
  98. package/web/_astro/{xychartDiagram-2RQKCTM6.Cm4v_MiJ.js → xychartDiagram-2RQKCTM6.DcM5Y4b9.js} +1 -1
  99. package/web/index.html +1 -1
  100. package/config/workflows/basic.yaml +0 -146
  101. package/config/workflows/docs-pipeline.yaml +0 -350
  102. package/config/workflows/feature-dev.yaml +0 -288
  103. package/plugins/sp/scripts/feature-dev-precheck.mjs +0 -146
  104. package/plugins/sp/scripts/feature-dev-precheck.ts +0 -238
  105. package/web/_astro/BoardApp.CHenHFia.js +0 -1
  106. package/web/_astro/channel.CbDHK5UQ.js +0 -1
@@ -7,7 +7,7 @@
7
7
  "plugins": [
8
8
  {
9
9
  "name": "sp",
10
- "version": "0.3.85",
10
+ "version": "0.3.86",
11
11
  "source": "./plugins/sp"
12
12
  }
13
13
  ]
@@ -28,17 +28,6 @@
28
28
  "source": "Post-merge count (0607 R2: doc-sync + learning-capture consolidated, 2 -> 1). Real-run reading (R5): median 253s, max-sane 2319s (n=44). Budget = 60 min ceiling.",
29
29
  "decision": null
30
30
  },
31
- "docs-pipeline": {
32
- "modelQueries": 2,
33
- "wallClockMs": null,
34
- "tokenCostUsd": null,
35
- "source": "No fixture (0607 option a) and only dry/short runs recorded in history (max 1s, n=4) — wall-clock budget unenforced until a real docs-pipeline run exists. Query budget 2 matches the live workflow definition's query list ['draft','verify'] (added by task 0704; 0607 R3 recorded 1, which is stale against the definition). 0754 R6: FIX, not raise — the value was wrong against the definition, the workflow's declared query count did not change.",
36
- "decision": {
37
- "date": "2026-09-03",
38
- "wbs": "0754",
39
- "note": "align docs-pipeline.modelQueries to the live workflow definition's query list ['draft','verify']; not a measured-cost raise — the workflow's declared query count was already 2 (added by 0704); the budget was the stale side, not the workflow. Per D8 Decision 11."
40
- }
41
- },
42
31
  "pr-review": {
43
32
  "modelQueries": 0,
44
33
  "wallClockMs": null,
@@ -53,26 +42,12 @@
53
42
  "source": "Coverage entry (0826 R2): the live definition's model-query count (extractResolvedWorkflowFacts, 2026-09-11). No real-run measurement yet: wall-clock and cost are unenforced until measured, never 0.",
54
43
  "decision": null
55
44
  },
56
- "feature-dev": {
57
- "modelQueries": 2,
58
- "wallClockMs": null,
59
- "tokenCostUsd": null,
60
- "source": "Coverage entry (0826 R2): the live definition's model-query count (extractResolvedWorkflowFacts, 2026-09-11). No real-run measurement yet: wall-clock and cost are unenforced until measured, never 0.",
61
- "decision": null
62
- },
63
45
  "wayfinder-resolution": {
64
46
  "modelQueries": 2,
65
47
  "wallClockMs": null,
66
48
  "tokenCostUsd": null,
67
49
  "source": "Coverage entry (0826 R2): the live definition's model-query count (extractResolvedWorkflowFacts, 2026-09-11). No real-run measurement yet: wall-clock and cost are unenforced until measured, never 0.",
68
50
  "decision": null
69
- },
70
- "basic": {
71
- "modelQueries": 1,
72
- "wallClockMs": null,
73
- "tokenCostUsd": null,
74
- "source": "Coverage entry (0826 R2): the live definition's model-query count (extractResolvedWorkflowFacts, 2026-09-11). No real-run measurement yet: wall-clock and cost are unenforced until measured, never 0.",
75
- "decision": null
76
51
  }
77
52
  }
78
53
  }
@@ -26,11 +26,6 @@
26
26
  "contract": "standard",
27
27
  "twin": "dogfood-testing/validate-report.mjs"
28
28
  },
29
- {
30
- "rel": "feature-dev-precheck.ts",
31
- "contract": "standard",
32
- "twin": "feature-dev-precheck.mjs"
33
- },
34
29
  {
35
30
  "rel": "feature-sync-bounded.ts",
36
31
  "contract": "standard",
@@ -0,0 +1,41 @@
1
+ $schema: "@gobing-ai/spur/schemas/rule-file.schema.json"
2
+ # Environment-variable hygiene — env access funnels through the config gateway (task 0902).
3
+ #
4
+ # Contract:
5
+ # - `@gobing-ai/ts-utils` (`packages/utils/src/env.ts` in ts-libs) is the single
6
+ # implementation source; `packages/config/src/index.ts` re-exports `getEnvVar` /
7
+ # `getEnvVars` / `setEnvVar` / `removeEnvVar` / `getAppOptions` as the app-side funnel,
8
+ # and NO file in this repo touches `process.env` directly — packages/config included.
9
+ # Env flows into the app as typed config or injected `env` records (ADR-027). Runtime
10
+ # options belong in `.spur/config.yaml` `bootstrap.options` via `getAppOptions`;
11
+ # dev-only knobs belong in consts.
12
+ # - Plugin scripts/hooks import the same functions from `@gobing-ai/ts-utils`; the
13
+ # `superskill script convert` `.mjs` twins bundle them in (self-contained on any
14
+ # install target).
15
+ # - `apps/web` uses `import.meta.env` (Vite browser plane) — not process env, never matches.
16
+ # - Which variables exist and who consumes them is documented in `.env.example`.
17
+ # (The former per-var lease table moved there; the rule now enforces the funnel,
18
+ # not a file-by-var inventory.)
19
+ #
20
+ # Scope: apps/**, packages/**, scripts/**, plugins/sp/** — src AND tests. No exclusions:
21
+ # even the gateway package itself is free of direct access.
22
+ include:
23
+ - "apps/**/src/**/*.{ts,tsx}"
24
+ - "apps/**/tests/**/*.{ts,tsx}"
25
+ - "packages/**/src/**/*.{ts,tsx}"
26
+ - "packages/**/tests/**/*.{ts,tsx}"
27
+ - "scripts/**/*.ts"
28
+ - "plugins/sp/**/*.ts"
29
+ rules:
30
+ - id: env-var-hygiene
31
+ description: >
32
+ No direct `process.env` or `Bun.env` access outside the packages/config gateway.
33
+ Read via `getEnvVar` (single var, undefined-only fallback), seed/compose via
34
+ `getEnvVars()` (live record — also the sanctioned form for setting/deleting
35
+ parent→child contract markers), or take an injected `env` record parameter.
36
+ Aliasing (`const env = process.env`) is caught too — it must touch `process.env`.
37
+ severity: error
38
+ evaluator:
39
+ type: rg
40
+ config:
41
+ pattern: "process\\.env|\\bBun\\.env\\b"
@@ -1,5 +1,5 @@
1
1
  {
2
- "note": "Transition-shim manifest (task 0541, feature B2). Each entry records one compatibility path marked @transition-shim(<id>) in source. Every field is required. The gate (bun run transition-shim-check, inside `spur-check`) is two-sided: an unregistered marker fails, and a listed entry whose marker is gone fails. Emptying this file is the definition of the transition being complete (docs/04_DESIGN.md §2.5). Removal conditions must be objectively checkable against the repository, not 'when convenient'. Shims are registered by the tasks that create them (0536/0537/0538/0542).",
2
+ "note": "Transition-shim manifest (task 0541, feature B2). Each entry records one compatibility path marked @transition-shim(<id>) in source. Every field is required. The gate (bun run transition-shim-check, in the feature-scoped `spur-check-feature` pass since task 0872) is two-sided: an unregistered marker fails, and a listed entry whose marker is gone fails. Emptying this file is the definition of the transition being complete (docs/04_DESIGN.md §2.5). Removal conditions must be objectively checkable against the repository, not 'when convenient'. Shims are registered by the tasks that create them (0536/0537/0538/0542).",
3
3
  "entries": [
4
4
  {
5
5
  "id": "agent-bare-binary-name",
@@ -0,0 +1,41 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "note": "Workflow graph-change promotion candidates (task 0873, feature D62; ADR-076 amendment). A candidate is shadow-run against recorded real-run inputs and is promoted into the canonical definition or deleted by its named deadline — never left as a standing parallel <name>2.yaml. `verdict` is null while pending and is filled by `bun scripts/spur-dev.ts promotion evaluate <id>`; `promotion check` (spur-check-feature) fails any candidate still present past its deadline and any unreferenced parallel definition in config/workflows/.",
4
+ "candidates": [
5
+ {
6
+ "id": "wrapup-contract-violation-pilot-routing",
7
+ "canonical": "wrapup-pipeline",
8
+ "deadline": "2026-10-17",
9
+ "createdAt": "2026-09-17",
10
+ "rationale": "ADR-118 pilot graph change shipped by task 0871 (doc-sync contract-violation routing to the shell-only repair state). Registered by task 0876 to take the promotion decision on its first real-run measurement (R4/R5): wrapup-pipeline run fadca099-25a7-4884-a4ae-923cd0239775 (done, state-machine, definition sha256:cad7ad8b..., v4, created 2026-09-17T15:14:46Z, 14h28m after 0871 landed at 00:46:46Z - the only post-landing terminal non-dry wrapup run) routed doc-sync->learnings-append on the default edge: the doc-sync agent.run exited clean (exitCode 0) and produced its declared expectFile capture (.spur/run/fadca099-...-wrapup-learnings.md), so data.outcome was success, ContractViolationGuardRunner passed:false (packages/app/src/workflow/guards/contract-violation.ts:26), zero workflow.agent.contract-violation system_events, zero failed actions (executor-failure path not taken), no repair status file. Measured absence on real traffic - never fabricated. The change projects delta.agentRunCount=1 (unchanged): the repair edge adds no model hop (repair is a shell that records the miss; ADR-118 forbids re-dispatch), so the ADR-076 cost bar cannot reward it; its justification is ADR-118 routing correctness, evidenced here by the measured absence on the first real run. Disposition (resolve delete, or hold as the pattern-spread precedent for 0873's gate) belongs to the D62 owner before the deadline.",
11
+ "measurement": {
12
+ "workflow": "wrapup-pipeline",
13
+ "runIds": ["fadca099-25a7-4884-a4ae-923cd0239775"]
14
+ },
15
+ "delta": {
16
+ "agentRunCount": 1
17
+ },
18
+ "verdict": {
19
+ "decision": "delete",
20
+ "evaluatedAt": "2026-09-17T15:33:27.274Z",
21
+ "agentRunCount": {
22
+ "runs": 1,
23
+ "mean": 1,
24
+ "median": 1,
25
+ "min": 1,
26
+ "max": 1
27
+ },
28
+ "agentRunDurationMs": {
29
+ "runs": 1,
30
+ "mean": 505937,
31
+ "median": 505937,
32
+ "min": 505937,
33
+ "max": 505937
34
+ },
35
+ "candidateAgentRunCount": 1,
36
+ "canonicalAgentRunCount": 1,
37
+ "reason": "candidate projects 1 agent.run action(s), not fewer than the canonical wrapup-pipeline count of 1 (1 real run(s), median 1 agent.run action(s)/run, median 505937 ms/run) — ADR-076 rejected a graph adding a model hop"
38
+ }
39
+ }
40
+ ]
41
+ }
@@ -62,11 +62,13 @@ transitions:
62
62
  - from: verifying
63
63
  to: done
64
64
  description: >
65
- Feature verified — complete. Runs strict check (AC validated, traceability clean).
65
+ Feature verified — complete. Requires the feature-scoped verification pass
66
+ (ADR-119) to have recorded PASS, then strict check (AC validated,
67
+ traceability clean).
66
68
  guard:
67
69
  kind: shell
68
70
  options:
69
- command: '$spurBin feature check $featureId --strict --as done'
71
+ command: 'test "$(cat .spur/run/$featureId-feature-verification.status 2>/dev/null)" = PASS && $spurBin feature check $featureId --strict --as done'
70
72
 
71
73
  # Rework: verifying → active (mandatory History entry)
72
74
  - from: verifying
@@ -0,0 +1,70 @@
1
+ # Feature-scoped verification pass (ADR-119, feature D62, task 0872).
2
+ #
3
+ # Owns a lifecycle boundary no per-task graph owns: the repo-wide checks whose
4
+ # invariant spans the repository rather than a single task's diff — corpus
5
+ # consistency, contract baselines, dependency/schema drift, the frozen History
6
+ # surface, and the repo-wide test set. They run once per feature against a
7
+ # settled tree, deliberately the slow pass, and `feature-lifecycle`'s
8
+ # verifying→done guard refuses to complete the feature until this pass records
9
+ # PASS (ADR-119 consequence: a feature is not done until it passes).
10
+ #
11
+ # Run: spur workflow run feature-verification.yaml --vars '{"featureId":"D62"}'
12
+ #
13
+ # Shape: verify -> done | failed. The shell action writes the verdict to
14
+ # `.spur/run/<featureId>-feature-verification.status` and always exits 0; the
15
+ # transition guard reads the status so a missing, corrupt or FAIL verdict routes
16
+ # to `failed` (fail-closed), never a silent PASS.
17
+ #
18
+ # Reliability (aligned with task-pipeline / ADR-043): no agent.run nodes; the
19
+ # verification command is a trusted config var executed via `sh -c` (same
20
+ # surface as task-pipeline's qualityGateCmd — never interpolate untrusted input).
21
+ "$schema": "@gobing-ai/spur/schemas/state-machine-workflow.schema.json"
22
+ kind: state-machine
23
+ name: feature-verification
24
+ version: "1"
25
+ description: "Feature-scoped verification pass (ADR-119): runs the repo-wide check set once per feature against a settled tree and records PASS/FAIL."
26
+ iterationBound: 2
27
+ initialState: verify
28
+ terminalStates:
29
+ - done
30
+ - failed
31
+ failureStates:
32
+ - failed
33
+ vars:
34
+ featureId: "X"
35
+ spurBin: "spur"
36
+ verificationCmd: "bun run spur-check-feature"
37
+
38
+ states:
39
+ - id: verify
40
+ description: >
41
+ Run the repo-wide check set, record the verdict, always exit 0.
42
+ onEnter:
43
+ - kind: shell
44
+ options:
45
+ command: >-
46
+ mkdir -p .spur/run;
47
+ sh -c "$verificationCmd" > ".spur/run/$featureId-feature-verification.log" 2>&1
48
+ && printf 'PASS\n' > ".spur/run/$featureId-feature-verification.status"
49
+ || printf 'FAIL\n' > ".spur/run/$featureId-feature-verification.status";
50
+ exit 0
51
+
52
+ - id: done
53
+ description: Terminal — repo-wide checks passed.
54
+
55
+ - id: failed
56
+ description: Terminal — repo-wide checks failed or the verdict is missing/corrupt.
57
+
58
+ transitions:
59
+ - from: verify
60
+ to: done
61
+ description: Repo-wide checks passed — the feature-scoped verification pass records PASS.
62
+ guard:
63
+ kind: shell
64
+ options:
65
+ command: 'test "$(cat .spur/run/$featureId-feature-verification.status 2>/dev/null)" = PASS'
66
+ - from: verify
67
+ to: failed
68
+ description: Repo-wide checks failed (or the verdict is missing/corrupt) — stop at failed.
69
+ guard:
70
+ kind: always
@@ -568,12 +568,14 @@ transitions:
568
568
  - from: ac-generate
569
569
  to: system-design
570
570
  description: "profile=auto, check passed, design route — run system design."
571
- # (warn) 4 test segments: profile gate + captured status + route signal jointly own the
571
+ # (warn) 5 commands (named status capture + 4 conditions): profile gate + captured status + route signal jointly own the
572
572
  # route; guards never re-run the CLI (0769), so there is nothing smaller to extract.
573
573
  guard:
574
574
  kind: shell
575
575
  options:
576
- command: 'test "$profile" = auto && test "$(cat .spur/run/$__runId-idea-ac-check.status 2>/dev/null)" = PASS && test "$design" = auto && test "$(jq -r .needs_design .spur/run/$__runId-idea-needs-design.json 2>/dev/null)" != false'
576
+ command: >-
577
+ ac_status="$(cat .spur/run/$__runId-idea-ac-check.status 2>/dev/null)";
578
+ test "$profile" = auto && test "$ac_status" = PASS && test "$design" = auto && test "$(jq -r .needs_design .spur/run/$__runId-idea-needs-design.json 2>/dev/null)" != false
577
579
  # Auto-skip 2: pass + skip-design route → decompose
578
580
  - from: ac-generate
579
581
  to: decompose
@@ -588,22 +590,26 @@ transitions:
588
590
  - from: ac-generate
589
591
  to: ac-generate
590
592
  description: "profile=auto, check failed, retry cap not reached — re-run ac-generate."
591
- # (warn) 4 test segments: profile gate + captured status + captured retry count; the
593
+ # (warn) 5 commands (named status capture + 4 conditions): profile gate + captured status + captured retry count; the
592
594
  # retry loop is the smallest honest formulation of cap<3 routing (0769).
593
595
  guard:
594
596
  kind: shell
595
597
  options:
596
- command: 'test "$profile" = auto && test "$(cat .spur/run/$__runId-idea-ac-check.status 2>/dev/null)" != PASS && test "$(cat .spur/run/$__runId-idea-ac-retry-count 2>/dev/null || echo 0)" -lt 3'
598
+ command: >-
599
+ ac_status="$(cat .spur/run/$__runId-idea-ac-check.status 2>/dev/null)";
600
+ test "$profile" = auto && test "$ac_status" != PASS && test "$(cat .spur/run/$__runId-idea-ac-retry-count 2>/dev/null || echo 0)" -lt 3
597
601
  # Auto-skip 4: check failed, retry cap reached → escalate to failed
598
602
  - from: ac-generate
599
603
  to: failed
600
604
  description: "profile=auto, check failed after 3 retries — escalate to failed."
601
- # (warn) 4 test segments: mirror of the retry guard with cap>=3; keeping escalation and
605
+ # (warn) 5 commands (named status capture + 4 conditions): mirror of the retry guard with cap>=3; keeping escalation and
602
606
  # retry as one test-chain pair makes the cap boundary auditable in the diff (0769).
603
607
  guard:
604
608
  kind: shell
605
609
  options:
606
- command: 'test "$profile" = auto && test "$(cat .spur/run/$__runId-idea-ac-check.status 2>/dev/null)" != PASS && test "$(cat .spur/run/$__runId-idea-ac-retry-count 2>/dev/null || echo 0)" -ge 3'
610
+ command: >-
611
+ ac_status="$(cat .spur/run/$__runId-idea-ac-check.status 2>/dev/null)";
612
+ test "$profile" = auto && test "$ac_status" != PASS && test "$(cat .spur/run/$__runId-idea-ac-retry-count 2>/dev/null || echo 0)" -ge 3
607
613
  # Interactive fallback: enter feature-check HITL gate
608
614
  - from: ac-generate
609
615
  to: feature-check
@@ -616,12 +622,14 @@ transitions:
616
622
  - from: feature-check
617
623
  to: system-design
618
624
  description: Feature check passed, design route — run system design.
619
- # (warn) 4 test segments: HITL answer + captured status + design route; same shape as the
625
+ # (warn) 5 commands (named status capture + 4 conditions): HITL answer + captured status + design route; same shape as the
620
626
  # ac-generate auto-skips, reading the same captured signal files (0769).
621
627
  guard:
622
628
  kind: shell
623
629
  options:
624
- command: 'test "$__hitlAnswer" = yes && test "$(cat .spur/run/$__runId-idea-ac-check.status 2>/dev/null)" = PASS && test "$design" = auto && test "$(jq -r .needs_design .spur/run/$__runId-idea-needs-design.json 2>/dev/null)" != false'
630
+ command: >-
631
+ ac_status="$(cat .spur/run/$__runId-idea-ac-check.status 2>/dev/null)";
632
+ test "$__hitlAnswer" = yes && test "$ac_status" = PASS && test "$design" = auto && test "$(jq -r .needs_design .spur/run/$__runId-idea-needs-design.json 2>/dev/null)" != false
625
633
  - from: feature-check
626
634
  to: decompose
627
635
  description: Feature check passed, skip-design route — go directly to decompose.
@@ -634,20 +642,24 @@ transitions:
634
642
  - from: feature-check
635
643
  to: ac-generate
636
644
  description: "Feature check failed — revise AC (retry cap: 3)."
637
- # (warn) 4 test segments: HITL reject/failed-status OR-pair + captured retry count; the
645
+ # (warn) 5 commands (named status capture + 4 conditions): HITL reject/failed-status OR-pair + captured retry count; the
638
646
  # interactive retry mirror of the ac-generate cap<3 guard (0769).
639
647
  guard:
640
648
  kind: shell
641
649
  options:
642
- command: '(test "$__hitlAnswer" = no || test "$(cat .spur/run/$__runId-idea-ac-check.status 2>/dev/null)" != PASS) && test "$(cat .spur/run/$__runId-idea-ac-retry-count 2>/dev/null || echo 0)" -lt 3'
650
+ command: >-
651
+ ac_status="$(cat .spur/run/$__runId-idea-ac-check.status 2>/dev/null)";
652
+ (test "$__hitlAnswer" = no || test "$ac_status" != PASS) && test "$(cat .spur/run/$__runId-idea-ac-retry-count 2>/dev/null || echo 0)" -lt 3
643
653
  - from: feature-check
644
654
  to: failed
645
655
  description: Feature check failed after 3 retries — escalate to failed.
646
- # (warn) 4 test segments: mirror of the revise guard with cap>=3 (0769).
656
+ # (warn) 5 commands (named status capture + 4 conditions): mirror of the revise guard with cap>=3 (0769).
647
657
  guard:
648
658
  kind: shell
649
659
  options:
650
- command: '(test "$__hitlAnswer" = no || test "$(cat .spur/run/$__runId-idea-ac-check.status 2>/dev/null)" != PASS) && test "$(cat .spur/run/$__runId-idea-ac-retry-count 2>/dev/null || echo 0)" -ge 3'
660
+ command: >-
661
+ ac_status="$(cat .spur/run/$__runId-idea-ac-check.status 2>/dev/null)";
662
+ (test "$__hitlAnswer" = no || test "$ac_status" != PASS) && test "$(cat .spur/run/$__runId-idea-ac-retry-count 2>/dev/null || echo 0)" -ge 3
651
663
  - from: feature-check
652
664
  to: cancelled
653
665
  description: Operator cancelled the feature-check gate.
@@ -603,10 +603,14 @@ transitions:
603
603
  - from: precheck
604
604
  to: implement
605
605
  description: Deterministic size, evidence, and task checks are green — begin implementation.
606
+ # (warn) 5 commands: named size/evidence status reads + task check (legibility, 0874).
606
607
  guard:
607
608
  kind: shell
608
609
  options:
609
- command: 'test "$(cat .spur/run/$wbs-precheck-size.status 2>/dev/null)" = PASS && test "$(cat .spur/run/$wbs-precheck-evidence.status 2>/dev/null)" = PASS && $spurBin task check $wbs'
610
+ command: >-
611
+ size_status="$(cat .spur/run/$wbs-precheck-size.status 2>/dev/null)";
612
+ evidence_status="$(cat .spur/run/$wbs-precheck-evidence.status 2>/dev/null)";
613
+ test "$size_status" = PASS && test "$evidence_status" = PASS && $spurBin task check $wbs
610
614
  - from: precheck
611
615
  to: failed
612
616
  description: Size and/or task check failed — stop before implement.
@@ -626,14 +630,18 @@ transitions:
626
630
  guard:
627
631
  kind: shell
628
632
  options:
629
- command: 'test "$(cat .spur/run/$wbs-test-gate.status 2>/dev/null)" = PASS && test "$mode" = fast'
633
+ command: >-
634
+ gate_status="$(cat .spur/run/$wbs-test-gate.status 2>/dev/null)";
635
+ test "$gate_status" = PASS && test "$mode" = fast
630
636
  - from: test
631
637
  to: review
632
638
  description: Quality gate already green and safety mode — proceed to review.
633
639
  guard:
634
640
  kind: shell
635
641
  options:
636
- command: 'test "$(cat .spur/run/$wbs-test-gate.status 2>/dev/null)" = PASS && test "$mode" != fast'
642
+ command: >-
643
+ gate_status="$(cat .spur/run/$wbs-test-gate.status 2>/dev/null)";
644
+ test "$gate_status" = PASS && test "$mode" != fast
637
645
  - from: test
638
646
  to: test-fix
639
647
  description: Quality gate red — start bounded fixall loop.
@@ -659,28 +667,40 @@ transitions:
659
667
  guard:
660
668
  kind: shell
661
669
  options:
662
- command: 'test "$(cat .spur/run/$wbs-test-gate.status 2>/dev/null)" = PASS && test "$mode" = fast'
670
+ command: >-
671
+ gate_status="$(cat .spur/run/$wbs-test-gate.status 2>/dev/null)";
672
+ test "$gate_status" = PASS && test "$mode" = fast
663
673
  - from: test-recheck
664
674
  to: review
665
675
  description: Quality gate green after fixall and safety mode — proceed to review.
666
676
  guard:
667
677
  kind: shell
668
678
  options:
669
- command: 'test "$(cat .spur/run/$wbs-test-gate.status 2>/dev/null)" = PASS && test "$mode" != fast'
679
+ command: >-
680
+ gate_status="$(cat .spur/run/$wbs-test-gate.status 2>/dev/null)";
681
+ test "$gate_status" = PASS && test "$mode" != fast
670
682
  - from: test-recheck
671
683
  to: test-fix
672
684
  description: Still red and under qualityGateMaxFixAttempts — another fixall hop.
685
+ # (warn) 5 commands: named gate status + fix attempts (legibility, 0874).
673
686
  guard:
674
687
  kind: shell
675
688
  options:
676
- command: 'test "$(cat .spur/run/$wbs-test-gate.status 2>/dev/null)" = FAIL && test "$(cat .spur/run/$wbs-test-fix-attempt 2>/dev/null || echo 0)" -lt "$qualityGateMaxFixAttempts"'
689
+ command: >-
690
+ gate_status="$(cat .spur/run/$wbs-test-gate.status 2>/dev/null)";
691
+ fix_attempts="$(cat .spur/run/$wbs-test-fix-attempt 2>/dev/null || echo 0)";
692
+ test "$gate_status" = FAIL && test "$fix_attempts" -lt "$qualityGateMaxFixAttempts"
677
693
  - from: test-recheck
678
694
  to: failed
679
695
  description: Still red after max fixall attempts — stop at failed (not silent abort).
696
+ # (warn) 5 commands: named gate status + fix attempts (legibility, 0874).
680
697
  guard:
681
698
  kind: shell
682
699
  options:
683
- command: 'test "$(cat .spur/run/$wbs-test-gate.status 2>/dev/null)" = FAIL && test "$(cat .spur/run/$wbs-test-fix-attempt 2>/dev/null || echo 0)" -ge "$qualityGateMaxFixAttempts"'
700
+ command: >-
701
+ gate_status="$(cat .spur/run/$wbs-test-gate.status 2>/dev/null)";
702
+ fix_attempts="$(cat .spur/run/$wbs-test-fix-attempt 2>/dev/null || echo 0)";
703
+ test "$gate_status" = FAIL && test "$fix_attempts" -ge "$qualityGateMaxFixAttempts"
684
704
  # Defense: corrupt recheck status — failed, not review.
685
705
  - from: test-recheck
686
706
  to: failed
@@ -748,7 +768,16 @@ transitions:
748
768
  kind: shell
749
769
  options:
750
770
  command: >-
751
- jq -e --arg d "$proofDigest" --arg r "$__runId" --arg dd "$__definitionDigest" '.verdict == "PASS" and (.proof.digest // "") == $d and (.proof.stages.qualityGate.digest // "") == $d and (.proof.stages.review.digest // "") == $d and (.proof.stages.review.status // "") == "completed" and (.proof.stages.verification.digest // "") == $d and (.proof.runId // "") == $r and (.proof.definitionDigest // "") == $dd' ".spur/run/$wbs-verdict.json" >/dev/null 2>&1
771
+ jq -e --arg d "$proofDigest" --arg r "$__runId" --arg dd "$__definitionDigest" '
772
+ .verdict == "PASS"
773
+ and (.proof.digest // "") == $d
774
+ and (.proof.stages.qualityGate.digest // "") == $d
775
+ and (.proof.stages.review.digest // "") == $d
776
+ and (.proof.stages.review.status // "") == "completed"
777
+ and (.proof.stages.verification.digest // "") == $d
778
+ and (.proof.runId // "") == $r
779
+ and (.proof.definitionDigest // "") == $dd
780
+ ' ".spur/run/$wbs-verdict.json" >/dev/null 2>&1
752
781
  - from: verify
753
782
  to: test-fix
754
783
  description: >-
@@ -760,8 +789,8 @@ transitions:
760
789
  kind: shell
761
790
  options:
762
791
  command: >-
763
- V="$(jq -r .verdict .spur/run/$wbs-verdict.json 2>/dev/null)";
764
- test -n "$V" && test "$V" != PASS &&
792
+ verdict="$(jq -r .verdict .spur/run/$wbs-verdict.json 2>/dev/null)";
793
+ test -n "$verdict" && test "$verdict" != PASS &&
765
794
  test "$(cat .spur/run/$wbs-test-fix-attempt 2>/dev/null || echo 0)" -lt "$qualityGateMaxFixAttempts"
766
795
  - from: verify
767
796
  to: failed
@@ -778,6 +807,7 @@ transitions:
778
807
  - from: record
779
808
  to: done
780
809
  description: Task check passed and the verdict proof block still names the captured digest — certify done.
810
+ # (warn) 5 commands: named verdict + proof digest reads after the task check (legibility, 0874).
781
811
  guard:
782
812
  kind: shell
783
813
  options:
@@ -788,8 +818,9 @@ transitions:
788
818
  # one shell line.
789
819
  command: >-
790
820
  $spurBin task check $wbs --as done &&
791
- test "$(jq -r .verdict .spur/run/$wbs-verdict.json 2>/dev/null)" = PASS &&
792
- test "$(jq -r '.proof.digest // ""' .spur/run/$wbs-verdict.json 2>/dev/null)" = "$proofDigest"
821
+ verdict="$(jq -r .verdict .spur/run/$wbs-verdict.json 2>/dev/null)" &&
822
+ proof_digest="$(jq -r '.proof.digest // ""' .spur/run/$wbs-verdict.json 2>/dev/null)" &&
823
+ test "$verdict" = PASS && test "$proof_digest" = "$proofDigest"
793
824
  - from: record
794
825
  to: failed
795
826
  description: Task check failed or proof evidence missing/malformed/mismatched — block before done.
@@ -13,10 +13,12 @@
13
13
  # pauses,
14
14
  # even under --auto (Iron Law #6: irreversible action -> surface to human).
15
15
  #
16
- # Shape: start -> task-resolve -> doc-sync -> metrics-record
16
+ # Shape: start -> task-resolve -> doc-sync -> learnings-append -> metrics-record
17
17
  # -> feature-transition (conditional: if vars.feature set)
18
18
  # -> branch-cleanup (conditional: if vars.merge=true)
19
19
  # -> done
20
+ # doc-sync routes a contract violation to `repair` (cheap, no
21
+ # re-dispatch — ADR-118 pilot) and an executor failure to `failed`;
20
22
  # task-resolve with a VALIDATED empty list short-circuits to `skipped`;
21
23
  # invalid wrap input, an unresolved/non-completed task, a failed metrics
22
24
  # capture, a failed required sync, or a failed feature gate routes to
@@ -72,7 +74,7 @@
72
74
  "$schema": "@gobing-ai/spur/schemas/state-machine-workflow.schema.json"
73
75
  kind: state-machine
74
76
  name: wrapup-pipeline
75
- version: "3"
77
+ version: "4"
76
78
  description: "Post-execution wrap-up: doc-sync (doc drift + learning capture), metrics, feature-transition, branch-cleanup"
77
79
  iterationBound: 10
78
80
  initialState: start
@@ -168,13 +170,16 @@ states:
168
170
  learnings (task 0607 R2: two adjacent agent.run hops merged, count 2 -> 1;
169
171
  no operator-decision pause or verdict boundary sits between them). No dedicated
170
172
  slash command yet — free-form skill pointer until a /sp:doc-evolve command
171
- exists (ADR-043 residual). Capture+shell decoupling preserved: expectFile gates
172
- a non-empty capture before the append; append is best-effort soft (empty capture
173
- skips without aborting wrap-up).
173
+ exists (ADR-043 residual). This is the expensive stage; a contract violation
174
+ (a clean exit that missed its declared answerFile/expectFile post-condition)
175
+ routes to the cheap `repair` edge instead of a full re-dispatch (ADR-118
176
+ pilot, 0871) — `onError: continue` lets the transition guards read the
177
+ agent's result instead of halting the run.
174
178
  onEnter:
175
179
  # (warn) free-form prompt: no /sp:doc-evolve command surface yet (ADR-043
176
180
  # residual, 0607 R2 one-query merge); capture is bounded by expectFile.
177
181
  - kind: agent.run
182
+ onError: continue
178
183
  options:
179
184
  agent: ${vars.agent}
180
185
  input: >-
@@ -192,6 +197,13 @@ states:
192
197
  answerFile: .spur/run/${vars.__runId}-wrapup-learnings.md
193
198
  expectFile: .spur/run/${vars.__runId}-wrapup-learnings.md
194
199
  timeoutMs: ${vars.stepTimeoutMs}
200
+
201
+ - id: learnings-append
202
+ description: >
203
+ Best-effort soft append of the captured learnings to .spur/memory/learnings.md
204
+ (0607 R2): an empty capture skips without aborting wrap-up. Runs only after
205
+ doc-sync's contract held; a contract violation never reaches this state.
206
+ onEnter:
195
207
  # (warn) learnings append is intentionally soft (empty capture skips
196
208
  # without aborting wrap-up, 0607 R2).
197
209
  - kind: shell
@@ -207,6 +219,21 @@ states:
207
219
  fi &&
208
220
  exit 0
209
221
 
222
+ - id: repair
223
+ description: >
224
+ Contract-violation repair (ADR-118 pilot, 0871): doc-sync's agent.run missed
225
+ its declared post-condition after a clean exit, so wrap-up does NOT re-dispatch
226
+ the expensive agent on this attempt. The miss is recorded to a run-scoped
227
+ repair status and wrap-up proceeds to metrics-record — the run log and action
228
+ trace already name the violated contract and the observed value.
229
+ onEnter:
230
+ - kind: shell
231
+ options:
232
+ command: >-
233
+ mkdir -p .spur/run &&
234
+ printf 'contract-violation: doc-sync learnings capture missed its declared contract — repair skipped re-dispatch (ADR-118 pilot)\n' > ".spur/run/$__runId-wrapup-repair.status" &&
235
+ exit 0
236
+
210
237
  - id: metrics-record
211
238
  description: >
212
239
  Append one JSONL row per task to .spur/memory/wrapup-metrics.jsonl deterministically.
@@ -354,10 +381,46 @@ transitions:
354
381
  guard:
355
382
  kind: always
356
383
 
357
- # ── linear body: doc-sync -> metrics-record ──
384
+ # ── doc-sync: contract-first routing (ADR-118 pilot, 0871) ──
385
+ # Declaration order matters: the contract-violation edge is tried first, then
386
+ # success (action-ok), then the executor-failure defense (always) — a failed
387
+ # agent.run reaches these guards because doc-sync's agent.run declares
388
+ # onError: continue.
358
389
  - from: doc-sync
390
+ to: repair
391
+ description: >
392
+ Contract violation (ADR-118): the agent exited 0 but missed its declared
393
+ post-condition. Route to the cheap repair edge — never re-dispatch the
394
+ full agent.run on this attempt.
395
+ trigger: contract-violation
396
+ guard:
397
+ kind: contract-violation
398
+ - from: doc-sync
399
+ to: learnings-append
400
+ description: Doc drift repair + learning capture succeeded — append learnings.
401
+ guard:
402
+ kind: action-ok
403
+ - from: doc-sync
404
+ to: failed
405
+ description: >
406
+ Executor failure (non-zero exit, signal, or dispatch error) — keep the
407
+ existing fail semantics; a contract violation never falls through here
408
+ because the contract-violation edge is declared first.
409
+ trigger: executor-failure
410
+ guard:
411
+ kind: always
412
+
413
+ # ── linear body: learnings-append -> metrics-record ──
414
+ - from: learnings-append
415
+ to: metrics-record
416
+ description: Learning capture appended (or soft-skipped) — record metrics.
417
+ guard:
418
+ kind: always
419
+
420
+ # ── repair: cheap path, no re-dispatch -> metrics-record ──
421
+ - from: repair
359
422
  to: metrics-record
360
- description: Doc drift repair + learning capture complete — record metrics.
423
+ description: Contract-violation repair recorded — proceed to metrics without re-dispatch.
361
424
  guard:
362
425
  kind: always
363
426
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gobing-ai/spur",
3
- "version": "0.3.85",
3
+ "version": "0.3.86",
4
4
  "description": "Spur CLI — local-first harness for mainstream coding agents: constraint checking, workflow orchestration, agent health, and history analytics. Bun-native; exposes the `spur` command.",
5
5
  "keywords": [
6
6
  "spur",
@@ -53,14 +53,14 @@
53
53
  },
54
54
  "devDependencies": {
55
55
  "@commander-js/extra-typings": "^14.0.0",
56
- "@gobing-ai/ts-db": "^0.4.66",
57
- "@gobing-ai/ts-ai-runner": "^0.4.66",
58
- "@gobing-ai/ts-dual-workflow-engine": "^0.4.66",
59
- "@gobing-ai/ts-infra": "^0.4.66",
60
- "@gobing-ai/ts-llm-jsonl-importer": "^0.4.66",
61
- "@gobing-ai/ts-rule-engine": "^0.4.66",
62
- "@gobing-ai/ts-runtime": "^0.4.66",
63
- "@gobing-ai/ts-utils": "^0.4.66",
56
+ "@gobing-ai/ts-db": "^0.4.67",
57
+ "@gobing-ai/ts-ai-runner": "^0.4.67",
58
+ "@gobing-ai/ts-dual-workflow-engine": "^0.4.67",
59
+ "@gobing-ai/ts-infra": "^0.4.67",
60
+ "@gobing-ai/ts-llm-jsonl-importer": "^0.4.67",
61
+ "@gobing-ai/ts-rule-engine": "^0.4.67",
62
+ "@gobing-ai/ts-runtime": "^0.4.67",
63
+ "@gobing-ai/ts-utils": "^0.4.67",
64
64
  "@types/bun": "1.3.14",
65
65
  "@types/figlet": "^1.7.0",
66
66
  "@types/node-notifier": "8.0.5",