@warpgogol/forge 5.3.4 → 6.2.0
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/CHANGELOG.md +8 -0
- package/bin/cli.ts +7 -2
- package/dist/bin/cli.js +7 -2
- package/dist/bin/cli.js.map +1 -1
- package/dist/os/adr/adr.module.d.ts.map +1 -1
- package/dist/os/adr/adr.module.js +2 -0
- package/dist/os/adr/adr.module.js.map +1 -1
- package/dist/os/audit/audit.module.d.ts.map +1 -1
- package/dist/os/audit/audit.module.js +2 -0
- package/dist/os/audit/audit.module.js.map +1 -1
- package/dist/os/compass/compass.module.d.ts.map +1 -1
- package/dist/os/compass/compass.module.js +47 -15
- package/dist/os/compass/compass.module.js.map +1 -1
- package/dist/os/compass/handlers/compass-audit-handler.d.ts +2 -0
- package/dist/os/compass/handlers/compass-audit-handler.d.ts.map +1 -1
- package/dist/os/compass/handlers/compass-audit-handler.js +40 -10
- package/dist/os/compass/handlers/compass-audit-handler.js.map +1 -1
- package/dist/os/compass/handlers/compass-docs-validate.d.ts +13 -0
- package/dist/os/compass/handlers/compass-docs-validate.d.ts.map +1 -0
- package/dist/os/compass/handlers/compass-docs-validate.js +328 -0
- package/dist/os/compass/handlers/compass-docs-validate.js.map +1 -0
- package/dist/os/compass/handlers/summary-record.d.ts +11 -2
- package/dist/os/compass/handlers/summary-record.d.ts.map +1 -1
- package/dist/os/compass/handlers/summary-record.js +95 -15
- package/dist/os/compass/handlers/summary-record.js.map +1 -1
- package/dist/os/core/core.module.d.ts.map +1 -1
- package/dist/os/core/core.module.js +124 -73
- package/dist/os/core/core.module.js.map +1 -1
- package/dist/os/core/handlers/file-size-lint.d.ts.map +1 -1
- package/dist/os/core/handlers/file-size-lint.js +2 -0
- package/dist/os/core/handlers/file-size-lint.js.map +1 -1
- package/dist/os/exploration/exploration.module.d.ts.map +1 -1
- package/dist/os/exploration/exploration.module.js +3 -0
- package/dist/os/exploration/exploration.module.js.map +1 -1
- package/dist/os/naming/naming-convention.d.ts.map +1 -1
- package/dist/os/naming/naming-convention.js +11 -1
- package/dist/os/naming/naming-convention.js.map +1 -1
- package/dist/os/naming/naming.module.d.ts.map +1 -1
- package/dist/os/naming/naming.module.js +9 -2
- package/dist/os/naming/naming.module.js.map +1 -1
- package/dist/os/notes/notes.module.d.ts.map +1 -1
- package/dist/os/notes/notes.module.js +17 -6
- package/dist/os/notes/notes.module.js.map +1 -1
- package/dist/os/plan/plan.module.d.ts.map +1 -1
- package/dist/os/plan/plan.module.js +2 -0
- package/dist/os/plan/plan.module.js.map +1 -1
- package/dist/os/plugin/plugin.module.d.ts.map +1 -1
- package/dist/os/plugin/plugin.module.js +9 -2
- package/dist/os/plugin/plugin.module.js.map +1 -1
- package/dist/os/program/program.module.d.ts.map +1 -1
- package/dist/os/program/program.module.js +19 -4
- package/dist/os/program/program.module.js.map +1 -1
- package/dist/os/queue/handlers/queue-validate.d.ts.map +1 -1
- package/dist/os/queue/handlers/queue-validate.js +154 -7
- package/dist/os/queue/handlers/queue-validate.js.map +1 -1
- package/dist/os/queue/manifest.d.ts +17 -1
- package/dist/os/queue/manifest.d.ts.map +1 -1
- package/dist/os/queue/manifest.js +127 -6
- package/dist/os/queue/manifest.js.map +1 -1
- package/dist/os/queue/queue.module.d.ts.map +1 -1
- package/dist/os/queue/queue.module.js +32 -4
- package/dist/os/queue/queue.module.js.map +1 -1
- package/dist/os/queue/types.d.ts +100 -1
- package/dist/os/queue/types.d.ts.map +1 -1
- package/dist/os/queue/types.js +44 -0
- package/dist/os/queue/types.js.map +1 -1
- package/dist/os/rfc/handlers/implement-stamp.d.ts.map +1 -1
- package/dist/os/rfc/handlers/implement-stamp.js +30 -8
- package/dist/os/rfc/handlers/implement-stamp.js.map +1 -1
- package/dist/os/rfc/rfc.module.d.ts.map +1 -1
- package/dist/os/rfc/rfc.module.js +25 -6
- package/dist/os/rfc/rfc.module.js.map +1 -1
- package/dist/os/rfc/types.d.ts +12 -2
- package/dist/os/rfc/types.d.ts.map +1 -1
- package/dist/os/rfc/types.js +2 -2
- package/dist/os/rfc/types.js.map +1 -1
- package/dist/os/rfc/verification-evidence.d.ts +21 -0
- package/dist/os/rfc/verification-evidence.d.ts.map +1 -1
- package/dist/os/rfc/verification-evidence.js +134 -23
- package/dist/os/rfc/verification-evidence.js.map +1 -1
- package/dist/os/rfc/verification-refresh.d.ts.map +1 -1
- package/dist/os/rfc/verification-refresh.js +66 -37
- package/dist/os/rfc/verification-refresh.js.map +1 -1
- package/dist/os/session/handlers/save.d.ts.map +1 -1
- package/dist/os/session/handlers/save.js +42 -5
- package/dist/os/session/handlers/save.js.map +1 -1
- package/dist/os/session/session.module.d.ts.map +1 -1
- package/dist/os/session/session.module.js +5 -0
- package/dist/os/session/session.module.js.map +1 -1
- package/dist/os/spec/live-spec-merge.d.ts.map +1 -1
- package/dist/os/spec/live-spec-merge.js +55 -134
- package/dist/os/spec/live-spec-merge.js.map +1 -1
- package/dist/os/spec/live-spec-rebuild.d.ts +32 -0
- package/dist/os/spec/live-spec-rebuild.d.ts.map +1 -0
- package/dist/os/spec/live-spec-rebuild.js +272 -0
- package/dist/os/spec/live-spec-rebuild.js.map +1 -0
- package/dist/os/spec/live-spec-shared.d.ts +62 -0
- package/dist/os/spec/live-spec-shared.d.ts.map +1 -0
- package/dist/os/spec/live-spec-shared.js +315 -0
- package/dist/os/spec/live-spec-shared.js.map +1 -0
- package/dist/os/spec/live-spec-types.d.ts +17 -1
- package/dist/os/spec/live-spec-types.d.ts.map +1 -1
- package/dist/os/spec/live-spec-types.js +3 -0
- package/dist/os/spec/live-spec-types.js.map +1 -1
- package/dist/os/spec/live-spec-validate.d.ts.map +1 -1
- package/dist/os/spec/live-spec-validate.js +105 -2
- package/dist/os/spec/live-spec-validate.js.map +1 -1
- package/dist/os/spec/spec-materialize.d.ts +2 -0
- package/dist/os/spec/spec-materialize.d.ts.map +1 -1
- package/dist/os/spec/spec-materialize.js +45 -5
- package/dist/os/spec/spec-materialize.js.map +1 -1
- package/dist/os/spec/spec-schema.d.ts +19 -0
- package/dist/os/spec/spec-schema.d.ts.map +1 -1
- package/dist/os/spec/spec-schema.js +30 -0
- package/dist/os/spec/spec-schema.js.map +1 -1
- package/dist/os/spec/spec-status.d.ts +4 -0
- package/dist/os/spec/spec-status.d.ts.map +1 -1
- package/dist/os/spec/spec-status.js +19 -1
- package/dist/os/spec/spec-status.js.map +1 -1
- package/dist/os/spec/spec-validate.d.ts.map +1 -1
- package/dist/os/spec/spec-validate.js +55 -8
- package/dist/os/spec/spec-validate.js.map +1 -1
- package/dist/os/spec/spec.module.d.ts.map +1 -1
- package/dist/os/spec/spec.module.js +84 -8
- package/dist/os/spec/spec.module.js.map +1 -1
- package/dist/os/werkstatt/handlers/werkstatt-operation-validate.d.ts.map +1 -1
- package/dist/os/werkstatt/handlers/werkstatt-operation-validate.js +10 -4
- package/dist/os/werkstatt/handlers/werkstatt-operation-validate.js.map +1 -1
- package/dist/os/werkstatt/werkstatt.module.d.ts.map +1 -1
- package/dist/os/werkstatt/werkstatt.module.js +13 -4
- package/dist/os/werkstatt/werkstatt.module.js.map +1 -1
- package/dist/os/workflow/workflow.module.d.ts.map +1 -1
- package/dist/os/workflow/workflow.module.js +13 -5
- package/dist/os/workflow/workflow.module.js.map +1 -1
- package/dist/src/cli-flags.d.ts.map +1 -1
- package/dist/src/cli-flags.js +25 -5
- package/dist/src/cli-flags.js.map +1 -1
- package/dist/src/config/forge-config.d.ts +3 -0
- package/dist/src/config/forge-config.d.ts.map +1 -1
- package/dist/src/config/forge-config.js +2 -0
- package/dist/src/config/forge-config.js.map +1 -1
- package/dist/src/onboarding/doctor.d.ts.map +1 -1
- package/dist/src/onboarding/doctor.js +2 -3
- package/dist/src/onboarding/doctor.js.map +1 -1
- package/dist/src/onboarding/init.d.ts.map +1 -1
- package/dist/src/onboarding/init.js +8 -3
- package/dist/src/onboarding/init.js.map +1 -1
- package/dist/src/pipeline-status.d.ts +14 -1
- package/dist/src/pipeline-status.d.ts.map +1 -1
- package/dist/src/pipeline-status.js +28 -8
- package/dist/src/pipeline-status.js.map +1 -1
- package/dist/src/types.d.ts +7 -1
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/types.js +6 -0
- package/dist/src/types.js.map +1 -1
- package/dist/src/utils/generated-marker.d.ts +8 -0
- package/dist/src/utils/generated-marker.d.ts.map +1 -1
- package/dist/src/utils/generated-marker.js +25 -0
- package/dist/src/utils/generated-marker.js.map +1 -1
- package/dist/src/validators/skill-validate.d.ts.map +1 -1
- package/dist/src/validators/skill-validate.js +2 -4
- package/dist/src/validators/skill-validate.js.map +1 -1
- package/os/adr/adr.module.ts +2 -0
- package/os/audit/audit.module.ts +2 -0
- package/os/compass/compass.module.ts +49 -15
- package/os/compass/handlers/compass-audit-handler.ts +51 -10
- package/os/compass/handlers/compass-docs-validate.ts +361 -0
- package/os/compass/handlers/summary-record.ts +106 -15
- package/os/compass/handlers/tests/compass-audit-record.test.ts +2 -1
- package/os/compass/handlers/tests/compass-audit-validate.test.ts +92 -3
- package/os/compass/handlers/tests/compass-docs-validate.test.ts +203 -0
- package/os/compass/handlers/tests/compass-ledger-scope.test.ts +2 -1
- package/os/compass/handlers/tests/compass-policy.test.ts +7 -1
- package/os/compass/handlers/tests/summary-record.test.ts +127 -0
- package/os/core/core.module.ts +147 -75
- package/os/core/docs-archive.test.ts +136 -0
- package/os/core/handlers/file-size-lint.ts +2 -0
- package/os/exploration/exploration.module.ts +3 -0
- package/os/naming/naming-convention.ts +11 -1
- package/os/naming/naming.module.ts +9 -2
- package/os/notes/notes.module.ts +17 -6
- package/os/plan/plan-0000-template.md +150 -0
- package/os/plan/plan.module.ts +2 -0
- package/os/plugin/plugin.module.ts +9 -2
- package/os/program/program.module.ts +19 -4
- package/os/queue/decision-ledger.test.ts +163 -0
- package/os/queue/handlers/queue-validate.ts +190 -8
- package/os/queue/manifest.ts +201 -7
- package/os/queue/queue-validate.test.ts +303 -0
- package/os/queue/queue.module.ts +32 -4
- package/os/queue/types.ts +56 -1
- package/os/rfc/handlers/implement-stamp.ts +37 -8
- package/os/rfc/rfc-read-only-no-side-effects.test.ts +1 -0
- package/os/rfc/rfc.module.ts +27 -6
- package/os/rfc/types.ts +18 -3
- package/os/rfc/verification-emit.test.ts +305 -0
- package/os/rfc/verification-evidence.ts +149 -24
- package/os/rfc/verification-refresh.test.ts +222 -1
- package/os/rfc/verification-refresh.ts +74 -38
- package/os/session/handlers/save.ts +37 -5
- package/os/session/session.module.ts +5 -0
- package/os/spec/live-spec-idempotency.pbt.test.ts +222 -0
- package/os/spec/live-spec-list-show-validate.test.ts +10 -6
- package/os/spec/live-spec-merge.test.ts +187 -7
- package/os/spec/live-spec-merge.ts +71 -155
- package/os/spec/live-spec-rebuild.test.ts +317 -0
- package/os/spec/live-spec-rebuild.ts +356 -0
- package/os/spec/live-spec-shared.ts +378 -0
- package/os/spec/live-spec-types.ts +21 -1
- package/os/spec/live-spec-validate.test.ts +317 -0
- package/os/spec/live-spec-validate.ts +106 -2
- package/os/spec/spec-materialize.test.ts +192 -0
- package/os/spec/spec-materialize.ts +48 -4
- package/os/spec/spec-schema.ts +49 -0
- package/os/spec/spec-status.ts +24 -0
- package/os/spec/spec-validate.test.ts +66 -0
- package/os/spec/spec-validate.ts +62 -8
- package/os/spec/spec.module.ts +85 -8
- package/os/werkstatt/handlers/werkstatt-operation-validate.ts +10 -4
- package/os/werkstatt/werkstatt.module.ts +13 -4
- package/os/workflow/workflow.module.ts +13 -5
- package/package.json +1 -1
- package/skills/_shared/fo-pipeline-conventions.md +126 -1
- package/skills/fo/fo-doc-audit/SKILL.md +4 -4
- package/skills/fo/fo-explore/SKILL.md +2 -1
- package/skills/fo/fo-fix/SKILL.md +11 -3
- package/skills/fo/fo-handoff/SKILL.md +4 -6
- package/skills/fo/fo-idea-create-rfc/SKILL.md +2 -1
- package/skills/fo/fo-idea-enhance/SKILL.md +23 -4
- package/skills/fo/fo-idea-i-just-want-to-see-the-result/SKILL.md +86 -22
- package/skills/fo/fo-idea-implement/SKILL.md +53 -10
- package/skills/fo/fo-idea-plan/SKILL.md +28 -6
- package/skills/fo/fo-review/SKILL.md +69 -8
- package/skills/fo/fo-session-retro/SKILL.md +3 -2
- package/skills/fo/fo-step-commit/SKILL.md +2 -0
- package/skills/shared/grilling/SKILL.md +12 -0
- package/skills/shared/writing-great-skills/GLOSSARY.md +2 -0
- package/skills/shared/writing-great-skills/SKILL.md +2 -1
- package/src/cli-flags.ts +23 -5
- package/src/config/forge-config.ts +4 -0
- package/src/onboarding/doctor.ts +2 -3
- package/src/onboarding/init.ts +8 -3
- package/src/pipeline-status.ts +32 -8
- package/src/tests/cli-flags.test.ts +20 -0
- package/src/tests/cli-output.test.ts +13 -7
- package/src/tests/fixtures/agents-generate-business-before.txt +7 -7
- package/src/tests/implement-stamp.test.ts +38 -0
- package/src/tests/session-handlers.test.ts +33 -0
- package/src/types.ts +13 -1
- package/src/utils/generated-marker.ts +28 -0
- package/src/validators/skill-validate.ts +2 -4
- package/skills/fo/fo-idea-implement/ADR-FLOW.md +0 -179
- package/skills/fo/fo-review/AXES.md +0 -70
package/os/spec/spec.module.ts
CHANGED
|
@@ -6,10 +6,18 @@
|
|
|
6
6
|
</non-goals>
|
|
7
7
|
</MODULE_CONTRACT>
|
|
8
8
|
<CHANGE_SUMMARY>
|
|
9
|
-
<item>RFC-
|
|
10
|
-
<item>RFC-0396: added spec.status and spec.materialize commands.</item>
|
|
11
|
-
<item>RFC-0711: added spec.live.merge, spec.live.list, spec.live.show, spec.live.validate commands.</item>
|
|
9
|
+
<item>RFC-1230: added spec.live.rebuild command + --force flag on spec.live.merge (idempotent merge design).</item>
|
|
12
10
|
<item>RFC-1173: declare mutatesState on all kernel commands — collectDeclarationDiagnostics emits error-severity MUTATES-STATE-DECLARED, command.manifest.validate is the blocking consumer in packages.check, sweep declares the flag on every command definition (factories hardcode false for read-only check specs)</item>
|
|
11
|
+
<item>RFC-1230: review findings — scoped droppedSections to namespaced headings, warn on unreadable spec, fail-fast merge on corrupt frontmatter, CHANGE_SUMMARY dedupe</item>
|
|
12
|
+
<item>RFC-1231: step 1 — rename supportsAllSites to acceptsAllFlag
|
|
13
|
+
|
|
14
|
+
Mechanical sweep: the field only ever gated --all argv acceptance; fan-out
|
|
15
|
+
follows the parsed selector. Guard renamed assertAllSitesAllowed ->
|
|
16
|
+
assertAllFlagAccepted, message updated. 417 declaration sites + type
|
|
17
|
+
surfaces (KernelCommandMetadata, ForgeCommandMetadata) in one atomic pass.</item>
|
|
18
|
+
<item>RFC-1234: spec.live.validate description lists V-LS-09 drift rule.</item>
|
|
19
|
+
<item>RFC-1240: --consumer flag on spec.validate/spec.status/spec.materialize; SPEC-12/13 rules in spec.validate description.</item>
|
|
20
|
+
<history>RFC-0394, RFC-0396, RFC-0711</history>
|
|
13
21
|
</CHANGE_SUMMARY>
|
|
14
22
|
*/
|
|
15
23
|
|
|
@@ -23,6 +31,7 @@ const { runSpecValidate } = await import("./spec-validate.ts");
|
|
|
23
31
|
const { runSpecLiveList } = await import("./live-spec-list.ts");
|
|
24
32
|
const { runSpecLiveShow } = await import("./live-spec-show.ts");
|
|
25
33
|
const { runSpecLiveValidate } = await import("./live-spec-validate.ts");
|
|
34
|
+
const { runSpecLiveRebuild } = await import("./live-spec-rebuild.ts");
|
|
26
35
|
return {
|
|
27
36
|
name: "forge-spec",
|
|
28
37
|
version: "0.2.0",
|
|
@@ -33,11 +42,26 @@ const { runSpecValidate } = await import("./spec-validate.ts");
|
|
|
33
42
|
name: "spec.validate",
|
|
34
43
|
mutatesState: false,
|
|
35
44
|
contract: "spec",
|
|
36
|
-
rules: [
|
|
45
|
+
rules: [
|
|
46
|
+
"SPEC-01",
|
|
47
|
+
"SPEC-02",
|
|
48
|
+
"SPEC-03",
|
|
49
|
+
"SPEC-04",
|
|
50
|
+
"SPEC-05",
|
|
51
|
+
"SPEC-06",
|
|
52
|
+
"SPEC-07",
|
|
53
|
+
"SPEC-08",
|
|
54
|
+
"SPEC-09",
|
|
55
|
+
"SPEC-10",
|
|
56
|
+
"SPEC-11",
|
|
57
|
+
"SPEC-12",
|
|
58
|
+
"SPEC-13",
|
|
59
|
+
],
|
|
37
60
|
description:
|
|
38
61
|
"Validate vendored spec packages under docs/specs/. " +
|
|
39
62
|
"Checks integrity (SHA-256), schema, dependency graph (acyclic), " +
|
|
40
|
-
"reference resolution, wave coverage, duplicate ids,
|
|
63
|
+
"reference resolution, wave coverage, duplicate ids, materializedAs links, " +
|
|
64
|
+
"and consumer hygiene (SPEC-12 duplicates/empty, SPEC-13 identity warning). " +
|
|
41
65
|
"Use --spec=<id> to validate a single spec.",
|
|
42
66
|
scope: "workspace",
|
|
43
67
|
flags: {
|
|
@@ -45,12 +69,17 @@ const { runSpecValidate } = await import("./spec-validate.ts");
|
|
|
45
69
|
kind: "string",
|
|
46
70
|
description: "Validate only the named spec.",
|
|
47
71
|
},
|
|
72
|
+
consumer: {
|
|
73
|
+
kind: "string",
|
|
74
|
+
description: "Local consumer identity override (default: forge.yaml project.consumer).",
|
|
75
|
+
},
|
|
48
76
|
},
|
|
49
77
|
reads: ["docs/specs/**/*"],
|
|
50
78
|
execute: runSpecValidate,
|
|
51
79
|
},
|
|
52
80
|
{
|
|
53
81
|
name: "spec.status",
|
|
82
|
+
coverage: "operator" as const,
|
|
54
83
|
mutatesState: false,
|
|
55
84
|
description:
|
|
56
85
|
"Show roadmap progress for vendored specs. " +
|
|
@@ -61,12 +90,17 @@ const { runSpecValidate } = await import("./spec-validate.ts");
|
|
|
61
90
|
kind: "string",
|
|
62
91
|
description: "Show status for a single spec.",
|
|
63
92
|
},
|
|
93
|
+
consumer: {
|
|
94
|
+
kind: "string",
|
|
95
|
+
description: "Local consumer identity override (default: forge.yaml project.consumer).",
|
|
96
|
+
},
|
|
64
97
|
},
|
|
65
98
|
reads: ["docs/specs/**/*", "docs/rfcs/**/*.md"],
|
|
66
99
|
execute: runSpecStatus,
|
|
67
100
|
},
|
|
68
101
|
{
|
|
69
102
|
name: "spec.materialize",
|
|
103
|
+
coverage: "operator" as const,
|
|
70
104
|
description:
|
|
71
105
|
"Scaffold RFC files for the next N front nodes of a spec roadmap. " +
|
|
72
106
|
"Requires --spec=<id>. Optional: --next=<N> (default 8, max 12), --nodes=<id,id> explicit selection.",
|
|
@@ -79,6 +113,7 @@ const { runSpecValidate } = await import("./spec-validate.ts");
|
|
|
79
113
|
spec: { kind: "string", required: true, description: "Spec id to materialize from." },
|
|
80
114
|
next: { kind: "string", description: "Number of front nodes to materialize (default 8, max 12)." },
|
|
81
115
|
nodes: { kind: "string", description: "Comma-separated explicit node ids to materialize." },
|
|
116
|
+
consumer: { kind: "string", description: "Local consumer identity override (default: forge.yaml project.consumer)." },
|
|
82
117
|
},
|
|
83
118
|
execute: runSpecMaterialize,
|
|
84
119
|
},
|
|
@@ -89,7 +124,8 @@ const { runSpecValidate } = await import("./spec-validate.ts");
|
|
|
89
124
|
"under docs/specs/live/<domain>.md. Requires --id=<RFC-XXXX>. " +
|
|
90
125
|
"Domain is auto-derived from packagesImpacted[0] when liveSpec: true, or uses " +
|
|
91
126
|
"the string value when liveSpec: <domain>. " +
|
|
92
|
-
"
|
|
127
|
+
"Idempotent: an RFC already in spec history[] is skipped as already-merged; " +
|
|
128
|
+
"use --force to re-merge (replaces that RFC's namespaced sections). " +
|
|
93
129
|
"Use --dry-run to preview deltas without writing.",
|
|
94
130
|
scope: "workspace",
|
|
95
131
|
mutatesState: true,
|
|
@@ -98,12 +134,14 @@ const { runSpecValidate } = await import("./spec-validate.ts");
|
|
|
98
134
|
reads: ["docs/rfcs/**/*.md", "docs/specs/live/*.md"],
|
|
99
135
|
flags: {
|
|
100
136
|
id: { kind: "string", required: true, description: "RFC id to merge (e.g. RFC-0711)." },
|
|
137
|
+
force: { kind: "boolean", description: "Re-merge an already-merged RFC — strips its (RFC-XXXX) sections and old history entries first." },
|
|
101
138
|
"dry-run": { kind: "boolean", description: "Preview deltas without writing files." },
|
|
102
139
|
},
|
|
103
140
|
execute: runSpecLiveMerge,
|
|
104
141
|
},
|
|
105
142
|
{
|
|
106
143
|
name: "spec.live.list",
|
|
144
|
+
coverage: "operator" as const,
|
|
107
145
|
mutatesState: false,
|
|
108
146
|
description:
|
|
109
147
|
"List all living feature specs in docs/specs/live/. " +
|
|
@@ -115,6 +153,7 @@ const { runSpecValidate } = await import("./spec-validate.ts");
|
|
|
115
153
|
},
|
|
116
154
|
{
|
|
117
155
|
name: "spec.live.show",
|
|
156
|
+
coverage: "operator" as const,
|
|
118
157
|
mutatesState: false,
|
|
119
158
|
description:
|
|
120
159
|
"Show a single living feature spec by domain. " +
|
|
@@ -128,18 +167,56 @@ const { runSpecValidate } = await import("./spec-validate.ts");
|
|
|
128
167
|
},
|
|
129
168
|
{
|
|
130
169
|
name: "spec.live.validate",
|
|
170
|
+
coverage: "operator" as const,
|
|
171
|
+
coverageNote: "spec.live drift audit — current debt repaired via spec.live.rebuild",
|
|
131
172
|
mutatesState: false,
|
|
132
173
|
contract: "spec",
|
|
133
|
-
rules: [
|
|
174
|
+
rules: [
|
|
175
|
+
"V-LS-01",
|
|
176
|
+
"V-LS-02",
|
|
177
|
+
"V-LS-03",
|
|
178
|
+
"V-LS-04",
|
|
179
|
+
"V-LS-05",
|
|
180
|
+
"V-LS-06",
|
|
181
|
+
"V-LS-07",
|
|
182
|
+
"V-LS-08",
|
|
183
|
+
"V-LS-09",
|
|
184
|
+
],
|
|
134
185
|
description:
|
|
135
186
|
"Validate all living feature specs in docs/specs/live/. " +
|
|
136
187
|
"Checks V-LS-01 (frontmatter), V-LS-02 (domain/filename match), " +
|
|
137
188
|
"V-LS-03 (lastMergedRfc is archived), V-LS-04 (history entries are archived), " +
|
|
138
|
-
"V-LS-05 (no duplicate domains)
|
|
189
|
+
"V-LS-05 (no duplicate domains), V-LS-06 (no duplicate RFC-namespaced headings), " +
|
|
190
|
+
"V-LS-07 (no duplicate history RFCs), V-LS-08 (merged-history coverage is complete), " +
|
|
191
|
+
"V-LS-09 (spec content matches the deterministic replay of its history). " +
|
|
192
|
+
"Repair path: spec.live.rebuild.",
|
|
139
193
|
scope: "workspace",
|
|
140
194
|
flags: {},
|
|
141
195
|
reads: ["docs/specs/live/*.md", "docs/rfcs/**/*.md"],
|
|
142
196
|
execute: runSpecLiveValidate,
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
name: "spec.live.rebuild",
|
|
200
|
+
coverage: "operator" as const,
|
|
201
|
+
acceptsAllFlag: true,
|
|
202
|
+
description:
|
|
203
|
+
"Rebuild a living feature spec by replaying its deduplicated history[] — " +
|
|
204
|
+
"the repair path for duplicated (RFC-XXXX) sections and duplicate history entries " +
|
|
205
|
+
"reported by spec.live.validate (V-LS-06/V-LS-07). " +
|
|
206
|
+
"Each unique RFC's current ## Design is re-applied in first-occurrence order; " +
|
|
207
|
+
"unreadable or unimplemented RFCs are skipped with a warning. " +
|
|
208
|
+
"With no --domain (or --all) every spec is rebuilt. Use --dry-run to preview.",
|
|
209
|
+
scope: "workspace",
|
|
210
|
+
mutatesState: true,
|
|
211
|
+
writes: ["docs/specs/live/*.md"],
|
|
212
|
+
generates: [],
|
|
213
|
+
reads: ["docs/specs/live/*.md", "docs/rfcs/**/*.md"],
|
|
214
|
+
flags: {
|
|
215
|
+
domain: { kind: "string", description: "Rebuild a single living spec by domain (filename without .md)." },
|
|
216
|
+
all: { kind: "boolean", description: "Rebuild every living spec in docs/specs/live/ (default when --domain is omitted)." },
|
|
217
|
+
"dry-run": { kind: "boolean", description: "Preview rebuild without writing files." },
|
|
218
|
+
},
|
|
219
|
+
execute: runSpecLiveRebuild,
|
|
143
220
|
}
|
|
144
221
|
],
|
|
145
222
|
pipelines: [
|
|
@@ -12,6 +12,7 @@ helper module (RFC-0362 §6).</purpose>
|
|
|
12
12
|
<CHANGE_SUMMARY>
|
|
13
13
|
<item>RFC-0362: initial operation.validate command handler.</item>
|
|
14
14
|
<item>RFC-0556: moved from @warpgogol/site-kernel-checks to @warpgogol/forge for autonomous mode. Uses node:fs/promises directly instead of context.io.</item>
|
|
15
|
+
<item>RFC-1248: VITE-CLIENT-DEP-02 lazy-import gate + SCAN-02 validator reads-root existence check (RFC-1248)</item>
|
|
15
16
|
</CHANGE_SUMMARY>
|
|
16
17
|
*/
|
|
17
18
|
|
|
@@ -25,8 +26,8 @@ import type {
|
|
|
25
26
|
ForgeRuntimeContext,
|
|
26
27
|
} from "../../../src/types.ts";
|
|
27
28
|
|
|
28
|
-
const SCAN_DIR = "packages/
|
|
29
|
-
const ALLOWLIST_DIR = "packages/
|
|
29
|
+
const SCAN_DIR = "packages/werkstatt-engine/src/handoff";
|
|
30
|
+
const ALLOWLIST_DIR = "packages/werkstatt-engine/src/werkstatt";
|
|
30
31
|
|
|
31
32
|
const DIRECT_WRITE_PATTERNS: Array<{ regex: RegExp; label: string }> = [
|
|
32
33
|
{ regex: /\bwriteFile\s*\(/g, label: "writeFile" },
|
|
@@ -56,10 +57,15 @@ export async function runWerkstattOperationValidate(
|
|
|
56
57
|
|
|
57
58
|
const violations: Array<{ file: string; line: number; pattern: string }> = [];
|
|
58
59
|
|
|
59
|
-
const PRE_EXISTING_ALLOWLIST = new Set([
|
|
60
|
+
const PRE_EXISTING_ALLOWLIST = new Set([
|
|
61
|
+
"handoff-pack.ts",
|
|
62
|
+
"materialize.ts",
|
|
63
|
+
"bundle-io.ts",
|
|
64
|
+
"platform-consistency.ts",
|
|
65
|
+
]);
|
|
60
66
|
|
|
61
67
|
for (const filePath of files) {
|
|
62
|
-
if (filePath.startsWith(allowlistPath)
|
|
68
|
+
if (filePath.startsWith(allowlistPath)) continue;
|
|
63
69
|
|
|
64
70
|
const fileName = basename(filePath);
|
|
65
71
|
if (fileName.endsWith(".test.ts") || fileName.endsWith(".spec.ts")) continue;
|
|
@@ -9,6 +9,13 @@
|
|
|
9
9
|
<item>RFC-0374: initial forgeWerkstattModule registering 3 werkstatt commands.</item>
|
|
10
10
|
<item>RFC-0556: removed dynamic imports of @warpgogol/site-kernel-handoff and @warpgogol/site-kernel-checks, all handlers now inlined in forge/os/werkstatt/handlers/.</item>
|
|
11
11
|
<item>RFC-1173: declare mutatesState on all kernel commands — collectDeclarationDiagnostics emits error-severity MUTATES-STATE-DECLARED, command.manifest.validate is the blocking consumer in packages.check, sweep declares the flag on every command definition (factories hardcode false for read-only check specs)</item>
|
|
12
|
+
<item>RFC-1231: step 1 — rename supportsAllSites to acceptsAllFlag
|
|
13
|
+
|
|
14
|
+
Mechanical sweep: the field only ever gated --all argv acceptance; fan-out
|
|
15
|
+
follows the parsed selector. Guard renamed assertAllSitesAllowed ->
|
|
16
|
+
assertAllFlagAccepted, message updated. 417 declaration sites + type
|
|
17
|
+
surfaces (KernelCommandMetadata, ForgeCommandMetadata) in one atomic pass.</item>
|
|
18
|
+
<item>RFC-1248: VITE-CLIENT-DEP-02 lazy-import gate + SCAN-02 validator reads-root existence check (RFC-1248)</item>
|
|
12
19
|
</CHANGE_SUMMARY>
|
|
13
20
|
*/
|
|
14
21
|
|
|
@@ -25,20 +32,22 @@ export const forgeWerkstattModule: ForgeModule = {
|
|
|
25
32
|
commands: [
|
|
26
33
|
{
|
|
27
34
|
name: "werkstatt.lock.status",
|
|
35
|
+
coverage: "operator" as const,
|
|
28
36
|
mutatesState: false,
|
|
29
37
|
description: "Report all Werkstatt locks, their age, owner, and staleness (RFC-0362).",
|
|
30
38
|
scope: "workspace",
|
|
31
|
-
|
|
39
|
+
acceptsAllFlag: false,
|
|
32
40
|
flags: {},
|
|
33
41
|
reads: [".werkstatt/locks/**"],
|
|
34
42
|
execute: runWerkstattLockStatus,
|
|
35
43
|
},
|
|
36
44
|
{
|
|
37
45
|
name: "werkstatt.lock.recover",
|
|
46
|
+
coverage: "operator" as const,
|
|
38
47
|
description:
|
|
39
48
|
"Classify and clean stale locks and staging artifacts (RFC-0362). Flags: --scope, --purge.",
|
|
40
49
|
scope: "workspace",
|
|
41
|
-
|
|
50
|
+
acceptsAllFlag: false,
|
|
42
51
|
mutatesState: true,
|
|
43
52
|
flags: {
|
|
44
53
|
scope: { kind: "string", description: "Recover only a single lock scope." },
|
|
@@ -61,9 +70,9 @@ export const forgeWerkstattModule: ForgeModule = {
|
|
|
61
70
|
description:
|
|
62
71
|
"Validate that mutating Werkstatt commands use shared lock/idempotency/atomic-write helpers (RFC-0362).",
|
|
63
72
|
scope: "workspace",
|
|
64
|
-
|
|
73
|
+
acceptsAllFlag: false,
|
|
65
74
|
flags: {},
|
|
66
|
-
reads: ["packages/
|
|
75
|
+
reads: ["packages/werkstatt-engine/src/handoff/**/*.ts"],
|
|
67
76
|
execute: runWerkstattOperationValidate,
|
|
68
77
|
},
|
|
69
78
|
],
|
|
@@ -9,6 +9,13 @@
|
|
|
9
9
|
<item>RFC-0075: Add workflow command module.</item>
|
|
10
10
|
<item>RFC-0374: Migrated from packages/os/site-kernel/src/workflow/ to packages/forge/os/workflow/.</item>
|
|
11
11
|
<item>RFC-1173: declare mutatesState on all kernel commands — collectDeclarationDiagnostics emits error-severity MUTATES-STATE-DECLARED, command.manifest.validate is the blocking consumer in packages.check, sweep declares the flag on every command definition (factories hardcode false for read-only check specs)</item>
|
|
12
|
+
<item>RFC-1231: step 1 — rename supportsAllSites to acceptsAllFlag
|
|
13
|
+
|
|
14
|
+
Mechanical sweep: the field only ever gated --all argv acceptance; fan-out
|
|
15
|
+
follows the parsed selector. Guard renamed assertAllSitesAllowed ->
|
|
16
|
+
assertAllFlagAccepted, message updated. 417 declaration sites + type
|
|
17
|
+
surfaces (KernelCommandMetadata, ForgeCommandMetadata) in one atomic pass.</item>
|
|
18
|
+
<item>RFC-1248: VITE-CLIENT-DEP-02 lazy-import gate + SCAN-02 validator reads-root existence check (RFC-1248)</item>
|
|
12
19
|
</CHANGE_SUMMARY>
|
|
13
20
|
*/
|
|
14
21
|
|
|
@@ -32,19 +39,20 @@ export async function createForgeWorkflowModule(): Promise<ForgeModule> {
|
|
|
32
39
|
"and per-chain phase links (RFC-0075 + RFC-0136).",
|
|
33
40
|
scope: "workspace",
|
|
34
41
|
flags: {},
|
|
35
|
-
|
|
36
|
-
reads: [".agents/workflows/**/*.md", ".windsurf/workflows/**/*.md"],
|
|
42
|
+
acceptsAllFlag: true,
|
|
43
|
+
reads: [".agents/workflows/**/*.md", ".windsurf/workflows/**/*.md"], // scan-coverage: optional tool dirs — workshops declare workflows under either
|
|
37
44
|
execute: runWorkflowLint,
|
|
38
45
|
},
|
|
39
46
|
{
|
|
40
47
|
name: "workflow.list",
|
|
48
|
+
coverage: "operator" as const,
|
|
41
49
|
mutatesState: false,
|
|
42
50
|
description:
|
|
43
51
|
"List .agents/workflows entries with phase, IO summary, and next workflow (RFC-0075).",
|
|
44
52
|
scope: "workspace",
|
|
45
53
|
flags: {},
|
|
46
|
-
|
|
47
|
-
reads: [".agents/workflows/**/*.md", ".windsurf/workflows/**/*.md"],
|
|
54
|
+
acceptsAllFlag: true,
|
|
55
|
+
reads: [".agents/workflows/**/*.md", ".windsurf/workflows/**/*.md"], // scan-coverage: optional tool dirs — workshops declare workflows under either
|
|
48
56
|
execute: runWorkflowList,
|
|
49
57
|
},
|
|
50
58
|
{
|
|
@@ -54,7 +62,7 @@ export async function createForgeWorkflowModule(): Promise<ForgeModule> {
|
|
|
54
62
|
"List .agents/workflows-amend entries with phase, IO summary, and next workflow (RFC-0136).",
|
|
55
63
|
scope: "workspace",
|
|
56
64
|
flags: {},
|
|
57
|
-
|
|
65
|
+
acceptsAllFlag: true,
|
|
58
66
|
reads: [".agents/workflows-amend/**/*.md"],
|
|
59
67
|
execute: runWorkflowAmendList,
|
|
60
68
|
},
|
package/package.json
CHANGED
|
@@ -27,6 +27,27 @@ Stage only the files this skill produces or modifies. Another agent may be worki
|
|
|
27
27
|
- **RFC pipeline**: create → audit → enhance → plan → implement (includes review → fix)
|
|
28
28
|
- **ADR pipeline**: create → implement (includes review → fix)
|
|
29
29
|
|
|
30
|
+
## Review triggers (T1/T2/T3)
|
|
31
|
+
|
|
32
|
+
Reviews fire on mandatory triggers across the pipeline lifecycle, not only at delivery.
|
|
33
|
+
|
|
34
|
+
| Trigger | Point | Covered by |
|
|
35
|
+
| --- | --- | --- |
|
|
36
|
+
| T1 — plan review | Before implementation starts | `fo-idea-audit` + `fo-idea-enhance` + `fo-idea-plan` grilling (existing — declared, unchanged) |
|
|
37
|
+
| T2 — checkpoint review | A step checkpoint that records an approach change vs. the plan, or a plan step that consumed >2 fix iterations | `fo-review` invocation scoped to the step diff, `independent` mode preferred |
|
|
38
|
+
| T3 — pre-delivery review | End of `fo-idea-implement` | Existing; `independent` mode by default in the full pipeline |
|
|
39
|
+
|
|
40
|
+
## Review blocking semantics
|
|
41
|
+
|
|
42
|
+
`fo-review` verdicts carry `blockLevel` (`pass | warning | soft-block | hard-block`), mapped to `verdict` for backward compatibility (`fo-fix` consumes `verdict` unchanged).
|
|
43
|
+
|
|
44
|
+
- **`hard-block` (`rejected`)** — the item must be corrected and then undergo a **full** re-review (not a delta on the flagged point) before it may proceed to stamping. At most two fix→re-review cycles inside one pipeline run; a third failure escalates to the operator regardless of mode. In queue mode the item stops before stamping and is recorded as blocked in the batch report; the batch continues.
|
|
45
|
+
- **`soft-block` (`needs-revision` + `escalation: operator`)** — interactive mode: the pipeline pauses and escalates to the operator via a structured question (`acknowledge and continue` / `redirect` / `abort`), presenting stop/redirect as first-class options to counter the continue-bias. Queue mode: the item is paused, recorded in the batch summary as `awaiting operator arbitration`, the arbitration question is appended to the queue's decision ledger (§Decision ledger), and the batch continues with the next item.
|
|
46
|
+
- **`warning` (`needs-revision`)** — findings are recorded as tracked observations; unresolved warnings at T3 escalate to `soft-block`.
|
|
47
|
+
- **`pass` (`approved`)** — no fracture signals; zero findings.
|
|
48
|
+
|
|
49
|
+
**Queue-mode resume:** a parked item resumes by re-invoking the orchestrator with the same manifest — `queue.validate` derives the continuation point from document status (the queue resume contract). Parking never leaves an item stranded without a defined re-entry path. `blocked` remains report language only — never persisted into RFC frontmatter or queue manifests.
|
|
50
|
+
|
|
30
51
|
## Minimality ladder
|
|
31
52
|
|
|
32
53
|
Before writing implementation code, climb the minimality ladder. Stop at the first rung that holds — that is your implementation. The ladder runs after you understand the problem (read the code, trace the flow), not instead of it.
|
|
@@ -229,6 +250,7 @@ When the orchestrator skill processes multiple documents (>=2), perform a contex
|
|
|
229
250
|
- `commits`: list of commit SHAs produced for this document
|
|
230
251
|
- `lessons`: 1-3 short freeform sentences capturing key errors, root causes, patterns discovered, or validator quirks encountered during this document's pipeline run
|
|
231
252
|
- `dependencies`: cross-RFC dependency notes (e.g., "RFC-YYYY depends on RFC-XXXX for schema field Z") — empty if none
|
|
253
|
+
- `unclosed`: list of `{ item, state: closed | unclosed | undecidable }` — mandatory when the item carried a checklist structure (§Tri-state closure marking); required in particular when `status` is `failed` or the item was parked
|
|
232
254
|
- `next`: id of the next document to process, or `null` if this was the last
|
|
233
255
|
2. **Release context** — explicitly treat all detailed context from the completed document as no longer actionable: file contents, search results, edit operations, intermediate reasoning. Retain only the checkpoint block. Release means treat as no longer actionable for reasoning, not delete or undo.
|
|
234
256
|
3. **Fresh start** — begin the next document with a fresh read phase: re-read the RFC file and all related documents (amends, supersedes, related RFCs, DNA invariants, AGENTS.md sections).
|
|
@@ -248,6 +270,7 @@ When the orchestrator skill implements a single RFC with >=5 plan steps, perform
|
|
|
248
270
|
- `commit`: SHA of the commit produced by this step
|
|
249
271
|
- `decisions`: 1-3 short freeform sentences capturing key micro-decisions made during this step (e.g., "used flag instead of new command", "skipped validator X because it's in package Y, not in scope")
|
|
250
272
|
- `errors`: list of errors encountered and fixed during this step — empty if none
|
|
273
|
+
- `unclosed`: list of `{ item, state: closed | unclosed | undecidable }` for every multi-item checklist the step carried — mandatory when a checklist exists (§Tri-state closure marking); three or more `undecidable` entries escalate to the operator
|
|
251
274
|
- `nextStep`: number of the next plan step, or `null` if this was the last
|
|
252
275
|
2. **Release step context** — treat all detailed context from the completed step as no longer actionable: codebase search results, file reads, edit operations, validation output. Retain only the step-checkpoint block and the RFC's plan file.
|
|
253
276
|
3. **Fresh start** — begin the next plan step with a fresh read of the plan file and the specific files the next step touches.
|
|
@@ -270,12 +293,46 @@ The beacon text must use `aiLanguage` per the language policy.
|
|
|
270
293
|
|
|
271
294
|
When a pipeline step fails and cannot be auto-fixed within 2 attempts (per §Command execution timeout discipline), emit a structured error checkpoint block in conversation output:
|
|
272
295
|
|
|
273
|
-
1. **Emit error checkpoint** — output a YAML block with: rfc, step, planStep (if within implement phase), error (command, exitCode, summary, attempts), partialState (filesModified, commits, rfcStatus), resumePoint.
|
|
296
|
+
1. **Emit error checkpoint** — output a YAML block with: rfc, step, planStep (if within implement phase), error (command, exitCode, summary, attempts), partialState (filesModified, commits, rfcStatus), resumePoint, unclosed (tri-state list per §Tri-state closure marking — mandatory here because a failing step always carries an implicit checklist of attempted sub-items).
|
|
274
297
|
2. **Stop the pipeline** — do not continue to the next pipeline step. The error is not auto-fixable; continuing would compound the problem. This is an **explicit exception** to the orchestrator's "no pauses between pipeline steps" constraint. The "no pauses" directive assumes the pipeline can proceed; when an error is unfixable after 2 attempts, continuing is impossible and the exception is justified. The pause is for error reporting, not for optional operator input.
|
|
275
298
|
3. **Report to operator** — present the error checkpoint in `aiLanguage` and ask the operator how to proceed: fix manually, skip the step, or abort the RFC.
|
|
276
299
|
|
|
277
300
|
The error checkpoint doubles as a resume marker: when resuming an interrupted session, scan for the last error checkpoint. If found, resume from the failed step using the partialState and resumePoint fields.
|
|
278
301
|
|
|
302
|
+
## Falsified-routes ledger
|
|
303
|
+
|
|
304
|
+
Plan files (`docs/plans/plan-*.md`) MAY carry a `## Falsified routes` section — the negative-knowledge ledger for the work item:
|
|
305
|
+
|
|
306
|
+
```markdown
|
|
307
|
+
## Falsified routes
|
|
308
|
+
|
|
309
|
+
| Route | Root cause | Falsified at | Forbidden retry |
|
|
310
|
+
| --- | --- | --- | --- |
|
|
311
|
+
| <approach tried> | <why it cannot work — the evidence, not the vibe> | <commit-sha or date> | yes \| no |
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
Rules for `fo-idea-implement` and `fo-fix`:
|
|
315
|
+
|
|
316
|
+
- **Append on abandon** — when an approach is abandoned after a real attempt (not merely considered and skipped), append a row with the route, the root cause discovered, and falsified-at evidence (commit SHA or date). Never write prose instead of rows.
|
|
317
|
+
- **Consult before proposing** — before proposing an alternative route, read the plan's `## Falsified routes` section. A `Forbidden retry: yes` row rejects a matching proposal unless the proposal states a new fact that invalidates the recorded root cause. A plan-prescribed route that matches a forbidden row counts as an approach change for this rule — consult applies even when the route was chosen by a previous session.
|
|
318
|
+
- **Rows are never deleted** — a superseded route gets a `revivedAt` annotation: annotate the row's Route cell as `<route> (revived <date>: <new fact that invalidates the root cause>)`, matching criterion-versioning discipline. An empty or absent section is legal: the ledger is required only when an approach was actually abandoned.
|
|
319
|
+
- `blocked` and `falsified` are report and ledger vocabulary — never persist them into RFC frontmatter or queue manifests.
|
|
320
|
+
|
|
321
|
+
### Blind-spot pass
|
|
322
|
+
|
|
323
|
+
After **two failed attempts on the same approach** within one work item — whether during step execution or the fix loop — and before the next retry or pivot, dispatch a clean-context re-examination using the same artifacts-only contract as `fo-review` `independent` mode: the problem statement, the falsified-routes table, the raw failing-run evidence, and the settled conclusion phrased as a question — never the executor's session narrative or self-assessment. The pass answers one question: _is the settled conclusion ("dead end", "impossible", "only option left") actually supported by evidence?_ Where no subagent primitive exists, degrade to an `isolated-inline` re-derive-from-artifacts pass and record that mode. The record lands in the session output and in the next step checkpoint's `decisions` field.
|
|
324
|
+
|
|
325
|
+
The pass runs once per approach — it never chains recursively. It answers a different question than the T2 checkpoint review (conclusion validity vs. implementation quality), so neither de-duplicates against the other.
|
|
326
|
+
|
|
327
|
+
## Tri-state closure marking
|
|
328
|
+
|
|
329
|
+
Checkpoint blocks and handoff documents declare their open items with a tri-state value — `closed | unclosed | undecidable` — so that "silently forgotten" is distinguishable from "done".
|
|
330
|
+
|
|
331
|
+
- **Mandatory-if-any:** wherever a checkpoint or handoff carries a multi-item checklist or unclosed-items structure, the `unclosed` list is mandatory and must state every item: `unclosed: [{ item, state: closed | unclosed | undecidable }]`. Where the anchor is a simple declare/verify with no checklist structure, `unclosed` may be absent entirely — the mandate binds the structure, not every anchor.
|
|
332
|
+
- **Absence is never success:** an item absent from `unclosed` after the checkpoint executes is treated as `undecidable`.
|
|
333
|
+
- **`undecidable` is explicit and legal:** an executor that cannot determine closure records `undecidable` — never silence.
|
|
334
|
+
- **Escalation:** a checkpoint carrying three or more `undecidable` items escalates to the operator instead of continuing — the tri-state exists to surface uncertainty, not to warehouse it.
|
|
335
|
+
|
|
279
336
|
## Pipeline continuation
|
|
280
337
|
|
|
281
338
|
When a pipeline step completes (audit, enhance, plan), the agent MUST proactively suggest the next step and offer to proceed. This is NOT automatic chaining — the agent asks the operator first. This applies when the operator is manually driving the pipeline step by step.
|
|
@@ -322,3 +379,71 @@ When the orchestrator skill processes multiple documents (>=2), emit a batch pla
|
|
|
322
379
|
The preview is informational — it does not pause for operator approval unless the operator explicitly requests confirmation. The operator's invocation of the orchestrator is the instruction to proceed.
|
|
323
380
|
|
|
324
381
|
The preview text must use `aiLanguage` per the language policy.
|
|
382
|
+
|
|
383
|
+
## Decision ledger
|
|
384
|
+
|
|
385
|
+
Every orchestrator run materializes a queue manifest (single-document runs are a one-item queue) and owns a **decision ledger** sibling: `docs/queues/<id>.decisions.yaml`. The ledger is the durable record of "what requires operator judgment" for that queue — committed, append-only, survives sessions, isolated per manifest so parallel batches in different sessions never share mutable decision state.
|
|
386
|
+
|
|
387
|
+
The ledger's `id` field equals the filename stem `<manifest-id>.decisions`, and its `queue` field equals the manifest `id` — `queue.validate` enforces both bindings (QUEUE-02) plus `Q-N` uniqueness (QUEUE-05), so a misplaced or copy-pasted ledger can never apply foreign decisions to this queue. `answered` and `auto-resolved` entries MUST carry `answer`, and every entry's `doc` MUST be a manifest item — violations surface as non-blocking QUEUE-08 warnings. Schema lives in `packages/forge/os/queue/types.ts` (`decisionLedgerSchema`).
|
|
388
|
+
|
|
389
|
+
Status vocabulary for `items[]` entries:
|
|
390
|
+
|
|
391
|
+
- `open` — awaiting the decision window; blocks execution (QUEUE-07) unless the entry is `parked`.
|
|
392
|
+
- `answered` — decided by the operator at the window; carries `answer` + `answeredAt`.
|
|
393
|
+
- `auto-resolved` — the agent applied its recommended option and logged it. Covers both resolved-by-inference rows emitted during maturation (shown at the window for dispute) and emergent questions auto-resolved during execution; carries `answer` + `answeredAt`.
|
|
394
|
+
- `deferred` — the operator deferred; the item is parked for this run.
|
|
395
|
+
|
|
396
|
+
Parking vocabulary: `parked: true` on an `open` entry means the _system_ parked the item pending arbitration — written only by the enumerated parking paths (execution hard-stop per §Auto-resolve and log, soft-block review arbitration). `deferred` means the _operator_ parked it at a window. Both make the item non-executable this run; `queue.validate`'s `next` skips them, and an item whose `dependsOn` target is parked is itself parked (cascade). QUEUE-07 is an error: an item derivable to the implement stage (RFC `pipelineStep: implement`, or a non-terminal ADR) that is NOT parked and carries ≥1 un-parked `open` entry blocks `queue.validate`. A parked entry never fires QUEUE-07 — the park is already the containment; it surfaces in the briefing's parked section and waits for the next window's arbitration. An un-parked `open` on an implementable item means "collected but never resolved" — its presence routes the run into the decision window rather than halting it, and the only suppression is resolving the entries.
|
|
397
|
+
|
|
398
|
+
The rendered human view is `docs/queues/<id>.briefing.md` — generated from the ledger, never the source of truth.
|
|
399
|
+
|
|
400
|
+
**Pending-decision markers.** Documents carry `> PENDING DECISION: Q-N — <one-line question>` blockquote markers at the point where an answer matters (RFC section, plan step). A document with open markers cannot transition to `accepted`, and an implementable document with open markers trips QUEUE-07. Markers lift during the resolution phase when the answer lands.
|
|
401
|
+
|
|
402
|
+
The ledger is append-only: changing an `answered` entry is forbidden. A disputed or superseded decision gets a new entry referencing the old `Q-N` — never an in-place edit. `blocked`, `parked`, and `deferred` are report/ledger vocabulary — never persisted into RFC frontmatter or queue manifests.
|
|
403
|
+
|
|
404
|
+
## Collect and finalize contract
|
|
405
|
+
|
|
406
|
+
Pipeline steps that produce operator-facing questions run in one of two modes:
|
|
407
|
+
|
|
408
|
+
- **`interview`** (standalone skill invocations — the operator is at the keyboard): ask inline, one question at a time, as today.
|
|
409
|
+
- **`collect`** (orchestrator-driven runs with a queue manifest): never call `ask_user_question` for pipeline questions. Emit each unresolved question as a ledger entry with `status: open`, a `resolutionPath`, and recommended options; apply all autonomous work; leave `PENDING DECISION` markers where an answer is required.
|
|
410
|
+
- **`finalize`** (the resolution phase after the window): consume `answered` entries, integrate them into the document, lift markers, complete the stage's stamps and commits. Finalize per document is atomic — a crash mid-document leaves markers intact and the next run re-finalizes idempotently.
|
|
411
|
+
|
|
412
|
+
Mode trigger: collect/finalize activate only under an orchestrator run carrying a manifest + ledger path. Everything else is `interview`.
|
|
413
|
+
|
|
414
|
+
## Decision window
|
|
415
|
+
|
|
416
|
+
The decision window is the single scheduled operator interaction of a queue run — placed after maturation, before execution. It doubles as the batch acceptance act: `draft → accepted` transitions happen in the resolution phase that follows the window, so the operator signs off having seen every trade-off at once.
|
|
417
|
+
|
|
418
|
+
Window mechanics:
|
|
419
|
+
|
|
420
|
+
- The orchestrator renders the ledger into `docs/queues/<id>.briefing.md`: batch header, batch policies, per-document decision blocks (question, `resolutionPath`, options with `recommended`, consequences), the resolved-by-inference list (disputable at a glance), and the parked-items section.
|
|
421
|
+
- The operator answers in free text — codes like `Q-03: B`, `all — per recommendations`, `Q-07: defer`. `ask_user_question` is legal only for ≤4 highest-risk decisions (it cannot carry open-ended answers).
|
|
422
|
+
- Batch `policies[]` collapse identical questions across documents — answer once, items inherit unless overridden.
|
|
423
|
+
- One bounded follow-up round is permitted only when an answer invalidates a drafted plan and surfaces a genuinely new trade-off; then the batch proceeds.
|
|
424
|
+
|
|
425
|
+
## Self-resolution ladder
|
|
426
|
+
|
|
427
|
+
Before any question reaches the ledger, the emitting skill MUST exhaust these rungs in order — a fact is looked up, never asked:
|
|
428
|
+
|
|
429
|
+
1. **codebase** — the answer is a fact in the repository; find it.
|
|
430
|
+
2. **convention** — derivable from DNA invariants, AGENTS.md rules, established patterns; record as inference.
|
|
431
|
+
3. **profile** — covered by `PREFERENCES.md`, `.agents/operator-profile.md`, or grilling `learned-principles.md` (`status: active`).
|
|
432
|
+
4. **policy** — already answered by a batch-level `policies[]` entry or an identical earlier question.
|
|
433
|
+
5. **none** — a genuine trade-off only the operator can settle → ledger entry.
|
|
434
|
+
|
|
435
|
+
Every ledger entry records which rung produced it (`resolutionPath`) — this disciplines the agent and gives the operator audit context. Inferences land in the ledger too (as briefing-visible "resolved-by-inference" rows) — the operator reviews them at the window but answers only genuine `none`-rung trade-offs.
|
|
436
|
+
|
|
437
|
+
## Auto-resolve and log
|
|
438
|
+
|
|
439
|
+
Questions discovered during execution (emergent questions) do not interrupt the operator. The agent applies its recommended option and appends a ledger entry with `status: auto-resolved` — append-only evidence, disputable post-factum via a follow-up document, never silently decided.
|
|
440
|
+
|
|
441
|
+
Only the **hard-stop** class parks an item instead of auto-resolving:
|
|
442
|
+
|
|
443
|
+
1. DNA-invariant changes or conflicts.
|
|
444
|
+
2. Security or privacy impact.
|
|
445
|
+
3. External-contract changes (Verbund, third-party APIs, published interfaces).
|
|
446
|
+
4. Irreversible or data-destructive operations.
|
|
447
|
+
5. Hard-block review verdicts surviving two fix→re-review cycles.
|
|
448
|
+
|
|
449
|
+
A hard-stopped question lands in the ledger as `status: open` + `parked: true`; the item parks, `dependsOn` dependents cascade-park, and the batch continues. These items surface for arbitration in the final batch report — or at the start of the next session with the same manifest.
|
|
@@ -49,7 +49,7 @@ The ecosystem has seven documentation surfaces. Each has a different audience an
|
|
|
49
49
|
| **architecture-dna.md** | `ref(forge.yaml bindings.paths.invariantsFile)` | AI agents + humans | New DNA invariant, invariant amendment, or invariant retirement |
|
|
50
50
|
| **Templates** | `packages/werkstatt-site/src/onboarding/templates/`, `packages/werkstatt-site/src/codegen/templates/` | Future apps/packages (scaffold time) | Change to what a new app or package should look like at creation time |
|
|
51
51
|
| **Generated artifacts** | `docs/ecosystem.generated.json`, `docs/command-manifest.generated.yaml`, `fleet/*.generated.yaml`, `*.generated.css` | AI agents (read-only projection) | **Never edit directly** — update the generator or registry, then regenerate |
|
|
52
|
-
| **
|
|
52
|
+
| **Command / ecosystem docs** | `docs/COMMANDS.md`, `docs/ecosystem.generated.yaml` | Humans + AI agents | New command, removed command, package graph change — regenerate via `docs.commands.generate` / `ecosystem.manifest.generate`, never hand-edit |
|
|
53
53
|
|
|
54
54
|
## Process
|
|
55
55
|
|
|
@@ -147,12 +147,12 @@ ref(forge.yaml bindings.commands.produce) --workspace=command.manifest.generate
|
|
|
147
147
|
|
|
148
148
|
Note: if the regeneration command is expensive or unavailable in the current session, document the need to regenerate in the session summary and move on.
|
|
149
149
|
|
|
150
|
-
#### 2g.
|
|
150
|
+
#### 2g. Command / ecosystem doc surfaces
|
|
151
151
|
|
|
152
152
|
- Were **commands** added, removed, or renamed?
|
|
153
153
|
- Did the **package graph** change (new package, removed package, new dependency)?
|
|
154
154
|
|
|
155
|
-
If yes,
|
|
155
|
+
If yes, regenerate the owned projections — `docs.commands.generate` refreshes `docs/command-manifest.generated.yaml` + `docs/COMMANDS.md`; `ecosystem.manifest.generate` refreshes `docs/ecosystem.generated.yaml` (the successor of the retired `docs/PACKAGE_GRAPH.md`). Never hand-edit generated files — update the generator or registry (see 2f).
|
|
156
156
|
|
|
157
157
|
### 3. Present analysis to the operator
|
|
158
158
|
|
|
@@ -264,7 +264,7 @@ Skills that delegate to `fo-doc-audit`:
|
|
|
264
264
|
- **`fo-fix`** step 5 ("Documentation audit") — invokes `fo-doc-audit`.
|
|
265
265
|
- **`fo-fix`** merge conflict resolution step 4 ("Documentation audit") — invokes `fo-doc-audit`.
|
|
266
266
|
- **`fo-idea-implement`** step 4.9 ("Documentation audit") — invokes `fo-doc-audit`.
|
|
267
|
-
- **`fo-idea-implement`**
|
|
267
|
+
- **`fo-idea-implement`** step 5.6 ("Documentation audit", ADR path) — invokes `fo-doc-audit`.
|
|
268
268
|
|
|
269
269
|
## Constraints
|
|
270
270
|
|
|
@@ -9,7 +9,7 @@ languagePolicy: ref(PREFERENCES.md)
|
|
|
9
9
|
bindings:
|
|
10
10
|
requires: [paths.invariantsFile]
|
|
11
11
|
optional: []
|
|
12
|
-
triggerPhrases: ["explore this idea", "let me think about this", "what are the options for", "what if we"]
|
|
12
|
+
triggerPhrases: ["нам надо закрыть открытые вопросы", "explore this idea", "let me think about this", "what are the options for", "what if we"]
|
|
13
13
|
---
|
|
14
14
|
|
|
15
15
|
<!--
|
|
@@ -23,6 +23,7 @@ triggerPhrases: ["explore this idea", "let me think about this", "what are the o
|
|
|
23
23
|
<item>RFC-1097: sweep — SKILL.md headers + classification fixes
|
|
24
24
|
|
|
25
25
|
Sweep batch 1: add Compass v2 headers to 45 SKILL.md files (purpose derived from frontmatter description). Fix non-skill-markdown exclusion to check filename not workspace-relative path (packages/AGENTS.md escaped it). Add .coverage to ignoredDirs.</item>
|
|
26
|
+
<item>RFC-1247: triggerPhrases vocabulary sync — mined operator phrasing applied to this skill's trigger set.</item>
|
|
26
27
|
</CHANGE_SUMMARY>
|
|
27
28
|
-->
|
|
28
29
|
|
|
@@ -9,7 +9,7 @@ languagePolicy: ref(PREFERENCES.md)
|
|
|
9
9
|
bindings:
|
|
10
10
|
requires: [commands.typecheck]
|
|
11
11
|
optional: [commands.test, paths.invariantsFile]
|
|
12
|
-
triggerPhrases: ["fix issues from review", "apply review findings and fix"
|
|
12
|
+
triggerPhrases: ["исправим", "примени findings", "fix all", "fix issues from review", "apply review findings and fix"]
|
|
13
13
|
---
|
|
14
14
|
|
|
15
15
|
<!--
|
|
@@ -20,9 +20,13 @@ triggerPhrases: ["fix issues from review", "apply review findings and fix", "ite
|
|
|
20
20
|
</non-goals>
|
|
21
21
|
</MODULE_CONTRACT>
|
|
22
22
|
<CHANGE_SUMMARY>
|
|
23
|
+
<item>RFC-1250: orchestrated-run contract — ambiguous findings auto-resolve
|
|
24
|
+
with auto-resolved ledger entries; hard-stop class parks the item instead of
|
|
25
|
+
asking.</item>
|
|
23
26
|
<item>RFC-1097: sweep — SKILL.md headers + classification fixes
|
|
24
27
|
|
|
25
28
|
Sweep batch 1: add Compass v2 headers to 45 SKILL.md files (purpose derived from frontmatter description). Fix non-skill-markdown exclusion to check filename not workspace-relative path (packages/AGENTS.md escaped it). Add .coverage to ignoredDirs.</item>
|
|
29
|
+
<item>RFC-1247: triggerPhrases vocabulary sync — mined operator phrasing applied to this skill's trigger set.</item>
|
|
26
30
|
</CHANGE_SUMMARY>
|
|
27
31
|
-->
|
|
28
32
|
|
|
@@ -87,10 +91,14 @@ If the review used the legacy format (`[Critical errors]`, `[Warnings]`, `[Concr
|
|
|
87
91
|
For each finding:
|
|
88
92
|
|
|
89
93
|
- If it includes a concrete line range or code snippet, apply the change directly.
|
|
90
|
-
- If it is ambiguous, ask the user before changing.
|
|
94
|
+
- If it is ambiguous, ask the user before changing — **except under an orchestrated queue run**: never call `ask_user_question` there. Auto-resolve the ambiguity with the recommended option and append a ledger entry `status: auto-resolved`; if the ambiguity falls in the hard-stop class (§Auto-resolve and log), append `status: open` + `parked: true` and park the item instead.
|
|
91
95
|
- Do not delete or weaken existing tests without explicit direction.
|
|
92
96
|
- Prefer minimal upstream fixes over downstream workarounds.
|
|
93
97
|
|
|
98
|
+
**Falsified-routes ledger** — before choosing a fix approach for a finding, read the plan's `## Falsified routes` section when the work item carries a plan file: a `Forbidden retry: yes` row rejects the approach unless you can state a new fact that invalidates its root cause. When a fix approach is abandoned after a real attempt, append a row (route, root cause, falsified-at evidence) before moving on — when no plan file exists, record the falsified route in the session output instead. See `_shared/fo-pipeline-conventions.md` §Falsified-routes ledger.
|
|
99
|
+
|
|
100
|
+
**Blind-spot pass after two failures on one approach** — after two failed attempts on the same fix approach, and before the next retry or pivot, run the clean-context blind-spot pass defined in `_shared/fo-pipeline-conventions.md` §Blind-spot pass.
|
|
101
|
+
|
|
94
102
|
After applying fixes, update any tests that should cover the change, then run the relevant package tests before the full build when that saves time.
|
|
95
103
|
|
|
96
104
|
### 3. Run scoped typecheck verification
|
|
@@ -155,7 +163,7 @@ If no source files were touched, skip this step.
|
|
|
155
163
|
|
|
156
164
|
This step is **always** performed — it is not optional and must not be skipped.
|
|
157
165
|
|
|
158
|
-
Invoke `fo-doc-audit` via the `skill` tool. It analyzes the session's changes, checks all documentation surfaces (AGENTS.md, README, Compass XML, `ref(forge.yaml bindings.paths.invariantsFile)`, templates, generated artifacts, COMMANDS.md
|
|
166
|
+
Invoke `fo-doc-audit` via the `skill` tool. It analyzes the session's changes, checks all documentation surfaces (AGENTS.md, README, Compass XML, `ref(forge.yaml bindings.paths.invariantsFile)`, templates, generated artifacts, generated command docs (COMMANDS.md, ecosystem.generated.yaml)), applies needed updates, and commits them separately. Wait for it to complete.
|
|
159
167
|
|
|
160
168
|
If `fo-doc-audit` reports that no updates are needed, state this explicitly and move on — the check itself is the mandatory part, not the outcome.
|
|
161
169
|
|