@warpgogol/forge 5.3.3 → 6.0.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 +48 -16
- 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 +39 -9
- 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 +326 -0
- package/dist/os/compass/handlers/compass-docs-validate.js.map +1 -0
- package/dist/os/compass/handlers/compass-inventory.d.ts.map +1 -1
- package/dist/os/compass/handlers/compass-inventory.js +5 -2
- package/dist/os/compass/handlers/compass-inventory.js.map +1 -1
- package/dist/os/compass/handlers/summary-record.d.ts +17 -3
- package/dist/os/compass/handlers/summary-record.d.ts.map +1 -1
- package/dist/os/compass/handlers/summary-record.js +107 -10
- package/dist/os/compass/handlers/summary-record.js.map +1 -1
- package/dist/os/compass/handlers/tests/forge-yaml-fixture.d.ts +18 -0
- package/dist/os/compass/handlers/tests/forge-yaml-fixture.d.ts.map +1 -0
- package/dist/os/compass/handlers/tests/forge-yaml-fixture.js +64 -0
- package/dist/os/compass/handlers/tests/forge-yaml-fixture.js.map +1 -0
- package/dist/os/compass/policy.d.ts +6 -1
- package/dist/os/compass/policy.d.ts.map +1 -1
- package/dist/os/compass/policy.js +8 -2
- package/dist/os/compass/policy.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/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/mission/handlers/archive.d.ts.map +1 -1
- package/dist/os/mission/handlers/archive.js +1 -2
- package/dist/os/mission/handlers/archive.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 +28 -5
- package/dist/os/rfc/handlers/implement-stamp.js.map +1 -1
- package/dist/os/rfc/handlers/validate.js +1 -1
- package/dist/os/rfc/rfc.module.d.ts.map +1 -1
- package/dist/os/rfc/rfc.module.js +27 -3
- package/dist/os/rfc/rfc.module.js.map +1 -1
- package/dist/os/rfc/types.d.ts +11 -0
- package/dist/os/rfc/types.d.ts.map +1 -1
- package/dist/os/rfc/types.js +1 -0
- 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 +140 -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 +72 -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 +46 -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 +24 -3
- package/dist/src/config/forge-config.d.ts.map +1 -1
- package/dist/src/config/forge-config.js +38 -7
- package/dist/src/config/forge-config.js.map +1 -1
- package/dist/src/onboarding/create.d.ts.map +1 -1
- package/dist/src/onboarding/create.js +26 -10
- package/dist/src/onboarding/create.js.map +1 -1
- package/dist/src/onboarding/doctor.d.ts.map +1 -1
- package/dist/src/onboarding/doctor.js +49 -2
- 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/onboarding/upgrade.d.ts.map +1 -1
- package/dist/src/onboarding/upgrade.js +24 -8
- package/dist/src/onboarding/upgrade.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 +42 -15
- 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 +50 -16
- package/os/compass/handlers/compass-audit-handler.ts +50 -9
- package/os/compass/handlers/compass-docs-validate.ts +359 -0
- package/os/compass/handlers/compass-inventory.ts +6 -3
- package/os/compass/handlers/summary-record.ts +118 -10
- 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 +15 -18
- package/os/compass/handlers/tests/compass-v2-contract.test.ts +38 -0
- package/os/compass/handlers/tests/forge-yaml-fixture.ts +69 -0
- package/os/compass/handlers/tests/summary-record.test.ts +152 -0
- package/os/compass/policy.ts +8 -2
- package/os/core/core.module.ts +147 -75
- package/os/core/docs-archive.test.ts +136 -0
- package/os/exploration/exploration.module.ts +3 -0
- package/os/mission/handlers/archive.ts +1 -2
- 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 +35 -5
- package/os/rfc/handlers/validate.ts +1 -1
- package/os/rfc/rfc.module.ts +29 -3
- package/os/rfc/types.ts +17 -1
- package/os/rfc/verification-emit.test.ts +305 -0
- package/os/rfc/verification-evidence.ts +155 -24
- package/os/rfc/verification-refresh.test.ts +222 -1
- package/os/rfc/verification-refresh.ts +80 -38
- package/os/session/handlers/save.ts +41 -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-compass-annotate/SKILL.md +1 -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 +6 -8
- package/skills/fo/fo-idea-audit/SKILL.md +1 -1
- package/skills/fo/fo-idea-create-rfc/SKILL.md +3 -2
- 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 +57 -13
- 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 +4 -3
- package/skills/fo/fo-session-save/SKILL.md +1 -1
- 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 +106 -57
- package/src/onboarding/create.ts +25 -9
- package/src/onboarding/doctor.ts +51 -2
- package/src/onboarding/init.ts +8 -3
- package/src/onboarding/upgrade.ts +36 -6
- package/src/pipeline-status.ts +32 -8
- package/src/tests/bindings-schema.test.ts +53 -1
- package/src/tests/cli-flags.test.ts +20 -0
- package/src/tests/cli-output.test.ts +13 -7
- package/src/tests/doctor-bindings.test.ts +7 -2
- package/src/tests/doctor-skills-unmanaged.test.ts +145 -0
- package/src/tests/fixtures/agents-generate-business-before.txt +7 -7
- package/src/tests/forge-config.test.ts +106 -2
- package/src/tests/implement-stamp.test.ts +38 -0
- package/src/tests/session-handlers.test.ts +33 -0
- package/src/tests/skill-validate.test.ts +180 -0
- package/src/tests/upgrade.test.ts +60 -0
- package/src/types.ts +13 -1
- package/src/utils/generated-marker.ts +28 -0
- package/src/validators/skill-validate.ts +43 -16
- package/skills/fo/fo-idea-implement/ADR-FLOW.md +0 -179
- package/skills/fo/fo-review/AXES.md +0 -70
|
@@ -20,9 +20,25 @@ triggerPhrases: ["plan the implementation for this RFC", "create implementation
|
|
|
20
20
|
</non-goals>
|
|
21
21
|
</MODULE_CONTRACT>
|
|
22
22
|
<CHANGE_SUMMARY>
|
|
23
|
+
<item>RFC-1250: collect-mode contract — open questions and grilling emit to
|
|
24
|
+
the decision ledger; draft plan carries PENDING DECISION markers;
|
|
25
|
+
draft-to-accepted transition deferred to the resolution phase (window =
|
|
26
|
+
acceptance act).</item>
|
|
23
27
|
<item>RFC-1097: sweep — SKILL.md headers + classification fixes
|
|
24
28
|
|
|
25
29
|
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>
|
|
30
|
+
<item>RFC-1250: review wave — QUEUE-07 gates un-parked opens only, ledger binding checks, fail-closed loader
|
|
31
|
+
|
|
32
|
+
REVIEW-RFC-1250-01 findings: QUEUE-07 no longer fires on parked entries
|
|
33
|
+
(the park is the containment — a parked queue stays resumable and the
|
|
34
|
+
decision window arbitrates it); loader fails open only on ENOENT —
|
|
35
|
+
other read errors are QUEUE-01; ledger gains queue/id-stem binding
|
|
36
|
+
(QUEUE-02), Q-N uniqueness (QUEUE-05), and QUEUE-08 hygiene warnings
|
|
37
|
+
(missing answers, foreign doc ids); next excludes QUEUE-07-blocked
|
|
38
|
+
items; top-level decision totals added. Orchestrator pre-flight treats
|
|
39
|
+
QUEUE-07 as the window agenda — structural errors still stop the batch;
|
|
40
|
+
maturation skips parked/deferred items; uncovered imperative ask sites
|
|
41
|
+
gain collect riders (ADR code-trace, NC markers, audit-verdict guard).</item>
|
|
26
42
|
</CHANGE_SUMMARY>
|
|
27
43
|
-->
|
|
28
44
|
|
|
@@ -71,7 +87,11 @@ If all checks pass, proceed to step 0.3.
|
|
|
71
87
|
|
|
72
88
|
#### 0.3. Transition draft → accepted
|
|
73
89
|
|
|
74
|
-
If the RFC is `draft` or `reviewing` and has `enhancedAt` — the user's instruction to plan IS the architecture acceptance. Transition the RFC to `accepted
|
|
90
|
+
If the RFC is `draft` or `reviewing` and has `enhancedAt` — the user's instruction to plan IS the architecture acceptance. Transition the RFC to `accepted`.
|
|
91
|
+
|
|
92
|
+
**Collect mode exception:** inside an orchestrator-driven queue run the `draft → accepted` transition moves to the resolution phase — the answered decision window IS the acceptance act. In collect mode this skill persists the plan as a draft carrying `PENDING DECISION` markers and does NOT transition the RFC; the orchestrator's resolution phase finalizes (integrate answers, lift markers, transition + commit) after the window.
|
|
93
|
+
|
|
94
|
+
Standalone/interview-mode flow:
|
|
75
95
|
|
|
76
96
|
1. Set `status: accepted`.
|
|
77
97
|
2. Set `reviewers` — if the operator specified a reviewer at invocation, use that. Otherwise, read the default reviewer(s) from the `reviewers` field comment in `docs/rfcs/rfc-0000-template.md`. Set all listed default reviewers.
|
|
@@ -93,7 +113,7 @@ Then proceed to step 1.
|
|
|
93
113
|
**Inherited acceptance.** If the RFC has a `specRef` frontmatter field pointing to a spec with `status: accepted`, the acceptance inheritance path applies:
|
|
94
114
|
|
|
95
115
|
1. Check the audit report for this RFC — if the audit verdict is `approved`, the RFC MAY transition `draft → accepted` without a separate human acceptance ceremony. Record `reviewers` from the spec's `reviewers` field and note `via spec acceptance <spec-id>` in the commit message.
|
|
96
|
-
2. If the audit verdict is `needs-revision` or `rejected`, inheritance is void — a human decision is required. Do not transition; ask the operator.
|
|
116
|
+
2. If the audit verdict is `needs-revision` or `rejected`, inheritance is void — a human decision is required. Do not transition; ask the operator. **Collect mode:** instead of asking, append an `open` ledger entry (`stage: plan`) recording the audit verdict and the inheritance question, leave a `> PENDING DECISION: Q-N` marker in the draft plan, and do not transition — the window arbitrates whether the RFC proceeds or returns to enhance.
|
|
97
117
|
3. If the `specRef` points to a spec with `status: vendored` (not yet accepted), the RFC cannot progress past `draft` — V-SPEC-03 blocks it.
|
|
98
118
|
|
|
99
119
|
### 1. Read the RFC
|
|
@@ -125,13 +145,15 @@ Verify the RFC's claims about affected artifacts. Check:
|
|
|
125
145
|
|
|
126
146
|
After exploring, identify decisions the RFC leaves open — ambiguities, trade-offs, unspecified boundaries, conflicting constraints. These are **decisions**, not facts: if a fact can be found by exploring the codebase, look it up instead of asking.
|
|
127
147
|
|
|
128
|
-
|
|
148
|
+
**Collect mode:** under an orchestrated run, never call `ask_user_question` — climb the self-resolution ladder (`_shared/fo-pipeline-conventions.md` §Self-resolution ladder); genuine trade-offs append to the queue's decision ledger as `open` entries (`stage: plan`) with recommended options, and `> PENDING DECISION: Q-N` markers land in the draft plan at the steps that depend on the answer.
|
|
149
|
+
|
|
150
|
+
Interview mode: walk the user through each question **one at a time**. For each:
|
|
129
151
|
|
|
130
152
|
1. **Short context** — what the question is, why the plan needs it resolved, what changes depending on the answer.
|
|
131
153
|
2. **Options** — list 2-4 concrete options, **recommended option first**. Mark it with "(recommended)". Each option is a short label plus one line explaining the trade-off.
|
|
132
154
|
3. **Wait** — present the question and stop. Do not batch multiple questions; asking several at once is bewildering.
|
|
133
155
|
|
|
134
|
-
Use the `ask_user_question` tool when available, with the recommended option as the first entry. Otherwise, present the question inline and wait for the answer.
|
|
156
|
+
Use the `ask_user_question` tool when available (interview mode only), with the recommended option as the first entry. Otherwise, present the question inline and wait for the answer.
|
|
135
157
|
|
|
136
158
|
Typical questions that arise:
|
|
137
159
|
|
|
@@ -146,7 +168,7 @@ If exploration surfaces no open questions, skip this step and proceed directly t
|
|
|
146
168
|
|
|
147
169
|
### 4. Draft the plan
|
|
148
170
|
|
|
149
|
-
Copy `docs/plans/plan-0000-template.md` and fill it, incorporating the user's answers from step 3. Each step must have a **completion criterion** — a checkable condition that tells the agent the step is done.
|
|
171
|
+
Copy `docs/plans/plan-0000-template.md` and fill it, incorporating the user's answers from step 3. Each step must have a **completion criterion** — a checkable condition that tells the agent the step is done. Keep the template's `## Falsified routes` ledger section — implementing skills append to it when an approach is abandoned after a real attempt (see `_shared/fo-pipeline-conventions.md` §Falsified-routes ledger).
|
|
150
172
|
|
|
151
173
|
Step ordering follows the contract-first pattern:
|
|
152
174
|
|
|
@@ -168,7 +190,7 @@ Mark **human review points** on steps that:
|
|
|
168
190
|
|
|
169
191
|
### 5. Grill the plan
|
|
170
192
|
|
|
171
|
-
Invoke the `/grilling` skill to stress-test the draft plan before persisting. This is **mandatory**, not optional — every plan goes through grilling.
|
|
193
|
+
Invoke the `/grilling` skill to stress-test the draft plan before persisting. This is **mandatory**, not optional — every plan goes through grilling. **Collect mode:** grilling runs in `emit` mode — questions land in the ledger (`stage: plan`) with recommended answers; no interview.
|
|
172
194
|
|
|
173
195
|
The grilling checks:
|
|
174
196
|
|
|
@@ -9,7 +9,7 @@ languagePolicy: ref(PREFERENCES.md)
|
|
|
9
9
|
bindings:
|
|
10
10
|
requires: [commands.validateRfc]
|
|
11
11
|
optional: [paths.invariantsFile, paths.compassDocs]
|
|
12
|
-
triggerPhrases: ["review this code diff", "check code against Forge standards"
|
|
12
|
+
triggerPhrases: ["проверим всё ли сделали правильно", "проверь изменения", "review this session", "review this code diff", "check code against Forge standards"]
|
|
13
13
|
---
|
|
14
14
|
|
|
15
15
|
<!--
|
|
@@ -20,9 +20,24 @@ triggerPhrases: ["review this code diff", "check code against Forge standards",
|
|
|
20
20
|
</non-goals>
|
|
21
21
|
</MODULE_CONTRACT>
|
|
22
22
|
<CHANGE_SUMMARY>
|
|
23
|
+
<item>RFC-1250: soft-block arbitration appends to the queue decision ledger
|
|
24
|
+
(open / stage: review) under orchestrated runs.</item>
|
|
23
25
|
<item>RFC-1097: sweep — SKILL.md headers + classification fixes
|
|
24
26
|
|
|
25
27
|
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>
|
|
28
|
+
<item>RFC-1247: triggerPhrases vocabulary sync — mined operator phrasing applied to this skill's trigger set.</item>
|
|
29
|
+
<item>RFC-1250: review wave — QUEUE-07 gates un-parked opens only, ledger binding checks, fail-closed loader
|
|
30
|
+
|
|
31
|
+
REVIEW-RFC-1250-01 findings: QUEUE-07 no longer fires on parked entries
|
|
32
|
+
(the park is the containment — a parked queue stays resumable and the
|
|
33
|
+
decision window arbitrates it); loader fails open only on ENOENT —
|
|
34
|
+
other read errors are QUEUE-01; ledger gains queue/id-stem binding
|
|
35
|
+
(QUEUE-02), Q-N uniqueness (QUEUE-05), and QUEUE-08 hygiene warnings
|
|
36
|
+
(missing answers, foreign doc ids); next excludes QUEUE-07-blocked
|
|
37
|
+
items; top-level decision totals added. Orchestrator pre-flight treats
|
|
38
|
+
QUEUE-07 as the window agenda — structural errors still stop the batch;
|
|
39
|
+
maturation skips parked/deferred items; uncovered imperative ask sites
|
|
40
|
+
gain collect riders (ADR code-trace, NC markers, audit-verdict guard).</item>
|
|
26
41
|
</CHANGE_SUMMARY>
|
|
27
42
|
-->
|
|
28
43
|
|
|
@@ -41,6 +56,25 @@ This skill reviews **code** — `.ts`, `.js`, `.tsx`, `.astro`, `.css`, `.json`,
|
|
|
41
56
|
- For **RFCs, ADRs, architecture docs, or plans**, use `/fo-idea-audit` instead.
|
|
42
57
|
- For **iterative fix-then-build-then-commit**, use `/fo-fix`.
|
|
43
58
|
|
|
59
|
+
## Review modes: `inline` vs `independent`
|
|
60
|
+
|
|
61
|
+
`fo-review` accepts an `independent` flag. **Default: `true` when invoked from a pipeline orchestrator (`fo-idea-i-just-want-to-see-the-result`, `fo-idea-implement`), `false` for ad-hoc in-session review.**
|
|
62
|
+
|
|
63
|
+
In `independent` mode the reviewing pass executes in a **clean agent context** — a subagent dispatch where the platform provides one — carrying only artifacts:
|
|
64
|
+
|
|
65
|
+
- the diff range or file list to review;
|
|
66
|
+
- the rubric paths (this skill file, `_shared/fo-pipeline-conventions.md`);
|
|
67
|
+
- the anchor paths (AGENTS.md files, DNA invariants file, relevant specs);
|
|
68
|
+
- raw evidence (command output, failing logs, mechanical floor results).
|
|
69
|
+
|
|
70
|
+
**Never pass the executor's session narrative, self-assessment, or settled conclusions** — passing them defeats the isolation the mode exists for (veil-of-ignorance contract, shared with the falsified-routes blind-spot pass). The dispatched reviewer's prompt contains artifact paths and the rubric, not the executor's story.
|
|
71
|
+
|
|
72
|
+
Where the platform exposes no subagent primitive (or policy forbids dispatch), run an `isolated-inline` pass instead: re-derive conclusions only from the artifacts, deliberately ignoring the session's accumulated narrative, and record the fallback. **Never claim `subagent` isolation that did not happen** — the persisted report's `reviewer.isolation` field records the mode actually used (`subagent` | `isolated-inline` | `inline`), so independence is auditable rather than asserted.
|
|
73
|
+
|
|
74
|
+
An executor that narrows the reviewer's inputs — passing a self-authored summary instead of artifact paths — commits a scope-narrowing violation, itself reportable as a `soft-block` on the review process.
|
|
75
|
+
|
|
76
|
+
**Report persistence is the dispatcher's duty in `independent` mode.** A clean-context reviewer may be read-only and never writes files — it returns findings and verdict. The skill run that dispatched it performs steps 6–7 itself: it assembles the report, builds the YAML frontmatter (`reviewer.isolation` records the mode actually used), and writes the file to `docs/reviews/code/`. A persisted review report without the frontmatter block is a contract violation regardless of which side produced the prose.
|
|
77
|
+
|
|
44
78
|
## Process
|
|
45
79
|
|
|
46
80
|
### 1. Identify the diff
|
|
@@ -99,7 +133,7 @@ Read the context the diff claims to fit into:
|
|
|
99
133
|
|
|
100
134
|
Do not read every file in the repo — only the standards relevant to the diff.
|
|
101
135
|
|
|
102
|
-
### 4. Run the
|
|
136
|
+
### 4. Run the eight review axes
|
|
103
137
|
|
|
104
138
|
For each axis, check every item. An item either **passes**, **fails** (specific finding with evidence), or is **not applicable** (state why). Skip N/A items silently — do not pad the report.
|
|
105
139
|
|
|
@@ -177,6 +211,15 @@ If the invariants file is absent or the optional binding is unresolvable, state
|
|
|
177
211
|
- **Migration path**: existing apps' path to compliance is documented.
|
|
178
212
|
- **Security / privacy**: if the diff touches user data, PII, or external services, it addresses GDPR/privacy and secret management. No cookies (`document.cookie`, `Set-Cookie`). Client-side persistence is `localStorage` only; server-side is `unstorage`.
|
|
179
213
|
|
|
214
|
+
#### Axis H — Fracture inference
|
|
215
|
+
|
|
216
|
+
Will this output collapse at the next step? Judge the diff not only for what it is, but for whether the _process that produced it_ is honest:
|
|
217
|
+
|
|
218
|
+
- **Goal-closure authenticity** — claims of completion vs. verifiable evidence. A marked-done criterion whose checkable trace is absent or hand-waved is a fracture signal.
|
|
219
|
+
- **Ordering-constraint compliance** — skipped preconditions: plan steps executed out of order, dependencies implemented after their dependents, gates bypassed to reach a green run.
|
|
220
|
+
- **Unclosed-marking truthfulness** — deferred or open items actually declared as such; nothing silently dropped from the plan, todo list, or spec.
|
|
221
|
+
- **State-transmission completeness** — would a fresh agent recover this work without the conversation? Checkpoints, persisted reports, and committed artifacts carry the state — not session memory.
|
|
222
|
+
|
|
180
223
|
### 5. Check spec compliance
|
|
181
224
|
|
|
182
225
|
If an original request, spec, PRD, issue, or brief is available (from commit messages, linked issues, or session context), build a gap table:
|
|
@@ -199,7 +242,7 @@ Present the findings in this structure in `aiLanguage`. **Translate all labels,
|
|
|
199
242
|
```
|
|
200
243
|
## <Code Review in aiLanguage>: <diff range or file list>
|
|
201
244
|
|
|
202
|
-
### Verdict: <Approved | Needs revision | Rejected>
|
|
245
|
+
### Verdict: <Approved | Needs revision | Rejected> (blockLevel: <pass | warning | soft-block | hard-block>)
|
|
203
246
|
|
|
204
247
|
<2-3 sentence justification grounded in the most serious findings.>
|
|
205
248
|
|
|
@@ -228,6 +271,9 @@ Present the findings in this structure in `aiLanguage`. **Translate all labels,
|
|
|
228
271
|
### Axis G — Blind spots
|
|
229
272
|
<Findings or "No issues.">
|
|
230
273
|
|
|
274
|
+
### Axis H — Fracture inference
|
|
275
|
+
<Findings or "No issues.">
|
|
276
|
+
|
|
231
277
|
### Spec compliance
|
|
232
278
|
|
|
233
279
|
<Gap table or "No spec available — skipped.">
|
|
@@ -239,11 +285,22 @@ Present the findings in this structure in `aiLanguage`. **Translate all labels,
|
|
|
239
285
|
3. <Hard question.>
|
|
240
286
|
```
|
|
241
287
|
|
|
242
|
-
**Verdict criteria:**
|
|
288
|
+
**Verdict criteria (blocking model):**
|
|
289
|
+
|
|
290
|
+
Every verdict carries a `blockLevel` — the blocking semantics downstream pipeline skills act on. `verdict` is retained and **derived** from it for backward compatibility (`fo-fix` consumes `verdict` unchanged):
|
|
291
|
+
|
|
292
|
+
| `blockLevel` | `verdict` | Semantics |
|
|
293
|
+
| --- | --- | --- |
|
|
294
|
+
| `pass` | `approved` | Zero findings across all axes — no fracture signals |
|
|
295
|
+
| `warning` | `needs-revision` | Findings recorded as tracked observations; they must be answered, and unresolved warnings at T3 escalate to `soft-block` |
|
|
296
|
+
| `soft-block` | `needs-revision` + `escalation: operator` | Directional deviation or process violation — suspends the item for operator arbitration (queue mode: item parked, arbitration question appended to the decision ledger as `open`/`stage: review`/`parked: true`, batch continues) |
|
|
297
|
+
| `hard-block` | `rejected` | Fundamental flaw — fix, then **full** re-review (not a delta on the flagged point) before the item may proceed to stamping |
|
|
298
|
+
|
|
299
|
+
- **Approved (`pass`)** — zero findings across all eight axes. Any finding, no matter how minor or cosmetic, disqualifies Approved and forces Needs revision. The rationale: downstream agents treat Approved as a stop signal and stop reading the findings — so even a trivial finding left under Approved gets silently ignored. If there is anything to fix, the verdict must say so.
|
|
300
|
+
- **Needs revision (`warning` | `soft-block`)** — one or more findings on any axis, regardless of severity. A one-line cosmetic rename is enough (`warning`). Escalate to `soft-block` when the deviation is directional or the review process itself was compromised (e.g. narrowed inputs). The agent must not downgrade to Approved based on severity — a finding is a finding.
|
|
301
|
+
- **Rejected (`hard-block`)** — fundamental flaw: the diff contradicts a DNA invariant, introduces a backward compatibility layer, or bypasses the storage policy.
|
|
243
302
|
|
|
244
|
-
|
|
245
|
-
- **Needs revision** — one or more findings on any axis, regardless of severity. A one-line cosmetic rename is enough. The agent must not downgrade to Approved based on severity — a finding is a finding.
|
|
246
|
-
- **Rejected** — fundamental flaw: the diff contradicts a DNA invariant, introduces a backward compatibility layer, or bypasses the storage policy.
|
|
303
|
+
The `blockLevel` → pipeline semantics (full re-review on `hard-block`, queue parking on `soft-block`, warning escalation at T3) are declared in `_shared/fo-pipeline-conventions.md` §Review blocking semantics.
|
|
247
304
|
|
|
248
305
|
### 7. Persist the review
|
|
249
306
|
|
|
@@ -265,8 +322,12 @@ reviewId: REVIEW-CODE-<YYYY-MM-DD>-<NN>
|
|
|
265
322
|
date: YYYY-MM-DD
|
|
266
323
|
reviewer:
|
|
267
324
|
skill: fo-review
|
|
325
|
+
isolation: <subagent | isolated-inline | inline> # the isolation mode actually used
|
|
268
326
|
model: <AI model identifier>
|
|
269
|
-
|
|
327
|
+
blockLevel: <pass | warning | soft-block | hard-block> # blocking semantics
|
|
328
|
+
verdict: <approved | needs-revision | rejected> # derived from blockLevel
|
|
329
|
+
escalation: <none | operator> # set when blockLevel = soft-block
|
|
330
|
+
observations: [] # tracked warnings carried to T3
|
|
270
331
|
diffRange: <fixed-point>...HEAD
|
|
271
332
|
filesReviewed:
|
|
272
333
|
- <file path>
|
|
@@ -9,7 +9,7 @@ languagePolicy: ref(PREFERENCES.md)
|
|
|
9
9
|
bindings:
|
|
10
10
|
requires: []
|
|
11
11
|
optional: [paths.invariantsFile]
|
|
12
|
-
triggerPhrases: ["
|
|
12
|
+
triggerPhrases: ["завершаем", "протокол завершения", "Завершаем эту сессию", "session retrospective", "End session"]
|
|
13
13
|
---
|
|
14
14
|
|
|
15
15
|
<!--
|
|
@@ -23,6 +23,7 @@ triggerPhrases: ["session retrospective", "triage session discoveries", "Зав
|
|
|
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
|
|
|
@@ -85,7 +86,7 @@ The agent reconstructs the current session's conversation from its context windo
|
|
|
85
86
|
3. Reconstruct the conversation from context — include every user message and assistant response you can recall from the current session, in chronological order. This is a best-effort reconstruction: the agent's context window is the source, not an external export tool.
|
|
86
87
|
4. **Redact sensitive information** — remove API keys, passwords, PII, and secret values before writing. Replace with `<redacted>`.
|
|
87
88
|
5. **Truncate very long tool outputs** — if a tool call produced thousands of lines of output, summarize it as `<tool output truncated, N lines>` in the content field. Keep the tool call name and key results.
|
|
88
|
-
6. Write the file
|
|
89
|
+
6. Write the file **atomically**: `write_to_file` to `docs/sessions/.raw/<timestamp>-session.atif.tmp`, then `mv` it to the same path without `.tmp` (rename is atomic). A parallel agent's `session.save` claims any `.atif` the moment it appears — this ordering guarantees it never sees a half-written transcript.
|
|
89
90
|
|
|
90
91
|
### 0c. Run session.save
|
|
91
92
|
|
|
@@ -450,7 +451,7 @@ If any operator insights were routed to `.agents/operator-profile.md`, offer the
|
|
|
450
451
|
|
|
451
452
|
Present a concise summary in `aiLanguage`. **ALL labels, headings, column names, and prose MUST be translated to `aiLanguage`** — the template below is structural only. Only identifiers (file paths, skill names, RFC/ADR ids, commit hashes) stay untranslated. This is non-negotiable: an English summary when `aiLanguage` is `ru` is a violation of this skill's language contract.
|
|
452
453
|
|
|
453
|
-
**Engineering Checkpoint
|
|
454
|
+
**Engineering Checkpoint:** The closing block follows the Engineering Checkpoint protocol defined in `_shared/fo-session-summary.md`. The agent MUST:
|
|
454
455
|
|
|
455
456
|
1. **Select mode** — analyze the session's changes. If the session changed architecture, runtime flow, state machines, persistence models, or public contracts, use **full mode** (6 sections). Otherwise, use **lightweight mode** (3 sections).
|
|
456
457
|
2. **Diagram selection** (full mode only) — apply the diagram selection rules table from `_shared/fo-session-summary.md` to determine if a Mermaid diagram is warranted. If no structural change warrants a diagram, explicitly state "No diagram: this session did not change system structure..."
|
|
@@ -60,7 +60,7 @@ Enhance saved session transcripts with semantic annotations, summaries, and qual
|
|
|
60
60
|
|
|
61
61
|
6. **Update the session file:**
|
|
62
62
|
- Update frontmatter: `summary`, `decisions`, refined `types`, corrected metadata.
|
|
63
|
-
- **Checkpoint fields
|
|
63
|
+
- **Checkpoint fields:** When the session produced substantial engineering work, populate the optional checkpoint frontmatter fields:
|
|
64
64
|
- `checkpoint` — object with `before`, `change`, `after` (each 1-2 sentences describing state N, what was done, state N+1)
|
|
65
65
|
- `systemDelta` — object with arrays: `changedContracts`, `changedSchemas`, `changedStateMachines`, `changedInvariants`, `changedPersistence`
|
|
66
66
|
- `diagrams` — array of objects: `type` (flowchart/sequenceDiagram/stateDiagram-v2/erDiagram/none), `scope` (current-system/session-delta), `caption`, `mermaid` (Mermaid syntax or empty string)
|
|
@@ -10,6 +10,7 @@ concerns: code-mutation
|
|
|
10
10
|
dependsOn: ['my-preferences']
|
|
11
11
|
languagePolicy: ref(PREFERENCES.md)
|
|
12
12
|
triggerPhrases:
|
|
13
|
+
- "закоммитим"
|
|
13
14
|
- "commit after request"
|
|
14
15
|
- "auto-commit changes"
|
|
15
16
|
- "step commit"
|
|
@@ -26,6 +27,7 @@ triggerPhrases:
|
|
|
26
27
|
<item>RFC-1097: sweep — SKILL.md headers + classification fixes
|
|
27
28
|
|
|
28
29
|
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>
|
|
30
|
+
<item>RFC-1247: triggerPhrases vocabulary sync — mined operator phrasing applied to this skill's trigger set.</item>
|
|
29
31
|
</CHANGE_SUMMARY>
|
|
30
32
|
-->
|
|
31
33
|
|
|
@@ -22,11 +22,23 @@ knowledge:
|
|
|
22
22
|
<item>RFC-1097: sweep — SKILL.md headers + classification fixes
|
|
23
23
|
|
|
24
24
|
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>
|
|
25
|
+
<item>RFC-1250: two modes — interview (standalone, interactive) and emit
|
|
26
|
+
(orchestrated runs: questions land in the queue decision ledger with
|
|
27
|
+
recommended answers, no interview).</item>
|
|
25
28
|
</CHANGE_SUMMARY>
|
|
26
29
|
-->
|
|
27
30
|
|
|
28
31
|
Before starting, read `PREFERENCES.md` at the repository root. If the file is missing or `aiLanguage` is unset, ask the operator once and create the file using the `my-preferences` skill semantics.
|
|
29
32
|
|
|
33
|
+
## Modes
|
|
34
|
+
|
|
35
|
+
Grilling runs in one of two modes — the caller selects:
|
|
36
|
+
|
|
37
|
+
- **`interview`** (default — standalone, operator-invoked runs): the interactive behavior below, one question at a time.
|
|
38
|
+
- **`emit`** (inside an orchestrator-driven queue run — `fo-idea-i-just-want-to-see-the-result` queue mode): never ask the operator. Generate the same questions you would have asked, climb the self-resolution ladder (`_shared/fo-pipeline-conventions.md` §Self-resolution ladder), and append each surviving question to the queue's decision ledger `docs/queues/<id>.decisions.yaml` as an `open` entry (`id: Q-N`, `doc`, `stage`, `question`, `resolutionPath`, `options` with `recommended: true` on your recommended answer, `status: open`). Branching questions are written conditionally ("if Q-3 resolves to X, then…"). The pipeline's decision window consumes the emitted entries.
|
|
39
|
+
|
|
40
|
+
Mode trigger: `emit` activates only when the invoking skill passes a queue manifest / ledger path; otherwise `interview`.
|
|
41
|
+
|
|
30
42
|
Read `learned-principles.md` (L2) at the start of each session to improve recommended answers. Apply only entries with `status: active`; skip entries with `status: stale`, `superseded`, or `archived`. Principles with `confirmations >= 3` may be applied autonomously — but re-evaluate if context changes.
|
|
31
43
|
|
|
32
44
|
Interview me relentlessly about every aspect of this plan until we reach a shared understanding. Walk down each branch of the design tree, resolving dependencies between decisions one-by-one. For each question, provide your recommended answer.
|
|
@@ -58,6 +58,8 @@ A **user-invoked** skill whose job is to point at your other user-invoked skills
|
|
|
58
58
|
|
|
59
59
|
_Avoid_: dispatcher, menu, registry, index, router procedure
|
|
60
60
|
|
|
61
|
+
_Applied instance_: `fo-idea-i-just-want-to-see-the-result` is the forge pipeline's router skill — the operator's single front door. Its Preconditions carry an intent-routing table that maps non-pipeline intents (review, fix, session-end, commit, mission work, exploration) to their standing skills before document-id detection; pipeline intents flow through unchanged, and the escape hatches stay directly invocable.
|
|
62
|
+
|
|
61
63
|
### Granularity
|
|
62
64
|
|
|
63
65
|
How finely you divide skills. Finer division spends one of the two loads: more **model-invoked** skills spend **context load** (more descriptions crowding the window and competing for attention); more **user-invoked** skills spend **cognitive load** (more for the human to remember and reach for). Two cuts guide the division. By **invocation**, split off a model-invoked skill where you have a distinct **leading word** to trigger it — a trigger word you actually use in your prompts. By **sequence**, split a run of **steps** where a step's **post-completion steps** need hiding, since isolating it in its own context clears what follows. Beware the reverse: merging sequences exposes each step's post-completion steps to what follows, inviting premature completion.
|
|
@@ -19,6 +19,7 @@ languagePolicy: ref(PREFERENCES.md)
|
|
|
19
19
|
<item>RFC-1097: sweep — SKILL.md headers + classification fixes
|
|
20
20
|
|
|
21
21
|
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>
|
|
22
|
+
<item>RFC-1247: close RFC-1247 review r2 — CHANGE_SUMMARY items on six touched skills, fo-handoff in AGENTS enumeration, glossary applied-instance pointer, recorded per-skill phrase split</item>
|
|
22
23
|
</CHANGE_SUMMARY>
|
|
23
24
|
-->
|
|
24
25
|
|
|
@@ -37,7 +38,7 @@ Two choices, trading different costs:
|
|
|
37
38
|
|
|
38
39
|
Pick model-invocation only when the agent must reach the skill on its own, or another skill must. If it only ever fires by hand, make it user-invoked and pay no context load.
|
|
39
40
|
|
|
40
|
-
When user-invoked skills multiply past what you can remember, that piled-up cognitive load is cured by a **router skill**: one user-invoked skill that names the others and when to reach for each.
|
|
41
|
+
When user-invoked skills multiply past what you can remember, that piled-up cognitive load is cured by a **router skill**: one user-invoked skill that names the others and when to reach for each. (Applied instance: `fo-idea-i-just-want-to-see-the-result` — see GLOSSARY.md.)
|
|
41
42
|
|
|
42
43
|
## Writing the description
|
|
43
44
|
|
package/src/cli-flags.ts
CHANGED
|
@@ -12,6 +12,10 @@ with `TypeError: targetId.toLowerCase is not a function`.</purpose>
|
|
|
12
12
|
</MODULE_CONTRACT>
|
|
13
13
|
<CHANGE_SUMMARY>
|
|
14
14
|
<item>Standalone port of kernel argv resolution for the forge CLI (RFC-0260 lineage): strict KERNEL-FLAG-01/02/03 + KERNEL-ARG-01 diagnostics for schema-carrying commands, legacy heuristic parse (with KERNEL-ARG-01) for schema-less commands; repeated single-value string flags diagnose instead of silently promoting to an array that crashes handlers; indexOf-based inline-value split preserves values containing "=" that split("=", 2) silently truncated.</item>
|
|
15
|
+
<item>Session-retro 2026-10-08: string[] flags greedily consume consecutive
|
|
16
|
+
bare tokens until the next --flag (`--files a b` → ["a","b"]), matching the
|
|
17
|
+
kernel argv parser; bare positionals without a preceding string[] flag still
|
|
18
|
+
emit KERNEL-ARG-01.</item>
|
|
15
19
|
</CHANGE_SUMMARY>
|
|
16
20
|
*/
|
|
17
21
|
|
|
@@ -227,11 +231,25 @@ function resolveStrict(
|
|
|
227
231
|
continue;
|
|
228
232
|
}
|
|
229
233
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
234
|
+
// string[] flags consume every following bare token — mirrors the kernel's
|
|
235
|
+
// resolveCommandFlags: positional args are never valid (KERNEL-ARG-01),
|
|
236
|
+
// so `--files a b` unambiguously means the value list [a, b].
|
|
237
|
+
if (spec.kind === "string[]") {
|
|
238
|
+
let consumed = 0;
|
|
239
|
+
while (index + 1 < rawArgv.length && !rawArgv[index + 1]!.startsWith("--")) {
|
|
240
|
+
addFlagValue(flags, flagName, rawArgv[index + 1]!);
|
|
241
|
+
index += 1;
|
|
242
|
+
consumed += 1;
|
|
243
|
+
}
|
|
244
|
+
if (consumed > 0) continue;
|
|
245
|
+
// fall through to the missing-value diagnostic
|
|
246
|
+
} else {
|
|
247
|
+
const next = rawArgv[index + 1];
|
|
248
|
+
if (typeof next === "string" && !next.startsWith("--")) {
|
|
249
|
+
addFlagValue(flags, flagName, next);
|
|
250
|
+
index += 1;
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
235
253
|
}
|
|
236
254
|
|
|
237
255
|
diagnostics.push({
|
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
</non-goals>
|
|
7
7
|
</MODULE_CONTRACT>
|
|
8
8
|
<CHANGE_SUMMARY>
|
|
9
|
-
<item>RFC-0661: added optional knowledge.budgets binding for hot/warm layer character budget overrides.</item>
|
|
10
9
|
<item>RFC-0662: added optional knowledge.retentionDays and knowledge.staleDays bindings for compaction overrides.</item>
|
|
11
10
|
<item>RFC-0704: added optional independentVersionPackages field to forgeConfigSchema for packages with autonomous npm versions.</item>
|
|
12
11
|
<item>RFC-1097: step 6 — compass.migrate codemod run
|
|
@@ -15,14 +14,15 @@ Mechanical v1 to v2 header migration across the workspace: 942 files rewritten
|
|
|
15
14
|
<item>RFC-1097: sweep — packages/forge + services clean
|
|
16
15
|
|
|
17
16
|
Sweep batch 2: real KEY_DECISIONS on 10 files, expanded purposes (CONTRACT-02/PURPOSE-02), headers on mission/index + gen-upstreams, sanitizeItemText in summary.record (literal Compass tags corrupted history), excludedPaths for wrangler types, test-fixtures testPattern. forge+services now 0 diagnostics under --mode error.</item>
|
|
18
|
-
<
|
|
17
|
+
<item>RFC-1224: preserve operator forge.yaml content on upgrade, promote adrImplementStamp binding</item>
|
|
18
|
+
<history>RFC-0391, RFC-0393, RFC-0537, RFC-0538, RFC-0539, RFC-0540, RFC-0543, RFC-0546, RFC-0639, RFC-0640, RFC-0643, RFC-0661, RFC-1224</history>
|
|
19
19
|
</CHANGE_SUMMARY>
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
22
|
import * as fs from "../utils/sync-fs.ts";
|
|
23
23
|
import path from "node:path";
|
|
24
24
|
import { z } from "zod";
|
|
25
|
-
import { parse as parseYaml } from "yaml";
|
|
25
|
+
import { parse as parseYaml, parseDocument } from "yaml";
|
|
26
26
|
import {
|
|
27
27
|
TERMINOLOGY_DEFAULTS,
|
|
28
28
|
compassPolicyOverridesSchema,
|
|
@@ -36,22 +36,27 @@ import { listStackProfiles, type StackProfile } from "../profiles/stack-profile.
|
|
|
36
36
|
|
|
37
37
|
export const forgeBindingsSchema = z.object({
|
|
38
38
|
schema: z.literal("forge/bindings@1"),
|
|
39
|
-
commands: z
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
39
|
+
commands: z
|
|
40
|
+
.object({
|
|
41
|
+
validateRfc: z.string().nullable().default(null),
|
|
42
|
+
validateAdr: z.string().nullable().default(null),
|
|
43
|
+
implementStamp: z.string().nullable().default(null),
|
|
44
|
+
adrImplementStamp: z.string().nullable().default(null),
|
|
45
|
+
typecheck: z.string().nullable().default(null),
|
|
46
|
+
test: z.string().nullable().default(null),
|
|
47
|
+
scopedBuild: z.string().nullable().default(null),
|
|
48
|
+
specValidate: z.string().nullable().default(null),
|
|
49
|
+
sessionSave: z.string().nullable().default(null),
|
|
50
|
+
// Semantic keys (RFC-0639) — domain-neutral, optional
|
|
51
|
+
validate: z.string().nullable().default(null),
|
|
52
|
+
produce: z.string().nullable().default(null),
|
|
53
|
+
verify: z.string().nullable().default(null),
|
|
54
|
+
preview: z.string().nullable().default(null),
|
|
55
|
+
lint: z.string().nullable().default(null),
|
|
56
|
+
// RFC-1224: consumer-defined command keys (e.g. createRfc) stay in the
|
|
57
|
+
// parsed config so resolveBinding can resolve them.
|
|
58
|
+
})
|
|
59
|
+
.passthrough(),
|
|
55
60
|
paths: z.object({
|
|
56
61
|
invariantsFile: z.string().nullable().default(null),
|
|
57
62
|
compassDocs: z.array(z.string()).default([]),
|
|
@@ -98,6 +103,7 @@ export interface ForgeBindings {
|
|
|
98
103
|
validateRfc: string | null;
|
|
99
104
|
validateAdr: string | null;
|
|
100
105
|
implementStamp: string | null;
|
|
106
|
+
adrImplementStamp: string | null;
|
|
101
107
|
typecheck: string | null;
|
|
102
108
|
test: string | null;
|
|
103
109
|
scopedBuild: string | null;
|
|
@@ -177,44 +183,50 @@ export interface ForgeMigrationAdapter {
|
|
|
177
183
|
// Schema (forge/config@1)
|
|
178
184
|
// ---------------------------------------------------------------------------
|
|
179
185
|
|
|
180
|
-
export const forgeConfigSchema = z
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
.
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
})
|
|
186
|
+
export const forgeConfigSchema = z
|
|
187
|
+
.object({
|
|
188
|
+
schema: z.literal("forge/config@1"),
|
|
189
|
+
project: z.object({
|
|
190
|
+
name: z.string().min(1),
|
|
191
|
+
stack: z.array(z.string()).default([]),
|
|
192
|
+
packageManager: z.enum(["pnpm", "npm", "yarn", "bun", "none"]).default("pnpm"),
|
|
193
|
+
// RFC-0640: optional domain field — absent means software-domain fallback
|
|
194
|
+
domain: z.string().optional(),
|
|
195
|
+
/** RFC-1240: local consumer identity — absent means no consumer-aware spec filtering. */
|
|
196
|
+
consumer: z.string().optional(),
|
|
197
|
+
}),
|
|
198
|
+
paths: z.object({
|
|
199
|
+
rfcsDir: z.string().default("docs/rfcs"),
|
|
200
|
+
adrsDir: z.string().default("docs/adrs"),
|
|
201
|
+
plansDir: z.string().default("docs/plans"),
|
|
202
|
+
auditsDir: z.string().default("docs/audits"),
|
|
203
|
+
specsDir: z.string().default("docs/specs"),
|
|
204
|
+
skillsDir: z.string().default(".agents/skills"),
|
|
205
|
+
sessionsDir: z.string().default("docs/sessions"),
|
|
206
|
+
}),
|
|
207
|
+
/** Bindings contract (RFC-0393). Optional — absent means no bindings. */
|
|
208
|
+
bindings: forgeBindingsSchema.optional(),
|
|
209
|
+
/** Skill packs (RFC-0539). Optional — absent means no project-local packs. */
|
|
210
|
+
skillPacks: z.array(forgeSkillPackSchema).optional(),
|
|
211
|
+
/** Migration adapters (RFC-0546). Optional — absent means built-in adapters only. */
|
|
212
|
+
migrationAdapters: z.array(forgeMigrationAdapterSchema).optional(),
|
|
213
|
+
/** Forge sync metadata (RFC-0543). Optional — absent means never synced. */
|
|
214
|
+
forge: z
|
|
215
|
+
.object({
|
|
216
|
+
syncedVersion: z.string().nullable().default(null),
|
|
217
|
+
})
|
|
218
|
+
.optional(),
|
|
219
|
+
/** RFC-0643: profile id — when present, loadForgeConfig loads the corresponding profiles/<id>.yaml */
|
|
220
|
+
// RFC-1118: accept the corrupted object form (whole StackProfile written by a
|
|
221
|
+
// previous buggy serialize) so loadForgeConfig can recover the declared id —
|
|
222
|
+
// a hard schema throw here would deadlock `forge upgrade`, the healing path.
|
|
223
|
+
profile: z.union([z.string(), z.object({ id: z.string().min(1) }).passthrough()]).optional(),
|
|
224
|
+
/** RFC-0704: packages with autonomous npm versions — ecosystem.commit skips platform bump when all staged files belong to these packages */
|
|
225
|
+
independentVersionPackages: z.array(z.string()).optional(),
|
|
226
|
+
// RFC-1224: consumer-owned top-level sections (e.g. `plugins:`) stay in the
|
|
227
|
+
// parsed config so full-serialization writes do not silently drop them.
|
|
228
|
+
})
|
|
229
|
+
.passthrough();
|
|
218
230
|
|
|
219
231
|
export interface ForgeConfig {
|
|
220
232
|
schema: "forge/config@1";
|
|
@@ -224,6 +236,8 @@ export interface ForgeConfig {
|
|
|
224
236
|
packageManager: "pnpm" | "npm" | "yarn" | "bun" | "none";
|
|
225
237
|
/** RFC-0640: optional domain field — absent means software-domain fallback */
|
|
226
238
|
domain?: string;
|
|
239
|
+
/** RFC-1240: local consumer identity — absent means no consumer-aware spec filtering */
|
|
240
|
+
consumer?: string;
|
|
227
241
|
};
|
|
228
242
|
paths: {
|
|
229
243
|
rfcsDir: string;
|
|
@@ -268,6 +282,10 @@ export const FORGE_CLI_BINDING_DEFAULTS: ForgeCliBindingDefault[] = [
|
|
|
268
282
|
key: "commands.implementStamp",
|
|
269
283
|
template: "forge rfc.implement.stamp --id {id} --implementation-commit {commit}",
|
|
270
284
|
},
|
|
285
|
+
{
|
|
286
|
+
key: "commands.adrImplementStamp",
|
|
287
|
+
template: "forge adr.implement.stamp --id {id} --implementation-commit {commit}",
|
|
288
|
+
},
|
|
271
289
|
{ key: "commands.specValidate", template: "forge spec.validate --spec={id} --json" },
|
|
272
290
|
{ key: "commands.sessionSave", template: "forge session.save --json" },
|
|
273
291
|
];
|
|
@@ -302,6 +320,7 @@ export function applyCliBindingDefaults(pm: string): ForgeBindings["commands"] {
|
|
|
302
320
|
validateRfc: null,
|
|
303
321
|
validateAdr: null,
|
|
304
322
|
implementStamp: null,
|
|
323
|
+
adrImplementStamp: null,
|
|
305
324
|
typecheck: null,
|
|
306
325
|
test: null,
|
|
307
326
|
scopedBuild: null,
|
|
@@ -471,6 +490,36 @@ export function serializeForgeConfig(config: ForgeConfig): Record<string, unknow
|
|
|
471
490
|
return out;
|
|
472
491
|
}
|
|
473
492
|
|
|
493
|
+
// ---------------------------------------------------------------------------
|
|
494
|
+
// YAML document patching — RFC-1224
|
|
495
|
+
// ---------------------------------------------------------------------------
|
|
496
|
+
|
|
497
|
+
/**
|
|
498
|
+
* A single targeted write into forge.yaml: a dotted key path expressed as
|
|
499
|
+
* segments plus the value to set. `applyForgeYamlPatches` creates missing
|
|
500
|
+
* intermediate maps and preserves comments/formatting elsewhere in the file.
|
|
501
|
+
*/
|
|
502
|
+
export interface ForgeYamlPatch {
|
|
503
|
+
path: string[];
|
|
504
|
+
value: unknown;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* Apply targeted patches to a forge.yaml document without rewriting it.
|
|
509
|
+
* Returns the patched YAML text, or null when the document cannot be parsed —
|
|
510
|
+
* callers should fall back to full serialization in that case.
|
|
511
|
+
*/
|
|
512
|
+
export function applyForgeYamlPatches(rawYaml: string, patches: ForgeYamlPatch[]): string | null {
|
|
513
|
+
const doc = parseDocument(rawYaml);
|
|
514
|
+
if (doc.errors.length > 0) {
|
|
515
|
+
return null;
|
|
516
|
+
}
|
|
517
|
+
for (const patch of patches) {
|
|
518
|
+
doc.setIn(patch.path, patch.value);
|
|
519
|
+
}
|
|
520
|
+
return doc.toString();
|
|
521
|
+
}
|
|
522
|
+
|
|
474
523
|
// ---------------------------------------------------------------------------
|
|
475
524
|
// Forge root resolver — the single place that decides monorepo vs npm-installed
|
|
476
525
|
// ---------------------------------------------------------------------------
|