@gobing-ai/spur 0.3.93 → 0.3.95
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.
- package/.claude-plugin/marketplace.json +1 -1
- package/README.md +42 -0
- package/board/index.d.ts +38 -0
- package/config/plugin-scripts.json +5 -0
- package/config/rules/boundary/test-subpath-boundary.yaml +48 -0
- package/config/rules/strict/runtime-boundaries.yaml +2 -1
- package/config/rules/structure/protected-files.yaml +4 -0
- package/config/workflows/feature-verification.yaml +7 -4
- package/config/workflows/idea-pipeline.yaml +10 -4
- package/config/workflows/task-pipeline.yaml +71 -52
- package/config/workflows/wrapup-pipeline.yaml +92 -17
- package/package.json +15 -11
- package/plugins/sp/README.md +1 -1
- package/plugins/sp/commands/dev-review-session.md +4 -4
- package/plugins/sp/commands/dev-review.md +16 -5
- package/plugins/sp/commands/dev-verify.md +7 -4
- package/plugins/sp/commands/dev-verifyall.md +4 -3
- package/plugins/sp/commands/dev-wrap.md +1 -1
- package/plugins/sp/hooks/context-post-tool.ts +2 -2
- package/plugins/sp/hooks/context-session-start.ts +2 -1
- package/plugins/sp/hooks/context-session-stop.ts +22 -14
- package/plugins/sp/hooks/pi/guard-extension.ts +112 -172
- package/plugins/sp/lib/idea-handoff.generated.mjs +2 -2
- package/plugins/sp/lib/inline-run.generated.d.mts +4 -2
- package/plugins/sp/lib/inline-run.generated.mjs +35 -14
- package/plugins/sp/plugin.json +1 -1
- package/plugins/sp/scripts/daily-summary/daily-summary.mjs +3 -3
- package/plugins/sp/scripts/daily-summary/daily-summary.ts +3 -3
- package/plugins/sp/scripts/dogfood-testing/detect-pipeline-driving.mjs +2 -0
- package/plugins/sp/scripts/dogfood-testing/detect-pipeline-driving.ts +1 -0
- package/plugins/sp/scripts/dogfood-testing/validate-report.mjs +9 -7
- package/plugins/sp/scripts/dogfood-testing/validate-report.ts +8 -7
- package/plugins/sp/scripts/feature-sync-bounded.mjs +5 -2
- package/plugins/sp/scripts/feature-sync-bounded.ts +3 -1
- package/plugins/sp/scripts/feature-verification-steps.ts +6 -6
- package/plugins/sp/scripts/history-anatomy-cache.mjs +3 -3
- package/plugins/sp/scripts/history-anatomy-cache.ts +4 -4
- package/plugins/sp/scripts/inline-run-setup.mjs +60 -12
- package/plugins/sp/scripts/inline-run-setup.ts +122 -15
- package/plugins/sp/scripts/pr-reviewing.mjs +2 -0
- package/plugins/sp/scripts/pr-reviewing.ts +1 -0
- package/plugins/sp/scripts/quality-gate.mjs +15 -6
- package/plugins/sp/scripts/quality-gate.ts +30 -9
- package/plugins/sp/scripts/residual-scan.mjs +4 -4
- package/plugins/sp/scripts/residual-scan.ts +5 -4
- package/plugins/sp/scripts/script-contract-check.ts +175 -46
- package/plugins/sp/scripts/script-root.mjs +125 -0
- package/plugins/sp/scripts/script-root.ts +195 -0
- package/plugins/sp/scripts/stage-registry-adapter.ts +1 -1
- package/plugins/sp/scripts/task-evidence-precheck.ts +4 -2
- package/plugins/sp/scripts/task-size-precheck.ts +3 -1
- package/plugins/sp/scripts/validate-commands.ts +12 -12
- package/plugins/sp/scripts/validate-flag-contracts.ts +42 -30
- package/plugins/sp/scripts/verify-answer-lint.ts +3 -1
- package/plugins/sp/scripts/workflow-step-profile.mjs +5 -2
- package/plugins/sp/scripts/workflow-step-profile.ts +3 -1
- package/plugins/sp/scripts/wrapup-drift-probe.mjs +5 -2
- package/plugins/sp/scripts/wrapup-drift-probe.ts +4 -2
- package/plugins/sp/scripts/wrapup-steps.mjs +32 -8
- package/plugins/sp/scripts/wrapup-steps.ts +56 -10
- package/plugins/sp/skills/code-verification/SKILL.md +12 -7
- package/plugins/sp/skills/code-verification/references/verdict-schema.md +11 -0
- package/plugins/sp/skills/functional-review/SKILL.md +1 -1
- package/plugins/sp/skills/next-router/references/routing-table.md +1 -1
- package/plugins/sp/skills/session-review/SKILL.md +11 -9
- package/plugins/sp/skills/spur-cli/references/tasks/verbs.md +9 -1
- package/plugins/sp/skills/spur-dev/references/dev-operations.md +8 -2
- package/plugins/sp/skills/spur-dev/references/execution-batch.md +65 -17
- package/plugins/sp/skills/spur-dev/references/flag-glossary.md +16 -3
- package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +22 -5
- package/plugins/sp/tsconfig.json +8 -0
- package/spur.js +20934 -21087
- package/web/_astro/{BoardApp.CerSBgis.js → BoardApp.BxJuwD7I.js} +151 -152
- package/web/_astro/BoardApp.Cpxntzad.js +1 -0
- package/web/_astro/TaskDetail.C5bW4WGV.js +1 -0
- package/web/_astro/_commonjsHelpers.CqkleIqs.js +1 -0
- package/web/_astro/arc.CyjRvNMY.js +1 -0
- package/web/_astro/architectureDiagram-3BPJPVTR.B4lWRzJA.js +36 -0
- package/web/_astro/{blockDiagram-GPEHLZMM.DXVIiv0p.js → blockDiagram-GPEHLZMM.Be38USQ2.js} +1 -1
- package/web/_astro/board-facade-react-dom-client.B2U5wMvk.js +1 -0
- package/web/_astro/board-facade-react-dom.Cd2MuMhF.js +1 -0
- package/web/_astro/board-facade-react-jsx-dev-runtime.B_L3JzfC.js +1 -0
- package/web/_astro/board-facade-react-jsx-runtime.BY2yfHRi.js +1 -0
- package/web/_astro/board-facade-react-router-dom.Dy5pjzOw.js +1 -0
- package/web/_astro/board-facade-react-router.DjjqU27_.js +1 -0
- package/web/_astro/board-facade-react.Dgf4GRyj.js +1 -0
- package/web/_astro/{c4Diagram-AAUBKEIU.BbF_zCxW.js → c4Diagram-AAUBKEIU.DT9Fj5Qx.js} +1 -1
- package/web/_astro/channel.CI6N_tCg.js +1 -0
- package/web/_astro/{chunk-2J33WTMH.CAgQHpPC.js → chunk-2J33WTMH.SeSBWLg5.js} +1 -1
- package/web/_astro/{chunk-4BX2VUAB.BN-5tpw4.js → chunk-4BX2VUAB.DoO4VE14.js} +1 -1
- package/web/_astro/{chunk-55IACEB6.CnPkEEr0.js → chunk-55IACEB6.DrmTFA53.js} +1 -1
- package/web/_astro/{chunk-727SXJPM.BQzQeMVm.js → chunk-727SXJPM.Bi-TUb_V.js} +4 -4
- package/web/_astro/{chunk-AQP2D5EJ.B6xNyDnL.js → chunk-AQP2D5EJ.B-xp8Uhi.js} +1 -1
- package/web/_astro/{chunk-FMBD7UC4.C7f9Ih78.js → chunk-FMBD7UC4.DGWrDnUU.js} +1 -1
- package/web/_astro/chunk-JMJ3UQ3L.BQJEJHu4.js +34 -0
- package/web/_astro/{chunk-ND2GUHAM.CNV1dFXT.js → chunk-ND2GUHAM._BagvPDy.js} +1 -1
- package/web/_astro/{chunk-QZHKN3VN.Cudn2TkJ.js → chunk-QZHKN3VN.VOboYWQ0.js} +1 -1
- package/web/_astro/chunk-YNUBSHFH.CxeAygfi.js +7 -0
- package/web/_astro/{classDiagram-4FO5ZUOK.D1NwP50q.js → classDiagram-4FO5ZUOK.D_apfHS7.js} +1 -1
- package/web/_astro/{classDiagram-v2-Q7XG4LA2.D1NwP50q.js → classDiagram-v2-Q7XG4LA2.D_apfHS7.js} +1 -1
- package/web/_astro/client.BhluLQqe.js +1 -0
- package/web/_astro/client.DBpSRLnx.js +9 -0
- package/web/_astro/cose-bilkent-S5V4N54A.DNLU_L-x.js +1 -0
- package/web/_astro/{cynefin-OW5HDTMX.BmK52w8G.js → cynefin-OW5HDTMX.D8borhV-.js} +1 -1
- package/web/_astro/{dagre-BM42HDAG.Bfy5CTDT.js → dagre-BM42HDAG.Uc0lvjcV.js} +2 -2
- package/web/_astro/diagram-2AECGRRQ.DDIxtDBo.js +43 -0
- package/web/_astro/diagram-5GNKFQAL.DVoDnD3H.js +10 -0
- package/web/_astro/{diagram-KO2AKTUF.CW_vMJ4z.js → diagram-KO2AKTUF.CRubTJ-0.js} +3 -3
- package/web/_astro/{diagram-LMA3HP47.B_8ZGF67.js → diagram-LMA3HP47.m9SeYcXQ.js} +1 -1
- package/web/_astro/{diagram-OG6HWLK6.BppnHsdS.js → diagram-OG6HWLK6.C6s2ZjV5.js} +1 -1
- package/web/_astro/{erDiagram-TEJ5UH35.BEuHXcjJ.js → erDiagram-TEJ5UH35.nSzr5KTj.js} +5 -5
- package/web/_astro/{flowDiagram-I6XJVG4X.CH-UlnGr.js → flowDiagram-I6XJVG4X.DrZcys16.js} +4 -4
- package/web/_astro/ganttDiagram-6RSMTGT7.Do4M1b-K.js +292 -0
- package/web/_astro/{gitGraphDiagram-PVQCEYII.XnPxPPZN.js → gitGraphDiagram-PVQCEYII.BWc9oJ4l.js} +1 -1
- package/web/_astro/index.5dn-Zm-2.js +1 -0
- package/web/_astro/index.C-IqPpW2.js +1 -0
- package/web/_astro/index.CENnIEqT.css +1 -0
- package/web/_astro/index.Cyc_GA4f.js +1 -0
- package/web/_astro/index.tZfqwSut.js +1 -0
- package/web/_astro/{infoDiagram-5YYISTIA.JyjYRu_T.js → infoDiagram-5YYISTIA.BIdOctFk.js} +1 -1
- package/web/_astro/{ishikawaDiagram-YF4QCWOH.BBRBF-Fo.js → ishikawaDiagram-YF4QCWOH.CV5SuG2t.js} +5 -5
- package/web/_astro/{journeyDiagram-JHISSGLW.C_iymSyp.js → journeyDiagram-JHISSGLW.CxE-rEJ-.js} +1 -1
- package/web/_astro/jsx-runtime.DWOiEOII.js +1 -0
- package/web/_astro/{kanban-definition-UN3LZRKU.DdfW-Oqt.js → kanban-definition-UN3LZRKU.BPRdKWs_.js} +7 -7
- package/web/_astro/{linear.C2_IkbZT.js → linear.zRsuuDTE.js} +1 -1
- package/web/_astro/mermaid.core.jAJTcMKc.js +301 -0
- package/web/_astro/{mindmap-definition-RKZ34NQL.DAZIxQSK.js → mindmap-definition-RKZ34NQL.BffJxfCr.js} +2 -2
- package/web/_astro/{pieDiagram-4H26LBE5.CN8sIhKM.js → pieDiagram-4H26LBE5.CacwWaE3.js} +3 -3
- package/web/_astro/{quadrantDiagram-W4KKPZXB.3dGcX5GP.js → quadrantDiagram-W4KKPZXB.hXELD06-.js} +1 -1
- package/web/_astro/{requirementDiagram-4Y6WPE33.BV2y4dd6.js → requirementDiagram-4Y6WPE33.DdEbPcqT.js} +3 -3
- package/web/_astro/{sankeyDiagram-5OEKKPKP.Cqo15Tvo.js → sankeyDiagram-5OEKKPKP.DgaDocKv.js} +4 -4
- package/web/_astro/{sequenceDiagram-3UESZ5HK.CROCPMJB.js → sequenceDiagram-3UESZ5HK.B0KScnAu.js} +1 -1
- package/web/_astro/{stateDiagram-AJRCARHV.RfXZrkFE.js → stateDiagram-AJRCARHV.CV9M_WNc.js} +1 -1
- package/web/_astro/{stateDiagram-v2-BHNVJYJU.CPXmbBs9.js → stateDiagram-v2-BHNVJYJU.BOAo74Et.js} +1 -1
- package/web/_astro/{timeline-definition-PNZ67QCA.DdgKTiO8.js → timeline-definition-PNZ67QCA.CqqepUMe.js} +3 -3
- package/web/_astro/{vennDiagram-CIIHVFJN.CPNVSHF1.js → vennDiagram-CIIHVFJN.DDqe4dOG.js} +5 -5
- package/web/_astro/{wardleyDiagram-YWT4CUSO.CQhA0Jyr.js → wardleyDiagram-YWT4CUSO.B3R9OPdO.js} +3 -3
- package/web/_astro/{xychartDiagram-2RQKCTM6.n61BWyy4.js → xychartDiagram-2RQKCTM6.B3SvgXpQ.js} +1 -1
- package/web/board-runtime.json +69 -0
- package/web/index.html +2 -2
- package/web/_astro/BoardApp.eoTz0pZs.js +0 -1
- package/web/_astro/TaskDetail.DCqiC-OZ.js +0 -1
- package/web/_astro/arc.CPwg6Rw0.js +0 -1
- package/web/_astro/architectureDiagram-3BPJPVTR.DM_vp_hO.js +0 -36
- package/web/_astro/channel.MYZLKNwy.js +0 -1
- package/web/_astro/client.yhYJvxCU.js +0 -9
- package/web/_astro/cose-bilkent-S5V4N54A.B1wSL-Xb.js +0 -1
- package/web/_astro/diagram-2AECGRRQ.DhNnvUvX.js +0 -43
- package/web/_astro/diagram-5GNKFQAL.lTX5KwnS.js +0 -10
- package/web/_astro/ganttDiagram-6RSMTGT7.BO81S85v.js +0 -292
- package/web/_astro/index.De90oHcH.js +0 -1
- package/web/_astro/index.Hjbr15fG.css +0 -1
- package/web/_astro/mermaid.core.GAOYeSR0.js +0 -303
package/README.md
CHANGED
|
@@ -59,6 +59,21 @@ If `~/.local/bin` isn't already on your `PATH`, add it (e.g. `export PATH="$HOME
|
|
|
59
59
|
in your shell profile). Supported targets: `darwin-arm64`, `darwin-x64`, `linux-arm64`, `linux-x64`.
|
|
60
60
|
Windows: use the Bun path under WSL.
|
|
61
61
|
|
|
62
|
+
**Verification.** The installer downloads to a temp file, checks it against the release's
|
|
63
|
+
`SHA256SUMS`, and only then atomically replaces `spur`. A failed download, a checksum mismatch, or a
|
|
64
|
+
missing `SHA256SUMS` leaves an existing install untouched and exits non-zero. `SPUR_RELEASE_URL`
|
|
65
|
+
overrides the download base URL (a mirror, or a `file://` directory in tests).
|
|
66
|
+
|
|
67
|
+
The checksum is a **code-execution** boundary, not just an integrity check: having verified the
|
|
68
|
+
download, the installer *runs* it (`spur init`), so a release whose `SHA256SUMS` cannot be verified
|
|
69
|
+
is a release you cannot safely install. `SPUR_SKIP_VERIFY=1` is the single explicit bypass and
|
|
70
|
+
prints a warning — keep it for local or air-gapped installs, and pipe the script into `sh` only from
|
|
71
|
+
a source you trust.
|
|
72
|
+
|
|
73
|
+
**Releasing standalone binaries.** Run `bun run build:binaries` in `apps/cli`, then upload **all**
|
|
74
|
+
of `dist/cli/spur-*` **and** `dist/cli/SHA256SUMS` to the GitHub Release for the tag. A release
|
|
75
|
+
without `SHA256SUMS` makes the installer fail by default.
|
|
76
|
+
|
|
62
77
|
### Package layout (what ships)
|
|
63
78
|
|
|
64
79
|
The published tarball is a self-contained Bun bundle plus static assets:
|
|
@@ -98,6 +113,33 @@ spur status
|
|
|
98
113
|
|
|
99
114
|
Every command supports `--json` for machine-readable output.
|
|
100
115
|
|
|
116
|
+
### Extending the Spur Board
|
|
117
|
+
|
|
118
|
+
A project can add its own Board modules — a compiled React tool or an embedded URL app — without
|
|
119
|
+
editing this package. An installed Board reads them from a fresh project's `.spur/config.yaml`:
|
|
120
|
+
|
|
121
|
+
```yaml
|
|
122
|
+
bootstrap:
|
|
123
|
+
modules:
|
|
124
|
+
- id: team-board
|
|
125
|
+
name: Team board
|
|
126
|
+
icon: "🧭"
|
|
127
|
+
type: react
|
|
128
|
+
directory: board/team-board/dist
|
|
129
|
+
entry: index.js
|
|
130
|
+
styles: [index.css]
|
|
131
|
+
- id: docs
|
|
132
|
+
name: Documentation
|
|
133
|
+
icon: "📚"
|
|
134
|
+
type: iframe
|
|
135
|
+
url: https://docs.example.test/
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
`spur init` seeds `modules: []` (built-ins only); change selection with a config edit, then restart
|
|
139
|
+
`spur serve` and reload. The full authoring contract — the declaration union, the
|
|
140
|
+
`@gobing-ai/spur/board` type export, the Vite library setup and the frame/trust limits — is in the
|
|
141
|
+
[downstream Board modules design](https://github.com/gobing-ai/spur/blob/main/docs/design/downstream-board-modules.md).
|
|
142
|
+
|
|
101
143
|
## Documentation
|
|
102
144
|
|
|
103
145
|
Full docs, architecture, and the complete command surface live in the
|
package/board/index.d.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Generated by scripts/commands/emit-board-types.ts from
|
|
2
|
+
// apps/web/src/modules/contribution.ts — edit the authoring source, then regenerate.
|
|
3
|
+
import type { ComponentType } from 'react';
|
|
4
|
+
/**
|
|
5
|
+
* Public authoring contract for a native (compiled React) Board module contribution
|
|
6
|
+
* (A8 / task 0988 R1).
|
|
7
|
+
*
|
|
8
|
+
* This file is the ONE authoring source for the declaration-only `@gobing-ai/spur/board`
|
|
9
|
+
* package export: `scripts/commands/emit-board-types.ts` emits `apps/cli/board/index.d.ts`
|
|
10
|
+
* from it, so the published ABI cannot drift from the Board's own types. Keep it
|
|
11
|
+
* type-only — no React *value* import may reach the CLI or plugin artifacts (the CLI
|
|
12
|
+
* ships no React; the contributor supplies compatible React types through its own
|
|
13
|
+
* devDependencies).
|
|
14
|
+
*
|
|
15
|
+
* Module metadata (id/name/icon/route) is deliberately absent: it is project
|
|
16
|
+
* configuration (one selection authority), while this shape carries only what the
|
|
17
|
+
* renderer needs to mount a contribution.
|
|
18
|
+
*/
|
|
19
|
+
export interface BoardModuleContribution {
|
|
20
|
+
/** Contribution protocol version this Board accepts. */
|
|
21
|
+
readonly apiVersion: 1;
|
|
22
|
+
/**
|
|
23
|
+
* Workspace component. Rendered inside the Board's React tree with the Board's own
|
|
24
|
+
* React instance — it must not call `createRoot`, and no private Board context is
|
|
25
|
+
* exported to it.
|
|
26
|
+
*/
|
|
27
|
+
readonly component: ComponentType;
|
|
28
|
+
/** Optional companion the Board's right panel renders while this module is active. */
|
|
29
|
+
readonly rightPanelComponent?: ComponentType;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The named export a native Board module entry must publish.
|
|
33
|
+
*
|
|
34
|
+
* Declared rather than implemented: `@gobing-ai/spur/board` is a declaration-only export,
|
|
35
|
+
* not a runtime SDK (consumers import its types; their compiled ESM entry exports this
|
|
36
|
+
* name for the renderer).
|
|
37
|
+
*/
|
|
38
|
+
export declare const webModule: BoardModuleContribution;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
$schema: "@gobing-ai/spur/schemas/rule-file.schema.json"
|
|
2
|
+
# Test-only subpath boundary — @gobing-ai/spur-app/testing and the app's testing/
|
|
3
|
+
# module are for tests and the mock itself, never production sources (task 0975 R3).
|
|
4
|
+
#
|
|
5
|
+
# WHY: `@gobing-ai/spur-app/testing` (packages/app/src/testing/history-board-mock.ts)
|
|
6
|
+
# is a test-only mock subpath (E82). A production import couples shipped code to a
|
|
7
|
+
# fake, and it crept toward the server transport before 0961 severed the seam. The
|
|
8
|
+
# evaluator's glob matcher is segment-aware with `*`/`**` only (no brace groups), so
|
|
9
|
+
# the ts/tsx globs would need separate entries — the repo carries .ts sources only,
|
|
10
|
+
# matching the dao-boundary precedent.
|
|
11
|
+
#
|
|
12
|
+
# Scope covers src trees only: `<workspace>/tests/**` directories stay outside, and
|
|
13
|
+
# `packages/app/src/testing/**` (the mock's own home) is exempted explicitly.
|
|
14
|
+
rules:
|
|
15
|
+
- id: no-testing-subpath-import
|
|
16
|
+
description: >
|
|
17
|
+
Production sources must not import the @gobing-ai/spur-app/testing subpath
|
|
18
|
+
(history-board mock, E82/0961). Tests under <workspace>/tests/** and the
|
|
19
|
+
packages/app/src/testing/** module itself are exempt.
|
|
20
|
+
severity: error
|
|
21
|
+
evaluator:
|
|
22
|
+
type: forbidden-import
|
|
23
|
+
config:
|
|
24
|
+
forbidden:
|
|
25
|
+
- specifier: "@gobing-ai/spur-app/testing"
|
|
26
|
+
scope:
|
|
27
|
+
include:
|
|
28
|
+
- "apps/**/src/**/*.ts"
|
|
29
|
+
- "packages/**/src/**/*.ts"
|
|
30
|
+
exclude:
|
|
31
|
+
- "packages/app/src/testing/**"
|
|
32
|
+
|
|
33
|
+
- id: no-relative-testing-module-import
|
|
34
|
+
description: >
|
|
35
|
+
packages/app production sources must not reach the testing/ module through
|
|
36
|
+
relative imports (from './testing/…' or '../…/testing…'). The testing/**
|
|
37
|
+
module itself and workspace tests/ directories are exempt.
|
|
38
|
+
severity: error
|
|
39
|
+
evaluator:
|
|
40
|
+
type: forbidden-import
|
|
41
|
+
config:
|
|
42
|
+
forbidden:
|
|
43
|
+
- pattern: "(?:from\\s+|import\\(\\s*)['\"](\\.\\.?/)+(?:[^'\"]*/)?testing(?:/|['\"])"
|
|
44
|
+
scope:
|
|
45
|
+
include:
|
|
46
|
+
- "packages/app/src/**/*.ts"
|
|
47
|
+
exclude:
|
|
48
|
+
- "packages/app/src/testing/**"
|
|
@@ -73,6 +73,7 @@ rules:
|
|
|
73
73
|
|
|
74
74
|
# Synchronous template & workflow resolvers:
|
|
75
75
|
- "apps/cli/src/commands/task.ts" # sync loadTemplateContent/Bodies callbacks
|
|
76
|
-
- "packages/app/src/services/workflow-service.ts" #
|
|
76
|
+
- "packages/app/src/services/workflow-service.ts" # run-log/checkpoint reclamation realpath confinement (:988, :1014)
|
|
77
|
+
- "packages/app/src/workflow/run-record.ts" # confined sync run-record reads: realpath + fstat byte-window (moved from workflow-service.ts, 0962)
|
|
77
78
|
- "apps/cli/src/release-ops.ts" # sync manifest/workspace reads + Bun.write rewrites inside the git release flow (task 0617); mirrors task.ts sync-template exemption
|
|
78
79
|
- "apps/cli/src/version-carriers.ts" # sync manifest reads + Bun.write rewrites for registered release carriers (task 0854); mirrors release-ops.ts sync exemption
|
|
@@ -37,6 +37,10 @@ rules:
|
|
|
37
37
|
# this rule's include scope — scanning generated copies only adds noise
|
|
38
38
|
# (e.g. `id: task-implement-transition` trips the sk- token shape).
|
|
39
39
|
- "apps/cli/config/"
|
|
40
|
+
# `apps/cli/plugins/` is the same kind of gitignored build:bundle output — a staged
|
|
41
|
+
# npm copy of `plugins/`, itself outside the include scope. Minified generated libs
|
|
42
|
+
# there trip the api-key shape (0976: HEAD's inline-run.generated.mjs fires too).
|
|
43
|
+
- "apps/cli/plugins/"
|
|
40
44
|
|
|
41
45
|
- id: no-unsafe-git-commands
|
|
42
46
|
description: "Unsafe git commands (force-push, hard reset) can overwrite history or cause data loss (AGENTS.md CRITICAL safety)."
|
|
@@ -50,13 +50,16 @@ states:
|
|
|
50
50
|
digest, run identity) and the coarse status file, always exit 0 so the
|
|
51
51
|
transition guard routes missing/corrupt/FAIL to `failed`.
|
|
52
52
|
onEnter:
|
|
53
|
+
# 0960 R2: run-start script-resolution identity — record which tree this run
|
|
54
|
+
# resolved (source-repo vs installed) before the verification step runs. Never aborts.
|
|
53
55
|
- kind: shell
|
|
54
56
|
options:
|
|
55
57
|
command: >-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
S=plugins/sp/scripts/script-root.ts; [ -f config/plugin-scripts.json -a -f "$S" ] || S="$(superskill script path sp script-root.mjs 2>/dev/null)"; RUNNER=bun; case "$S" in *.mjs) RUNNER=node ;; esac; [ -f "$S" ] && "$RUNNER" "$S" --run-id "$__runId" --spur-bin "$spurBin" || echo "script-root failed closed — run 'superskill install sp --marketplace gobing-ai/spur'" >&2; exit 0
|
|
59
|
+
- kind: shell
|
|
60
|
+
options:
|
|
61
|
+
command: >-
|
|
62
|
+
mkdir -p .spur/run; S=plugins/sp/scripts/feature-verification-steps.ts; [ -f config/plugin-scripts.json -a -f "$S" ] || S="$(superskill script path sp feature-verification-steps.mjs 2>/dev/null)"; RUNNER=bun; case "$S" in *.mjs) RUNNER=node ;; esac; [ -f "$S" ] && "$RUNNER" "$S" verify --feature-id "$featureId" --run-id "$__runId" --spur-bin "$spurBin" || printf 'FAIL feature-verification failed closed — script not found — run superskill install sp --marketplace gobing-ai/spur\n' > ".spur/run/$__runId-feature-verification.status"; exit 0
|
|
60
63
|
|
|
61
64
|
- id: done
|
|
62
65
|
description: Terminal — repo-wide checks passed and the receipt is bound.
|
|
@@ -84,6 +84,12 @@ states:
|
|
|
84
84
|
handoff — no task execution. Soft agent doctor (status file) so doctor red
|
|
85
85
|
routes to `failed` via transitions instead of a raw lifecycle abort.
|
|
86
86
|
onEnter:
|
|
87
|
+
# 0960 R2: run-start script-resolution identity — record which tree this run
|
|
88
|
+
# resolved (source-repo vs installed) before any step executes. Never aborts.
|
|
89
|
+
- kind: shell
|
|
90
|
+
options:
|
|
91
|
+
command: >-
|
|
92
|
+
S=plugins/sp/scripts/script-root.ts; [ -f config/plugin-scripts.json -a -f "$S" ] || S="$(superskill script path sp script-root.mjs 2>/dev/null)"; RUNNER=bun; case "$S" in *.mjs) RUNNER=node ;; esac; [ -f "$S" ] && "$RUNNER" "$S" --run-id "$__runId" --spur-bin "$spurBin" || echo "script-root failed closed — run 'superskill install sp --marketplace gobing-ai/spur'" >&2; exit 0
|
|
87
93
|
- kind: note
|
|
88
94
|
options:
|
|
89
95
|
message: "Idea pipeline start for idea: ${vars.idea}"
|
|
@@ -254,12 +260,12 @@ states:
|
|
|
254
260
|
options:
|
|
255
261
|
command: >-
|
|
256
262
|
mkdir -p .spur/run &&
|
|
257
|
-
S=plugins/sp/scripts/idea-coverage-check.ts
|
|
258
|
-
|
|
263
|
+
S=plugins/sp/scripts/idea-coverage-check.ts;
|
|
264
|
+
[ -f config/plugin-scripts.json -a -f "$S" ] || S="$(superskill script path sp idea-coverage-check.ts 2>/dev/null)";
|
|
259
265
|
if [ -n "$S" ] && [ -f "$S" ]; then
|
|
260
266
|
bun "$S" --run-id "$__runId" --report ".spur/run/$__runId-idea-eval-report.md" --ac ".spur/run/$__runId-idea-ac-content.md" || printf 'FAIL run=%s checker exited nonzero (bun missing or checker crash)\n' "$__runId" > ".spur/run/$__runId-idea-coverage.reason";
|
|
261
267
|
else
|
|
262
|
-
printf 'FAIL run=%s checker not found — run superskill install sp\n' "$__runId" | tee ".spur/run/$__runId-idea-coverage.reason" >&2;
|
|
268
|
+
printf 'FAIL run=%s checker not found — run superskill install sp --marketplace gobing-ai/spur\n' "$__runId" | tee ".spur/run/$__runId-idea-coverage.reason" >&2;
|
|
263
269
|
printf 'FAIL\n' > ".spur/run/$__runId-idea-coverage.status";
|
|
264
270
|
fi
|
|
265
271
|
# 0945 R2: derive the route facts ONCE at this boundary (0769 pattern) — guards read these
|
|
@@ -558,7 +564,7 @@ states:
|
|
|
558
564
|
elif H="$(superskill script path sp idea-handoff.mjs 2>/dev/null)" && [ -f "$H" ]; then
|
|
559
565
|
node "$H";
|
|
560
566
|
else
|
|
561
|
-
echo "idea handoff failed closed — idea-handoff script not found — run 'superskill install sp'" >&2;
|
|
567
|
+
echo "idea handoff failed closed — idea-handoff script not found — run 'superskill install sp --marketplace gobing-ai/spur'" >&2;
|
|
562
568
|
exit 1;
|
|
563
569
|
fi
|
|
564
570
|
- id: handoff
|
|
@@ -13,9 +13,10 @@
|
|
|
13
13
|
# `test` is the project quality gate (shell + bounded /sp:dev-fixall), not
|
|
14
14
|
# /sp:dev-unit (coverage gap-fill; router C3/C5).
|
|
15
15
|
#
|
|
16
|
-
# F96 residual sweep (0950): precheck captures the resume-safe base
|
|
17
|
-
# scans and folds residuals
|
|
18
|
-
#
|
|
16
|
+
# F96 residual sweep (0950, reordered 0983): precheck captures the resume-safe base
|
|
17
|
+
# commit; record scans and folds residuals AFTER `task record` flips the verdict-proven
|
|
18
|
+
# boxes (a post-record blocking leftover downgrades PASS → PARTIAL, fails the record →
|
|
19
|
+
# done guard closed, and re-records Testing before the failed edge); done settles
|
|
19
20
|
# deferrals; failed renders the recovery report. No new state, edge, or model query.
|
|
20
21
|
#
|
|
21
22
|
# Vars (passed as a JSON object via `--vars`):
|
|
@@ -187,6 +188,12 @@ states:
|
|
|
187
188
|
Fast deterministic task readiness and size checks. Failures route to the
|
|
188
189
|
`failed` terminal state (not a raw lifecycle abort mid-enter).
|
|
189
190
|
onEnter:
|
|
191
|
+
# 0960 R2: run-start script-resolution identity — record which tree this run
|
|
192
|
+
# resolved (source-repo vs installed) before any step executes. Never aborts.
|
|
193
|
+
- kind: shell
|
|
194
|
+
options:
|
|
195
|
+
command: >-
|
|
196
|
+
S=plugins/sp/scripts/script-root.ts; [ -f config/plugin-scripts.json -a -f "$S" ] || S="$(superskill script path sp script-root.mjs 2>/dev/null)"; RUNNER=bun; case "$S" in *.mjs) RUNNER=node ;; esac; [ -f "$S" ] && "$RUNNER" "$S" --run-id "$__runId" --spur-bin "$spurBin" || echo "script-root failed closed — run 'superskill install sp --marketplace gobing-ai/spur'" >&2; exit 0
|
|
190
197
|
# (e) git-status hygiene advisory; never fails the run (0487 R6 / 0511 R1).
|
|
191
198
|
- kind: shell
|
|
192
199
|
options:
|
|
@@ -207,12 +214,12 @@ states:
|
|
|
207
214
|
- kind: shell
|
|
208
215
|
options:
|
|
209
216
|
command: >-
|
|
210
|
-
mkdir -p .spur/run; S=plugins/sp/scripts/task-size-precheck.ts; [ -f "$S" ] || S="$(superskill script path sp task-size-precheck.ts 2>/dev/null)"; if [ -f "$S" ]; then bun "$S" "$wbs" --spur-bin "$spurBin" --max-reqs "$maxImplementReqs" --max-plan-items "$maxImplementPlanItems"; else echo "task-size-precheck failed closed — checker not found in plugins/sp/scripts/ nor staged — run 'superskill install sp'." >&2; echo "FAIL" > ".spur/run/$wbs-precheck-size.status"; fi; exit 0
|
|
217
|
+
mkdir -p .spur/run; S=plugins/sp/scripts/task-size-precheck.ts; [ -f config/plugin-scripts.json -a -f "$S" ] || S="$(superskill script path sp task-size-precheck.ts 2>/dev/null)"; if [ -f "$S" ]; then bun "$S" "$wbs" --spur-bin "$spurBin" --max-reqs "$maxImplementReqs" --max-plan-items "$maxImplementPlanItems"; else echo "task-size-precheck failed closed — checker not found in plugins/sp/scripts/ nor staged — run 'superskill install sp --marketplace gobing-ai/spur'." >&2; echo "FAIL" > ".spur/run/$wbs-precheck-size.status"; fi; exit 0
|
|
211
218
|
# (d) task-evidence-precheck.ts owns the check; shell only resolves it and fails closed (0726 R2).
|
|
212
219
|
- kind: shell
|
|
213
220
|
options:
|
|
214
221
|
command: >-
|
|
215
|
-
mkdir -p .spur/run; S=plugins/sp/scripts/task-evidence-precheck.ts; [ -f "$S" ] || S="$(superskill script path sp task-evidence-precheck.ts 2>/dev/null)"; if [ -f "$S" ]; then bun "$S" "$wbs" --spur-bin "$spurBin"; else echo "task-evidence-precheck failed closed — checker not found in plugins/sp/scripts/ nor staged — run 'superskill install sp'." >&2; echo "FAIL" > ".spur/run/$wbs-precheck-evidence.status"; fi; exit 0
|
|
222
|
+
mkdir -p .spur/run; S=plugins/sp/scripts/task-evidence-precheck.ts; [ -f config/plugin-scripts.json -a -f "$S" ] || S="$(superskill script path sp task-evidence-precheck.ts 2>/dev/null)"; if [ -f "$S" ]; then bun "$S" "$wbs" --spur-bin "$spurBin"; else echo "task-evidence-precheck failed closed — checker not found in plugins/sp/scripts/ nor staged — run 'superskill install sp --marketplace gobing-ai/spur'." >&2; echo "FAIL" > ".spur/run/$wbs-precheck-evidence.status"; fi; exit 0
|
|
216
223
|
# (e) F96 R1 (0950): capture the run's base commit once — a resumed or re-entered run
|
|
217
224
|
# keeps its original base so residual scans stay anchored to the same diff.
|
|
218
225
|
- kind: shell
|
|
@@ -286,6 +293,13 @@ states:
|
|
|
286
293
|
# a silent no-op routes the run to `failed` here instead of drifting
|
|
287
294
|
# into test/review and being caught a full pass later.
|
|
288
295
|
requireDiff: true
|
|
296
|
+
# Verification-only re-run admission (task 0976): when requireDiff
|
|
297
|
+
# sees zero non-corpus changes because the implementation already
|
|
298
|
+
# landed through another path, `spur task check <wbs>` PASS admits
|
|
299
|
+
# the empty implement as a certification pass; a check failure
|
|
300
|
+
# keeps the 0424 R3 empty-implement violation. Static option —
|
|
301
|
+
# deliberately no run-var knob (ADR-115).
|
|
302
|
+
requireDiffAllowCleanCheck: true
|
|
289
303
|
# 0933 R26: escalation contract — the agent.run option names the QUESTION
|
|
290
304
|
# file (the pause signal, deleted pre-dispatch for freshness); a paused
|
|
291
305
|
# attempt (agent wrote its question there and exited 0) succeeds with
|
|
@@ -425,7 +439,7 @@ states:
|
|
|
425
439
|
- kind: shell
|
|
426
440
|
options:
|
|
427
441
|
command: >-
|
|
428
|
-
mkdir -p .spur/run; if [ -f plugins/sp/scripts/quality-gate.ts ]; then bun plugins/sp/scripts/quality-gate.ts run; elif Q="$(superskill script path sp quality-gate.mjs 2>/dev/null)" && [ -f "$Q" ]; then node "$Q" run; else echo "quality gate failed closed — quality-gate script not found — run 'superskill install sp'" >&2; printf 'FAIL\n' > ".spur/run/$wbs-test-gate.status"; fi; exit 0
|
|
442
|
+
mkdir -p .spur/run; if [ -f config/plugin-scripts.json -a -f plugins/sp/scripts/quality-gate.ts ]; then bun plugins/sp/scripts/quality-gate.ts run; elif Q="$(superskill script path sp quality-gate.mjs 2>/dev/null)" && [ -f "$Q" ]; then node "$Q" run; else echo "quality gate failed closed — quality-gate script not found — run 'superskill install sp --marketplace gobing-ai/spur'" >&2; printf 'FAIL\n' > ".spur/run/$wbs-test-gate.status"; fi; exit 0
|
|
429
443
|
|
|
430
444
|
- id: test-fix
|
|
431
445
|
description: >
|
|
@@ -508,7 +522,7 @@ states:
|
|
|
508
522
|
- kind: shell
|
|
509
523
|
options:
|
|
510
524
|
command: >-
|
|
511
|
-
mkdir -p .spur/run; if [ -f plugins/sp/scripts/quality-gate.ts ]; then bun plugins/sp/scripts/quality-gate.ts recheck; elif Q="$(superskill script path sp quality-gate.mjs 2>/dev/null)" && [ -f "$Q" ]; then node "$Q" recheck; else echo "quality gate failed closed — quality-gate script not found — run 'superskill install sp'" >&2; printf 'FAIL\n' > ".spur/run/$wbs-test-gate.status"; fi; exit 0
|
|
525
|
+
mkdir -p .spur/run; if [ -f config/plugin-scripts.json -a -f plugins/sp/scripts/quality-gate.ts ]; then bun plugins/sp/scripts/quality-gate.ts recheck; elif Q="$(superskill script path sp quality-gate.mjs 2>/dev/null)" && [ -f "$Q" ]; then node "$Q" recheck; else echo "quality gate failed closed — quality-gate script not found — run 'superskill install sp --marketplace gobing-ai/spur'" >&2; printf 'FAIL\n' > ".spur/run/$wbs-test-gate.status"; fi; exit 0
|
|
512
526
|
|
|
513
527
|
- id: triage
|
|
514
528
|
description: >-
|
|
@@ -528,7 +542,7 @@ states:
|
|
|
528
542
|
- kind: shell
|
|
529
543
|
options:
|
|
530
544
|
command: >-
|
|
531
|
-
mkdir -p .spur/run; if [ -f plugins/sp/scripts/task-diffstat.ts ]; then bun plugins/sp/scripts/task-diffstat.ts --spur-bin "$spurBin"; elif D="$(superskill script path sp task-diffstat.mjs 2>/dev/null)" && [ -f "$D" ]; then node "$D"; else echo "task-diffstat failed closed — task-diffstat script not found — run 'superskill install sp'" >&2; printf '{"files":0,"insertions":0,"deletions":0,"paths":[],"sensitive":true}\n' > ".spur/run/$wbs-diffstat.json"; fi; exit 0
|
|
545
|
+
mkdir -p .spur/run; if [ -f config/plugin-scripts.json -a -f plugins/sp/scripts/task-diffstat.ts ]; then bun plugins/sp/scripts/task-diffstat.ts --spur-bin "$spurBin"; elif D="$(superskill script path sp task-diffstat.mjs 2>/dev/null)" && [ -f "$D" ]; then node "$D"; else echo "task-diffstat failed closed — task-diffstat script not found — run 'superskill install sp --marketplace gobing-ai/spur'" >&2; printf '{"files":0,"insertions":0,"deletions":0,"paths":[],"sensitive":true}\n' > ".spur/run/$wbs-diffstat.json"; fi; exit 0
|
|
532
546
|
# (b)+(c) lane pre-guard BEFORE decide: a caller-set mode is projected verbatim (R2b);
|
|
533
547
|
# a sensitive path or >400 changed lines pins safety (R2c) and the decide result below
|
|
534
548
|
# is never consulted. A missing/malformed diffstat row (producer crashed or never ran,
|
|
@@ -577,31 +591,24 @@ states:
|
|
|
577
591
|
Deterministic failure-class router on a red gate (0943 R3). The engine has no onEnter
|
|
578
592
|
conditionals, so the FAIL branch from `test`/`test-recheck` lands here as its own
|
|
579
593
|
deterministic state (the sanctioned alternative), while the green branch goes to
|
|
580
|
-
`triage`. `decide failure-class` reads the bounded gate findings and routes:
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
594
|
+
`triage`. `decide failure-class` reads the bounded gate findings and routes: fix →
|
|
595
|
+
test-fix (the bounded repair hop; its default, recorded as `source: default` when no
|
|
596
|
+
backend decides — 0976 R2), stop → failed with terminalReason failed-check. A
|
|
597
|
+
missing/corrupt decision fails closed to failed-check. (0976 R2 collapsed the former
|
|
598
|
+
`retryable` lane: the declared default made it unreachable on the inline path.)
|
|
584
599
|
onEnter:
|
|
585
600
|
- kind: decide
|
|
586
601
|
options:
|
|
587
602
|
id: failure-class
|
|
588
603
|
method: choice
|
|
589
604
|
question: >-
|
|
590
|
-
The quality gate failed. Is the failure
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
choices: [retryable, fix, stop]
|
|
605
|
+
The quality gate failed. Is the failure fixable by the repair agent, or should
|
|
606
|
+
the run stop here?
|
|
607
|
+
choices: [fix, stop]
|
|
594
608
|
default: fix
|
|
595
609
|
evidence:
|
|
596
610
|
- .spur/run/${vars.wbs}-test-gate.findings
|
|
597
611
|
resultFile: .spur/run/${vars.wbs}-failure-class.decision
|
|
598
|
-
# A retryable classification still counts an attempt so the existing
|
|
599
|
-
# qualityGateMaxFixAttempts cap bounds the recheck loop (0943 R3; the cap edge reads
|
|
600
|
-
# the same counter the fixall path uses).
|
|
601
|
-
- kind: shell
|
|
602
|
-
options:
|
|
603
|
-
command: >-
|
|
604
|
-
A=".spur/run/$wbs-test-fix-attempt"; [ "$(jq -r '.value // ""' ".spur/run/$wbs-failure-class.decision" 2>/dev/null)" = retryable ] && { n="$(cat "$A" 2>/dev/null || echo 0)"; printf '%s\n' "$((n + 1))" > "$A"; }; exit 0
|
|
605
612
|
|
|
606
613
|
- id: review
|
|
607
614
|
description: Three-dimensional code review via /sp:dev-review (functional requirements traceability + SECUA framework (Security, Efficiency, Correctness, Usability, Architecture) + architecture depth), findings written to `## Review`.
|
|
@@ -706,10 +713,10 @@ states:
|
|
|
706
713
|
options:
|
|
707
714
|
command: >-
|
|
708
715
|
LINT_SCRIPT="plugins/sp/scripts/verify-answer-lint.ts";
|
|
709
|
-
[ -f "$LINT_SCRIPT" ] ||
|
|
716
|
+
[ -f config/plugin-scripts.json -a -f "$LINT_SCRIPT" ] ||
|
|
710
717
|
LINT_SCRIPT="$(superskill script path sp verify-answer-lint.ts 2>/dev/null)";
|
|
711
718
|
if [ -z "$LINT_SCRIPT" ] || [ ! -f "$LINT_SCRIPT" ]; then
|
|
712
|
-
echo "verify-answer-lint: checker not found in plugins/sp/scripts/ nor staged — run 'superskill install sp'" >&2;
|
|
719
|
+
echo "verify-answer-lint: checker not found in plugins/sp/scripts/ nor staged — run 'superskill install sp --marketplace gobing-ai/spur'" >&2;
|
|
713
720
|
exit 1;
|
|
714
721
|
fi;
|
|
715
722
|
bun "$LINT_SCRIPT" "$wbs"
|
|
@@ -718,16 +725,6 @@ states:
|
|
|
718
725
|
- kind: shell
|
|
719
726
|
options:
|
|
720
727
|
command: "$spurBin task verdict $wbs --from-answer .spur/run/$wbs-verify-answer.txt"
|
|
721
|
-
# (d) F96 R2 (0950): residual-scan.ts owns the sweep; shell only resolves it.
|
|
722
|
-
# ONE hard action (scan+fold): a scanner crash fails verify closed — the
|
|
723
|
-
# verify→failed catch-all routes a missing/malformed verdict. Runs AFTER
|
|
724
|
-
# `task verdict` and BEFORE the jq bind so a blocking residual turns PASS
|
|
725
|
-
# into PARTIAL (fold rewrites the verdict artifact) and takes the existing
|
|
726
|
-
# verify→test-fix edge while attempts remain.
|
|
727
|
-
- kind: shell
|
|
728
|
-
options:
|
|
729
|
-
command: >-
|
|
730
|
-
S=plugins/sp/scripts/residual-scan.ts; [ -f "$S" ] || S="$(superskill script path sp residual-scan.mjs 2>/dev/null)"; if [ ! -f "$S" ]; then echo "residual-scan failed closed — scanner not found in plugins/sp/scripts/ nor staged — run 'superskill install sp'" >&2; exit 1; fi; case "$S" in *.mjs) RUNNER=node ;; *) RUNNER=bun ;; esac; "$RUNNER" "$S" scan "$wbs" --spur-bin "$spurBin" && "$RUNNER" "$S" fold "$wbs" --spur-bin "$spurBin"
|
|
731
728
|
# (e) one jq mutation binds the verdict to the proof digest (0703 R3; runId 0730 §B.2 /
|
|
732
729
|
# 0757 R4; definitionDigest 0759 R5; honest review stamp 0785 R4; soft action + hard guard).
|
|
733
730
|
- kind: shell
|
|
@@ -745,7 +742,11 @@ states:
|
|
|
745
742
|
evidence (0785 R4) — before any task record or status mutation. Post-record step
|
|
746
743
|
conditionally syncs feature status via the bounded `feature-sync-bounded` wrapper
|
|
747
744
|
(task 0411 retry-suppression) if `feature_id` is present, or appends an orphan
|
|
748
|
-
link proposal to the run report if absent (task 0328 / ADR-0322).
|
|
745
|
+
link proposal to the run report if absent (task 0328 / ADR-0322). The post-record
|
|
746
|
+
residual sweep (0983) re-scans the task file after the verdict-proven box flips and
|
|
747
|
+
folds blocking leftovers into the verdict before `record → done`; a downgrade
|
|
748
|
+
re-records Testing from the final artifact so a failed task never keeps a stale
|
|
749
|
+
PASS narrative.
|
|
749
750
|
onEnter:
|
|
750
751
|
# 0785 R3: BOUND verify-verdict registration — FIRST action, before any task record or
|
|
751
752
|
# status mutation, replacing the redundant proof.fingerprint compare (the action itself
|
|
@@ -771,7 +772,11 @@ states:
|
|
|
771
772
|
options:
|
|
772
773
|
id: task-record-transition
|
|
773
774
|
executable: "${vars.spurBin}"
|
|
774
|
-
|
|
775
|
+
# 0980: --no-lifecycle mirrors the wip/done hops — the pipeline run is
|
|
776
|
+
# already the lifecycle record, so a record-stage transition must not
|
|
777
|
+
# spawn a nested task-lifecycle run that outlives the pipeline as a
|
|
778
|
+
# `running` orphan. The target-aware check gate still runs (inline).
|
|
779
|
+
args: ["task", "record", "${vars.wbs}", "--solution-from-diff", "--transition", "testing", "--no-lifecycle"]
|
|
775
780
|
retry:
|
|
776
781
|
maxAttempts: 2
|
|
777
782
|
delayMs: 2000
|
|
@@ -791,7 +796,30 @@ states:
|
|
|
791
796
|
- kind: shell
|
|
792
797
|
options:
|
|
793
798
|
command: >-
|
|
794
|
-
S=plugins/sp/scripts/record-feature-sync.ts; [ -f "$S" ] || S="$(superskill script path sp record-feature-sync.mjs 2>/dev/null)"; [ "$deferFeatureSync" = "true" ] && echo "feature sync deferred to batch integration" >> ".spur/run/$wbs-report.txt" || if [ -f "$S" ]; then bun "$S" --spur-bin "$spurBin"; else echo "feature sync skipped — record-feature-sync not found in plugins/sp/scripts/ nor staged" >> ".spur/run/$wbs-report.txt"; fi; exit 0
|
|
799
|
+
S=plugins/sp/scripts/record-feature-sync.ts; [ -f config/plugin-scripts.json -a -f "$S" ] || S="$(superskill script path sp record-feature-sync.mjs 2>/dev/null)"; [ "$deferFeatureSync" = "true" ] && echo "feature sync deferred to batch integration" >> ".spur/run/$wbs-report.txt" || if [ -f "$S" ]; then bun "$S" --spur-bin "$spurBin"; else echo "feature sync skipped — record-feature-sync not found in plugins/sp/scripts/ nor staged" >> ".spur/run/$wbs-report.txt"; fi; exit 0
|
|
800
|
+
# (d) F96 (0983): residual-scan.ts owns the sweep; shell only resolves it. The
|
|
801
|
+
# scan moved here from verify: it must read the task file AFTER `task record`
|
|
802
|
+
# flipped the verdict-proven Requirement/AC boxes (0692), or a proven-but-unticked
|
|
803
|
+
# box folds every good run to PARTIAL and the done guard is unreachable (0967).
|
|
804
|
+
# Classification unchanged: any box still unchecked post-record (unproven R/AC,
|
|
805
|
+
# unfinished Plan) stays blocking and fails the record → done guard closed.
|
|
806
|
+
# ONE hard action (scan+fold): a scanner crash fails record closed.
|
|
807
|
+
- kind: shell
|
|
808
|
+
options:
|
|
809
|
+
command: >-
|
|
810
|
+
S=plugins/sp/scripts/residual-scan.ts; [ -f config/plugin-scripts.json -a -f "$S" ] || S="$(superskill script path sp residual-scan.mjs 2>/dev/null)"; if [ ! -f "$S" ]; then echo "residual-scan failed closed — scanner not found in plugins/sp/scripts/ nor staged — run 'superskill install sp --marketplace gobing-ai/spur'" >&2; exit 1; fi; case "$S" in *.mjs) RUNNER=node ;; *) RUNNER=bun ;; esac; "$RUNNER" "$S" scan "$wbs" --spur-bin "$spurBin" && "$RUNNER" "$S" fold "$wbs" --spur-bin "$spurBin"
|
|
811
|
+
# (e) F96 R5 (0983): a sweep downgrade must reach the task record — re-record from
|
|
812
|
+
# the FINAL (post-fold) artifact so Testing carries the downgraded verdict; a failed
|
|
813
|
+
# task must not retain a stale PASS Testing narrative. Soft (exit 0): the downgrade
|
|
814
|
+
# itself already fails the record → done guard; a re-record failure prints its
|
|
815
|
+
# re-run command and the failed state renders the recovery report.
|
|
816
|
+
# 0980: --no-lifecycle for the same orphan reason as the main record command —
|
|
817
|
+
# inert today (the task is already at testing, so this is a same-status no-op),
|
|
818
|
+
# but it keeps the no-nested-lifecycle invariant if the flow shifts.
|
|
819
|
+
- kind: shell
|
|
820
|
+
options:
|
|
821
|
+
command: >-
|
|
822
|
+
verdict="$(jq -r .verdict .spur/run/$wbs-verdict.json 2>/dev/null)"; if [ -n "$verdict" ] && [ "$verdict" != PASS ]; then $spurBin task record $wbs --solution-from-diff --transition testing --no-lifecycle || echo "post-downgrade re-record failed — re-run: $spurBin task record $wbs" >&2; fi; exit 0
|
|
795
823
|
|
|
796
824
|
- id: done
|
|
797
825
|
description: >
|
|
@@ -805,7 +833,7 @@ states:
|
|
|
805
833
|
- kind: shell
|
|
806
834
|
options:
|
|
807
835
|
command: >-
|
|
808
|
-
S=plugins/sp/scripts/residual-scan.ts; [ -f "$S" ] || S="$(superskill script path sp residual-scan.mjs 2>/dev/null)"; if [ -f "$S" ]; then case "$S" in *.mjs) RUNNER=node ;; *) RUNNER=bun ;; esac; "$RUNNER" "$S" settle "$wbs" --spur-bin "$spurBin" || echo "residual-settle failed — re-run: residual-scan settle $wbs" >&2; else echo "residual-scan not staged — settle skipped — re-run: residual-scan settle $wbs" >&2; fi; exit 0
|
|
836
|
+
S=plugins/sp/scripts/residual-scan.ts; [ -f config/plugin-scripts.json -a -f "$S" ] || S="$(superskill script path sp residual-scan.mjs 2>/dev/null)"; if [ -f "$S" ]; then case "$S" in *.mjs) RUNNER=node ;; *) RUNNER=bun ;; esac; "$RUNNER" "$S" settle "$wbs" --spur-bin "$spurBin" || echo "residual-settle failed — re-run: residual-scan settle $wbs" >&2; else echo "residual-scan not staged — settle skipped — re-run: residual-scan settle $wbs" >&2; fi; exit 0
|
|
809
837
|
# (c) command.gate owns the done transition with classified transient retry.
|
|
810
838
|
- kind: command.gate
|
|
811
839
|
options:
|
|
@@ -852,7 +880,7 @@ states:
|
|
|
852
880
|
- kind: shell
|
|
853
881
|
options:
|
|
854
882
|
command: >-
|
|
855
|
-
S=plugins/sp/scripts/residual-scan.ts; [ -f "$S" ] || S="$(superskill script path sp residual-scan.mjs 2>/dev/null)"; if [ -f "$S" ]; then case "$S" in *.mjs) RUNNER=node ;; *) RUNNER=bun ;; esac; "$RUNNER" "$S" report "$wbs" --spur-bin "$spurBin" || echo "residual-report failed — re-run: residual-scan report $wbs" >&2; else echo "residual-scan not staged — report skipped — re-run: residual-scan report $wbs" >&2; fi; exit 0
|
|
883
|
+
S=plugins/sp/scripts/residual-scan.ts; [ -f config/plugin-scripts.json -a -f "$S" ] || S="$(superskill script path sp residual-scan.mjs 2>/dev/null)"; if [ -f "$S" ]; then case "$S" in *.mjs) RUNNER=node ;; *) RUNNER=bun ;; esac; "$RUNNER" "$S" report "$wbs" --spur-bin "$spurBin" || echo "residual-report failed — re-run: residual-scan report $wbs" >&2; else echo "residual-scan not staged — report skipped — re-run: residual-scan report $wbs" >&2; fi; exit 0
|
|
856
884
|
|
|
857
885
|
- id: cancelled
|
|
858
886
|
description: Terminal — pipeline cancelled by operator at the approval gate (R1).
|
|
@@ -1007,8 +1035,7 @@ transitions:
|
|
|
1007
1035
|
options:
|
|
1008
1036
|
command: 'test "$mode" != fast'
|
|
1009
1037
|
# ── failure-class routing (0943 R3): stop first (never mislabeled by the cap), then the
|
|
1010
|
-
# attempt cap
|
|
1011
|
-
# decision lanes, then the fail-closed defense. Declaration order matters.
|
|
1038
|
+
# attempt cap, then the fix lane, then the fail-closed defense. Declaration order matters.
|
|
1012
1039
|
- from: test-fail-triage
|
|
1013
1040
|
to: failed
|
|
1014
1041
|
terminalReason: failed-check
|
|
@@ -1021,7 +1048,7 @@ transitions:
|
|
|
1021
1048
|
- from: test-fail-triage
|
|
1022
1049
|
to: failed
|
|
1023
1050
|
terminalReason: retry-exhausted
|
|
1024
|
-
description: Attempt cap reached — qualityGateMaxFixAttempts bounds the
|
|
1051
|
+
description: Attempt cap reached — qualityGateMaxFixAttempts bounds the fix lane.
|
|
1025
1052
|
# (warn) 5 commands: named fix attempts (legibility, 0874).
|
|
1026
1053
|
guard:
|
|
1027
1054
|
kind: shell
|
|
@@ -1029,14 +1056,6 @@ transitions:
|
|
|
1029
1056
|
command: >-
|
|
1030
1057
|
fix_attempts="$(cat .spur/run/$wbs-test-fix-attempt 2>/dev/null || echo 0)";
|
|
1031
1058
|
test "$fix_attempts" -ge "$qualityGateMaxFixAttempts"
|
|
1032
|
-
- from: test-fail-triage
|
|
1033
|
-
to: test-recheck
|
|
1034
|
-
description: Failure class retryable and under the cap — re-run the gate without fixall; the attempt was counted on entry.
|
|
1035
|
-
guard:
|
|
1036
|
-
kind: shell
|
|
1037
|
-
options:
|
|
1038
|
-
command: >-
|
|
1039
|
-
jq -e '.value == "retryable"' ".spur/run/$wbs-failure-class.decision" >/dev/null 2>&1
|
|
1040
1059
|
- from: test-fail-triage
|
|
1041
1060
|
to: test-fix
|
|
1042
1061
|
description: Failure class fix and under the cap — the bounded repair hop, as before.
|
|
@@ -1172,6 +1191,6 @@ transitions:
|
|
|
1172
1191
|
- from: record
|
|
1173
1192
|
to: failed
|
|
1174
1193
|
terminalReason: failed-check
|
|
1175
|
-
description: Task check failed or proof evidence missing/malformed/mismatched — block before done.
|
|
1194
|
+
description: Task check failed, a post-record residual downgrade, or proof evidence missing/malformed/mismatched — block before done.
|
|
1176
1195
|
guard:
|
|
1177
1196
|
kind: always
|