@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
package/src/onboarding/create.ts
CHANGED
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
</non-goals>
|
|
10
10
|
</MODULE_CONTRACT>
|
|
11
11
|
<CHANGE_SUMMARY>
|
|
12
|
-
<item>RFC-0643: pass profileId to runInit so forge.yaml gets a `profile` field.</item>
|
|
13
12
|
<item>RFC-0664: scaffold memory layer (.agents/memory/) after init.</item>
|
|
14
13
|
<item>RFC-0877: in-place mode only — --in-place flag required, no subdirectory creation, name derived from folder, strict empty-directory check (only .git/ tolerated).</item>
|
|
15
14
|
<item>RFC-1097: step 6 — compass.migrate codemod run
|
|
@@ -18,7 +17,8 @@ Mechanical v1 to v2 header migration across the workspace: 942 files rewritten
|
|
|
18
17
|
<item>RFC-1097: sweep — packages/forge + services clean
|
|
19
18
|
|
|
20
19
|
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>
|
|
21
|
-
<
|
|
20
|
+
<item>RFC-1224: preserve operator forge.yaml content on upgrade, promote adrImplementStamp binding</item>
|
|
21
|
+
<history>RFC-0544, RFC-0548, RFC-0550, RFC-0640, RFC-0643, RFC-1224</history>
|
|
22
22
|
</CHANGE_SUMMARY>
|
|
23
23
|
*/
|
|
24
24
|
|
|
@@ -32,6 +32,7 @@ import { scaffoldMemoryLayer } from "./memory-scaffold.ts";
|
|
|
32
32
|
import {
|
|
33
33
|
loadForgeConfig,
|
|
34
34
|
serializeForgeConfig,
|
|
35
|
+
applyForgeYamlPatches,
|
|
35
36
|
resolveForgeRoot,
|
|
36
37
|
resolvePackageManager,
|
|
37
38
|
applyCliBindingDefaults,
|
|
@@ -346,15 +347,30 @@ export async function runCreate(
|
|
|
346
347
|
const forgeYamlPath = path.join(targetDir, "forge.yaml");
|
|
347
348
|
if (await fio.exists(forgeYamlPath)) {
|
|
348
349
|
try {
|
|
349
|
-
const config = loadForgeConfig(targetDir);
|
|
350
350
|
const pm = resolvePackageManager(packageManager);
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
351
|
+
const commandDefaults = applyCliBindingDefaults(pm);
|
|
352
|
+
// RFC-1224: patch the document init just wrote instead of re-serializing —
|
|
353
|
+
// preserves comments/formatting and any schema-unknown sections.
|
|
354
|
+
const raw = await fio.readFile(forgeYamlPath);
|
|
355
|
+
const patched = applyForgeYamlPatches(raw, [
|
|
356
|
+
{ path: ["project", "packageManager"], value: pm },
|
|
357
|
+
...Object.entries(commandDefaults).map(([key, value]) => ({
|
|
358
|
+
path: ["bindings", "commands", key],
|
|
359
|
+
value,
|
|
360
|
+
})),
|
|
361
|
+
]);
|
|
362
|
+
if (patched !== null) {
|
|
363
|
+
await fio.writeFile(forgeYamlPath, patched);
|
|
364
|
+
} else {
|
|
365
|
+
const config = loadForgeConfig(targetDir);
|
|
366
|
+
config.project.packageManager = pm;
|
|
367
|
+
if (config.bindings) {
|
|
368
|
+
config.bindings.commands = commandDefaults;
|
|
369
|
+
}
|
|
370
|
+
// RFC-1118: serializeForgeConfig writes the declared profile id verbatim —
|
|
371
|
+
// never the resolved StackProfile object, never drops an unresolvable id.
|
|
372
|
+
await fio.writeFile(forgeYamlPath, stringifyYaml(serializeForgeConfig(config)));
|
|
354
373
|
}
|
|
355
|
-
// RFC-1118: serializeForgeConfig writes the declared profile id verbatim —
|
|
356
|
-
// never the resolved StackProfile object, never drops an unresolvable id.
|
|
357
|
-
await fio.writeFile(forgeYamlPath, stringifyYaml(serializeForgeConfig(config)));
|
|
358
374
|
} catch {
|
|
359
375
|
// Post-processing is best-effort — init already wrote a valid config
|
|
360
376
|
}
|
package/src/onboarding/doctor.ts
CHANGED
|
@@ -8,7 +8,6 @@ Checks for forge.yaml, AGENTS.md, PREFERENCES.md, .agents/skills/, docs/rfcs/,
|
|
|
8
8
|
</non-goals>
|
|
9
9
|
</MODULE_CONTRACT>
|
|
10
10
|
<CHANGE_SUMMARY>
|
|
11
|
-
<item>RFC-0664: added memory-layer health check (budget usage, gitignore coverage, daily-file leak risk).</item>
|
|
12
11
|
<item>RFC-0704: added independent-version-packages check — validates that paths in independentVersionPackages exist and contain package.json.</item>
|
|
13
12
|
<item>RFC-0941: added pack-manifests advisory check — validates forge.plugin.yaml existence and schema for each declared skill pack.</item>
|
|
14
13
|
<item>RFC-1097: step 6 — compass.migrate codemod run
|
|
@@ -17,7 +16,9 @@ Mechanical v1 to v2 header migration across the workspace: 942 files rewritten
|
|
|
17
16
|
<item>RFC-1097: sweep — packages/forge + services clean
|
|
18
17
|
|
|
19
18
|
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>
|
|
20
|
-
<
|
|
19
|
+
<item>RFC-1224: preserve operator forge.yaml content on upgrade, promote adrImplementStamp binding</item>
|
|
20
|
+
<item>RFC-1226: skills-unmanaged check — warn on SKILL.md-bearing dirs without .forge-managed marker</item>
|
|
21
|
+
<history>RFC-0391, RFC-0393, RFC-0524, RFC-0539, RFC-0540, RFC-0611, RFC-0640, RFC-0660, RFC-0661, RFC-0663, RFC-0664, RFC-0675, RFC-1224</history>
|
|
21
22
|
</CHANGE_SUMMARY>
|
|
22
23
|
*/
|
|
23
24
|
|
|
@@ -54,6 +55,7 @@ import { compactMemoryMd } from "./memory-compact.ts";
|
|
|
54
55
|
import { checkInvariants } from "./invariant-engine.ts";
|
|
55
56
|
import type { InvariantViolation } from "./invariant-engine.ts";
|
|
56
57
|
import { checkNpmToken, workshopNeedsWarpgogolToken } from "./npm-token-check.ts";
|
|
58
|
+
import { SKILL_MARKER_FILE } from "./skill-markers.ts";
|
|
57
59
|
import { execSync } from "../utils/sync-fs.ts";
|
|
58
60
|
import * as fs from "../utils/sync-fs.ts";
|
|
59
61
|
import type { ProfilePrerequisite } from "../profiles/profile-schema.ts";
|
|
@@ -142,6 +144,7 @@ const BINDING_COMMAND_KEYS = [
|
|
|
142
144
|
"commands.validateRfc",
|
|
143
145
|
"commands.validateAdr",
|
|
144
146
|
"commands.implementStamp",
|
|
147
|
+
"commands.adrImplementStamp",
|
|
145
148
|
"commands.typecheck",
|
|
146
149
|
"commands.test",
|
|
147
150
|
"commands.scopedBuild",
|
|
@@ -762,6 +765,49 @@ async function checkPackSkills(workspaceRoot: string, io: WorkspaceIO): Promise<
|
|
|
762
765
|
};
|
|
763
766
|
}
|
|
764
767
|
|
|
768
|
+
// ---------------------------------------------------------------------------
|
|
769
|
+
// Unmanaged skill directories (RFC-1226)
|
|
770
|
+
// ---------------------------------------------------------------------------
|
|
771
|
+
|
|
772
|
+
// Visibility only: a dir bearing SKILL.md without .forge-managed is
|
|
773
|
+
// consumer-owned per RFC-1154 — report it, never prune or block.
|
|
774
|
+
async function checkUnmanagedSkillDirs(workspaceRoot: string, io: WorkspaceIO): Promise<DoctorCheck> {
|
|
775
|
+
let config;
|
|
776
|
+
try {
|
|
777
|
+
config = loadForgeConfig(workspaceRoot);
|
|
778
|
+
} catch {
|
|
779
|
+
return { name: "skills-unmanaged", status: "pass", message: "No forge.yaml — unmanaged skill dir check skipped" };
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
const skillsDir = join(workspaceRoot, config.paths.skillsDir);
|
|
783
|
+
let entries;
|
|
784
|
+
try {
|
|
785
|
+
entries = await io.readdir(skillsDir);
|
|
786
|
+
} catch {
|
|
787
|
+
return { name: "skills-unmanaged", status: "pass", message: "skillsDir absent — nothing to scan" };
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
const unmanaged: string[] = [];
|
|
791
|
+
for (const entry of entries) {
|
|
792
|
+
if (!entry.isDirectory) continue;
|
|
793
|
+
const dir = join(skillsDir, entry.name);
|
|
794
|
+
// Support dirs (_shared/, knowledge-only dirs) are not skills — skip.
|
|
795
|
+
if (!(await io.exists(join(dir, "SKILL.md")))) continue;
|
|
796
|
+
if (await io.exists(join(dir, SKILL_MARKER_FILE))) continue;
|
|
797
|
+
unmanaged.push(entry.name);
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
if (unmanaged.length === 0) {
|
|
801
|
+
return { name: "skills-unmanaged", status: "pass", message: "all skill dirs forge-managed" };
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
return {
|
|
805
|
+
name: "skills-unmanaged",
|
|
806
|
+
status: "warn",
|
|
807
|
+
message: `${unmanaged.length} unmanaged skill dir(s): ${unmanaged.join(", ")} — consumer-owned (no ${SKILL_MARKER_FILE} marker). Port into a declared skillPacks pack to make them forge-managed, or leave as-is.`,
|
|
808
|
+
};
|
|
809
|
+
}
|
|
810
|
+
|
|
765
811
|
// ---------------------------------------------------------------------------
|
|
766
812
|
// Pack manifest diagnostics (RFC-0941)
|
|
767
813
|
// ---------------------------------------------------------------------------
|
|
@@ -1455,6 +1501,9 @@ export async function runDoctor(
|
|
|
1455
1501
|
const packManifestCheck = await checkPackManifests(workspaceRoot, fio);
|
|
1456
1502
|
checks.push(packManifestCheck);
|
|
1457
1503
|
|
|
1504
|
+
// RFC-1226: List unmanaged skill dirs under skillsDir (visibility only)
|
|
1505
|
+
checks.push(await checkUnmanagedSkillDirs(workspaceRoot, fio));
|
|
1506
|
+
|
|
1458
1507
|
// RFC-0704: Check independent version packages — paths must exist and contain package.json
|
|
1459
1508
|
const independentCheck = await checkIndependentVersionPackages(workspaceRoot, fio);
|
|
1460
1509
|
checks.push(independentCheck);
|
package/src/onboarding/init.ts
CHANGED
|
@@ -461,9 +461,9 @@ export function runInit(
|
|
|
461
461
|
}
|
|
462
462
|
}
|
|
463
463
|
|
|
464
|
-
// 5. Copy neutral RFC and
|
|
465
|
-
// Templates are copied from the forge package so new projects
|
|
466
|
-
//
|
|
464
|
+
// 5. Copy neutral RFC, ADR, and plan templates into the project's docs
|
|
465
|
+
// directories. Templates are copied from the forge package so new projects
|
|
466
|
+
// can create documents without falling back to the package's internal copy.
|
|
467
467
|
// Existing templates are never overwritten.
|
|
468
468
|
const templatesToCopy = [
|
|
469
469
|
{
|
|
@@ -476,6 +476,11 @@ export function runInit(
|
|
|
476
476
|
destRel: `${config.paths.adrsDir}/adr-0000-template.md`,
|
|
477
477
|
label: "docs/adrs/adr-0000-template.md",
|
|
478
478
|
},
|
|
479
|
+
{
|
|
480
|
+
src: path.join(forgeRoot, "os", "plan", "plan-0000-template.md"),
|
|
481
|
+
destRel: `${config.paths.plansDir}/plan-0000-template.md`,
|
|
482
|
+
label: "docs/plans/plan-0000-template.md",
|
|
483
|
+
},
|
|
479
484
|
];
|
|
480
485
|
for (const { src, destRel, label } of templatesToCopy) {
|
|
481
486
|
const destPath = path.join(workspaceRoot, destRel);
|
|
@@ -11,7 +11,6 @@ With --update-npm, also updates @warpgogol/forge from npm before syncing (skippe
|
|
|
11
11
|
</non-goals>
|
|
12
12
|
</MODULE_CONTRACT>
|
|
13
13
|
<CHANGE_SUMMARY>
|
|
14
|
-
<item>RFC-0611: added nested AGENTS.md generation after skill sync.</item>
|
|
15
14
|
<item>RFC-0663: added syncSharedKnowledge step to sync shared knowledge layer to .agents/skills/shared-knowledge/.</item>
|
|
16
15
|
<item>RFC-0664: added scaffoldMemoryLayer step to scaffold .agents/memory/ and .gitignore block.</item>
|
|
17
16
|
<item>RFC-1097: step 6 — compass.migrate codemod run
|
|
@@ -20,7 +19,8 @@ Mechanical v1 to v2 header migration across the workspace: 942 files rewritten
|
|
|
20
19
|
<item>RFC-1097: sweep — werkstatt-engine clean
|
|
21
20
|
|
|
22
21
|
Sweep batch 4: 73 Compass headers on headerless engine files (certification, component-runtime, isolation, evolution, testing), real KEY_DECISIONS on 75 files (kernel, cache, dht, swim, gitmesh, runtime), ~80 purpose expansions (CONTRACT-02/PURPOSE-02), non-goals on 13 CONTRACT-03 files, CS-07 history literal fix repo-wide (253 files). Policy: .template.ts/.template.astro excludedPaths. werkstatt-engine now 0 diagnostics.</item>
|
|
23
|
-
<
|
|
22
|
+
<item>RFC-1224: preserve operator forge.yaml content on upgrade, promote adrImplementStamp binding</item>
|
|
23
|
+
<history>RFC-0543, RFC-0611, RFC-1224</history>
|
|
24
24
|
</CHANGE_SUMMARY>
|
|
25
25
|
*/
|
|
26
26
|
|
|
@@ -35,10 +35,12 @@ import {
|
|
|
35
35
|
resolveForgeRoot,
|
|
36
36
|
loadForgeConfig,
|
|
37
37
|
serializeForgeConfig,
|
|
38
|
+
applyForgeYamlPatches,
|
|
38
39
|
resolvePmRunner,
|
|
39
40
|
resolvePmInstall,
|
|
40
41
|
type ForgeConfig,
|
|
41
42
|
type ForgeBindings,
|
|
43
|
+
type ForgeYamlPatch,
|
|
42
44
|
} from "../config/forge-config.ts";
|
|
43
45
|
import { FORGE_SKILLS, discoverPackSkills } from "../registry.ts";
|
|
44
46
|
import { syncKnowledgeFile } from "../knowledge/index.ts";
|
|
@@ -452,18 +454,38 @@ async function updateSyncedVersion(
|
|
|
452
454
|
workspaceRoot: string,
|
|
453
455
|
config: ForgeConfig,
|
|
454
456
|
version: string,
|
|
457
|
+
bindingsAdded: { key: string; value: string }[],
|
|
455
458
|
dryRun: boolean,
|
|
456
459
|
io: WorkspaceIO,
|
|
460
|
+
warn: (msg: string) => void,
|
|
457
461
|
): Promise<void> {
|
|
458
462
|
if (dryRun) return;
|
|
459
463
|
|
|
460
|
-
//
|
|
464
|
+
// Keep the in-memory config truthful for downstream steps (doctor).
|
|
461
465
|
config.forge = { syncedVersion: version };
|
|
462
466
|
|
|
463
|
-
//
|
|
467
|
+
// RFC-1224: patch the existing document — syncedVersion plus newly added
|
|
468
|
+
// binding defaults — instead of re-serializing, so consumer-owned keys,
|
|
469
|
+
// sections, comments and ordering survive the rewrite.
|
|
470
|
+
const patches: ForgeYamlPatch[] = [
|
|
471
|
+
{ path: ["forge", "syncedVersion"], value: version },
|
|
472
|
+
...bindingsAdded.map((b) => ({
|
|
473
|
+
path: ["bindings", ...b.key.split(".")],
|
|
474
|
+
value: b.value,
|
|
475
|
+
})),
|
|
476
|
+
];
|
|
477
|
+
const forgeYamlPath = path.join(workspaceRoot, "forge.yaml");
|
|
478
|
+
const raw = await io.readFile(forgeYamlPath).catch(() => null);
|
|
479
|
+
const patched = raw === null ? null : applyForgeYamlPatches(raw, patches);
|
|
480
|
+
if (patched !== null) {
|
|
481
|
+
await io.writeFile(forgeYamlPath, patched);
|
|
482
|
+
return;
|
|
483
|
+
}
|
|
484
|
+
warn(
|
|
485
|
+
"forge.upgrade: forge.yaml patch failed — falling back to full serialization (schema-unknown keys may be dropped)",
|
|
486
|
+
);
|
|
464
487
|
// RFC-1118: serializeForgeConfig writes the declared profile id verbatim —
|
|
465
488
|
// never the resolved StackProfile object, never drops an unresolvable id.
|
|
466
|
-
const forgeYamlPath = path.join(workspaceRoot, "forge.yaml");
|
|
467
489
|
await io.writeFile(forgeYamlPath, stringifyYaml(serializeForgeConfig(config)));
|
|
468
490
|
}
|
|
469
491
|
|
|
@@ -689,7 +711,15 @@ export async function runUpgrade(
|
|
|
689
711
|
|
|
690
712
|
// Step 5: Update forge.syncedVersion
|
|
691
713
|
if (!isDryRun) {
|
|
692
|
-
await updateSyncedVersion(
|
|
714
|
+
await updateSyncedVersion(
|
|
715
|
+
workspaceRoot,
|
|
716
|
+
config,
|
|
717
|
+
toVersion,
|
|
718
|
+
bindingsAdded,
|
|
719
|
+
false,
|
|
720
|
+
fio,
|
|
721
|
+
(msg) => context.logger.warn(msg),
|
|
722
|
+
);
|
|
693
723
|
}
|
|
694
724
|
|
|
695
725
|
// Step 5b: Generate nested AGENTS.md (RFC-0611). RFC-1153: the write path
|
package/src/pipeline-status.ts
CHANGED
|
@@ -19,9 +19,24 @@ os/ or kernel imports.</purpose>
|
|
|
19
19
|
<item>RFC-1140: steps 1-4 — shared resolver, queue module, registration
|
|
20
20
|
|
|
21
21
|
Extract pipeline-status derivation into packages/forge/src/pipeline-status.ts, refactor rfc.pipeline.status onto it, add os/queue module with queue.validate command, register in WORKSHOP_MODULE_MAP.forge + bin/cli.ts + package.json exports.</item>
|
|
22
|
+
<item>RFC-1250: decision-aware queue report — QueueItemReport gains kind +
|
|
23
|
+
decisions counts; `next` exclusion of parked/blocked items is computed by
|
|
24
|
+
the queue.validate caller (the resolver stays ledger-agnostic).</item>
|
|
22
25
|
<item>RFC-1140: step 6 — cover shared resolver and queue.validate
|
|
23
26
|
|
|
24
27
|
Add pipeline-status.test.ts (derivation matrix, order, next selection, ADR, skipped) and queue-validate.test.ts (schema errors, unknown/dup ids, id-filename mismatch, empty items, dependsOn warning, JSON shape). Fix queue derivation: pipelineStep is the stage after the last completed stage, not first incomplete — handles non-contiguous artifacts.</item>
|
|
28
|
+
<item>RFC-1250: review wave — QUEUE-07 gates un-parked opens only, ledger binding checks, fail-closed loader
|
|
29
|
+
|
|
30
|
+
REVIEW-RFC-1250-01 findings: QUEUE-07 no longer fires on parked entries
|
|
31
|
+
(the park is the containment — a parked queue stays resumable and the
|
|
32
|
+
decision window arbitrates it); loader fails open only on ENOENT —
|
|
33
|
+
other read errors are QUEUE-01; ledger gains queue/id-stem binding
|
|
34
|
+
(QUEUE-02), Q-N uniqueness (QUEUE-05), and QUEUE-08 hygiene warnings
|
|
35
|
+
(missing answers, foreign doc ids); next excludes QUEUE-07-blocked
|
|
36
|
+
items; top-level decision totals added. Orchestrator pre-flight treats
|
|
37
|
+
QUEUE-07 as the window agenda — structural errors still stop the batch;
|
|
38
|
+
maturation skips parked/deferred items; uncovered imperative ask sites
|
|
39
|
+
gain collect riders (ADR code-trace, NC markers, audit-verdict guard).</item>
|
|
25
40
|
</CHANGE_SUMMARY>
|
|
26
41
|
*/
|
|
27
42
|
|
|
@@ -244,6 +259,10 @@ export interface QueueItemReport {
|
|
|
244
259
|
status: QueueItemStatus;
|
|
245
260
|
/** First incomplete pipeline stage — present only when in-progress. */
|
|
246
261
|
pipelineStep?: PipelineStage;
|
|
262
|
+
/** Document kind — needed by queue.validate for QUEUE-07 (any non-terminal ADR is implementable). */
|
|
263
|
+
kind?: QueueDocumentKind;
|
|
264
|
+
/** Decision-ledger counts (RFC-1250) — present when the queue carries a sibling ledger. */
|
|
265
|
+
decisions?: { open: number; deferred: number; autoResolved: number };
|
|
247
266
|
}
|
|
248
267
|
|
|
249
268
|
/**
|
|
@@ -266,20 +285,20 @@ export async function deriveQueueItemStatus(
|
|
|
266
285
|
const implementedAt = fm["implementedAt"] ? String(fm["implementedAt"]) : undefined;
|
|
267
286
|
|
|
268
287
|
if (status === "implemented" || implementedAt) {
|
|
269
|
-
return { id: doc.id, status: "implemented" };
|
|
288
|
+
return { id: doc.id, status: "implemented", kind: doc.kind };
|
|
270
289
|
}
|
|
271
290
|
if (status === "rejected" || status === "superseded") {
|
|
272
|
-
return { id: doc.id, status: "skipped" };
|
|
291
|
+
return { id: doc.id, status: "skipped", kind: doc.kind };
|
|
273
292
|
}
|
|
274
293
|
|
|
275
294
|
// ADR pipeline is create → implement — no intermediate artifacts exist.
|
|
276
295
|
if (doc.kind === "adr") {
|
|
277
|
-
return { id: doc.id, status: "pending" };
|
|
296
|
+
return { id: doc.id, status: "pending", kind: doc.kind };
|
|
278
297
|
}
|
|
279
298
|
|
|
280
299
|
// RFC accepted means the plan step is done by definition.
|
|
281
300
|
if (status === "accepted") {
|
|
282
|
-
return { id: doc.id, status: "in-progress", pipelineStep: "implement" };
|
|
301
|
+
return { id: doc.id, status: "in-progress", pipelineStep: "implement", kind: doc.kind };
|
|
283
302
|
}
|
|
284
303
|
|
|
285
304
|
const enhancedAt = fm["enhancedAt"] ? String(fm["enhancedAt"]) : undefined;
|
|
@@ -302,13 +321,13 @@ export async function deriveQueueItemStatus(
|
|
|
302
321
|
if (stages[i]!.done) lastDone = i;
|
|
303
322
|
}
|
|
304
323
|
if (lastDone === -1) {
|
|
305
|
-
return { id: doc.id, status: "pending" };
|
|
324
|
+
return { id: doc.id, status: "pending", kind: doc.kind };
|
|
306
325
|
}
|
|
307
326
|
const nextStage = stages[lastDone + 1];
|
|
308
327
|
if (!nextStage) {
|
|
309
|
-
return { id: doc.id, status: "pending" };
|
|
328
|
+
return { id: doc.id, status: "pending", kind: doc.kind };
|
|
310
329
|
}
|
|
311
|
-
return { id: doc.id, status: "in-progress", pipelineStep: nextStage.stage };
|
|
330
|
+
return { id: doc.id, status: "in-progress", pipelineStep: nextStage.stage, kind: doc.kind };
|
|
312
331
|
}
|
|
313
332
|
|
|
314
333
|
export interface QueueReport {
|
|
@@ -317,7 +336,12 @@ export interface QueueReport {
|
|
|
317
336
|
next: string | null;
|
|
318
337
|
}
|
|
319
338
|
|
|
320
|
-
/**
|
|
339
|
+
/**
|
|
340
|
+
* Derive the full queue report, preserving manifest order. `next` selects
|
|
341
|
+
* the first pending/in-progress item; callers that need ledger-aware
|
|
342
|
+
* exclusion (RFC-1250 parked/QUEUE-07-blocked items) re-filter the returned
|
|
343
|
+
* items — the resolver itself stays ledger-agnostic.
|
|
344
|
+
*/
|
|
321
345
|
export async function deriveQueueReport(
|
|
322
346
|
workspaceRoot: string,
|
|
323
347
|
itemIds: string[],
|
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
</MODULE_CONTRACT>
|
|
8
8
|
<CHANGE_SUMMARY>
|
|
9
9
|
<item>RFC-0639: initial test suite for semantic command keys, terminology resolution, and applyCliBindingDefaults.</item>
|
|
10
|
+
<item>RFC-1224: adrImplementStamp schema/default coverage; consumer-defined command key passthrough.</item>
|
|
11
|
+
<item>RFC-1224: preserve operator forge.yaml content on upgrade, promote adrImplementStamp binding</item>
|
|
10
12
|
</CHANGE_SUMMARY>
|
|
11
13
|
*/
|
|
12
14
|
|
|
@@ -174,12 +176,14 @@ describe("RFC-0639: Terminology schema change", () => {
|
|
|
174
176
|
});
|
|
175
177
|
|
|
176
178
|
describe("RFC-0639: applyCliBindingDefaults", () => {
|
|
177
|
-
test("returns
|
|
179
|
+
test("returns 14 keys with semantic keys as null", () => {
|
|
178
180
|
const commands = applyCliBindingDefaults("pnpm");
|
|
179
181
|
// CLI-backed keys are non-null
|
|
180
182
|
expect(commands.validateRfc).not.toBeNull();
|
|
181
183
|
expect(commands.validateAdr).not.toBeNull();
|
|
182
184
|
expect(commands.implementStamp).not.toBeNull();
|
|
185
|
+
// RFC-1224: adr.implement.stamp promoted to a first-class default binding
|
|
186
|
+
expect(commands.adrImplementStamp).not.toBeNull();
|
|
183
187
|
expect(commands.specValidate).not.toBeNull();
|
|
184
188
|
expect(commands.sessionSave).not.toBeNull();
|
|
185
189
|
// Software-domain keys are null
|
|
@@ -312,3 +316,51 @@ describe("RFC-0639: resolveTerminology", () => {
|
|
|
312
316
|
expect(resolveTerminology(config, undefined, "source")).toBe("source file");
|
|
313
317
|
});
|
|
314
318
|
});
|
|
319
|
+
|
|
320
|
+
describe("RFC-1224: promoted + consumer-defined command keys", () => {
|
|
321
|
+
test("forgeBindingsSchema accepts adrImplementStamp", () => {
|
|
322
|
+
const result = forgeBindingsSchema.safeParse({
|
|
323
|
+
schema: "forge/bindings@1",
|
|
324
|
+
commands: {
|
|
325
|
+
adrImplementStamp:
|
|
326
|
+
"pnpm exec forge adr.implement.stamp --id {id} --implementation-commit {commit}",
|
|
327
|
+
},
|
|
328
|
+
paths: {
|
|
329
|
+
invariantsFile: null,
|
|
330
|
+
compassDocs: [],
|
|
331
|
+
reviewsDir: null,
|
|
332
|
+
handoffsDir: null,
|
|
333
|
+
sessionsDir: null,
|
|
334
|
+
},
|
|
335
|
+
});
|
|
336
|
+
expect(result.success).toBe(true);
|
|
337
|
+
if (result.success) {
|
|
338
|
+
expect(result.data.commands.adrImplementStamp).toBe(
|
|
339
|
+
"pnpm exec forge adr.implement.stamp --id {id} --implementation-commit {commit}",
|
|
340
|
+
);
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
test("forgeBindingsSchema retains consumer-defined command keys", () => {
|
|
345
|
+
const result = forgeBindingsSchema.safeParse({
|
|
346
|
+
schema: "forge/bindings@1",
|
|
347
|
+
commands: {
|
|
348
|
+
validateRfc: null,
|
|
349
|
+
createRfc: "pnpm exec forge rfc.create",
|
|
350
|
+
},
|
|
351
|
+
paths: {
|
|
352
|
+
invariantsFile: null,
|
|
353
|
+
compassDocs: [],
|
|
354
|
+
reviewsDir: null,
|
|
355
|
+
handoffsDir: null,
|
|
356
|
+
sessionsDir: null,
|
|
357
|
+
},
|
|
358
|
+
});
|
|
359
|
+
expect(result.success).toBe(true);
|
|
360
|
+
if (result.success) {
|
|
361
|
+
expect((result.data.commands as Record<string, unknown>)["createRfc"]).toBe(
|
|
362
|
+
"pnpm exec forge rfc.create",
|
|
363
|
+
);
|
|
364
|
+
}
|
|
365
|
+
});
|
|
366
|
+
});
|
|
@@ -143,6 +143,26 @@ describe("resolveCliFlags — strict (schema-carrying) path", () => {
|
|
|
143
143
|
expect(flags["files"]).toEqual(["a", "b"]);
|
|
144
144
|
expect(errorRuleIds(diagnostics)).toEqual([]);
|
|
145
145
|
});
|
|
146
|
+
|
|
147
|
+
test("string[] flag consumes consecutive bare tokens as a value list", () => {
|
|
148
|
+
const cmd = command({
|
|
149
|
+
files: { kind: "string[]", description: "Files." },
|
|
150
|
+
id: { kind: "string", description: "Id." },
|
|
151
|
+
});
|
|
152
|
+
const { flags, diagnostics } = resolveCliFlags(["--files", "a", "b", "c", "--id", "x"], cmd);
|
|
153
|
+
expect(flags["files"]).toEqual(["a", "b", "c"]);
|
|
154
|
+
expect(flags["id"]).toBe("x");
|
|
155
|
+
expect(errorRuleIds(diagnostics)).toEqual([]);
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
test("string[] flag with no value still emits KERNEL-FLAG-02", () => {
|
|
159
|
+
const cmd = command({
|
|
160
|
+
files: { kind: "string[]", description: "Files." },
|
|
161
|
+
json2: { kind: "boolean", description: "Switch." },
|
|
162
|
+
});
|
|
163
|
+
const { diagnostics } = resolveCliFlags(["--files", "--json2"], cmd);
|
|
164
|
+
expect(errorRuleIds(diagnostics)).toEqual(["KERNEL-FLAG-02"]);
|
|
165
|
+
});
|
|
146
166
|
});
|
|
147
167
|
|
|
148
168
|
describe("resolveCliFlags — legacy (schema-less) path", () => {
|
|
@@ -8,6 +8,12 @@ renderNextSteps, renderIdeRecommendation, generateHelp.</purpose>
|
|
|
8
8
|
</MODULE_CONTRACT>
|
|
9
9
|
<CHANGE_SUMMARY>
|
|
10
10
|
<item>RFC-0542: initial CLI output rendering tests.</item>
|
|
11
|
+
<item>RFC-1231: step 1 — rename supportsAllSites to acceptsAllFlag
|
|
12
|
+
|
|
13
|
+
Mechanical sweep: the field only ever gated --all argv acceptance; fan-out
|
|
14
|
+
follows the parsed selector. Guard renamed assertAllSitesAllowed ->
|
|
15
|
+
assertAllFlagAccepted, message updated. 417 declaration sites + type
|
|
16
|
+
surfaces (KernelCommandMetadata, ForgeCommandMetadata) in one atomic pass.</item>
|
|
11
17
|
</CHANGE_SUMMARY>
|
|
12
18
|
*/
|
|
13
19
|
|
|
@@ -41,7 +47,7 @@ class MockRegistry implements CommandRegistry, ForgeModuleRegistry {
|
|
|
41
47
|
provider: "workspace" as const,
|
|
42
48
|
mutatesState: c.mutatesState,
|
|
43
49
|
requiresNetwork: c.requiresNetwork,
|
|
44
|
-
|
|
50
|
+
acceptsAllFlag: c.acceptsAllFlag,
|
|
45
51
|
timeoutMs: c.timeoutMs,
|
|
46
52
|
expectedDurationMs: c.expectedDurationMs,
|
|
47
53
|
longRunning: c.longRunning,
|
|
@@ -112,7 +118,7 @@ describe("generateHelp", () => {
|
|
|
112
118
|
name: "forge.init",
|
|
113
119
|
description: "Deploy forge into a project.",
|
|
114
120
|
scope: "workspace",
|
|
115
|
-
|
|
121
|
+
acceptsAllFlag: false,
|
|
116
122
|
flags: {},
|
|
117
123
|
cacheable: false,
|
|
118
124
|
execute: async () => ({ exitCode: 0 }),
|
|
@@ -121,7 +127,7 @@ describe("generateHelp", () => {
|
|
|
121
127
|
name: "forge.doctor",
|
|
122
128
|
description: "Diagnose forge state in an existing project.",
|
|
123
129
|
scope: "workspace",
|
|
124
|
-
|
|
130
|
+
acceptsAllFlag: false,
|
|
125
131
|
flags: {},
|
|
126
132
|
cacheable: false,
|
|
127
133
|
execute: async () => ({ exitCode: 0 }),
|
|
@@ -138,7 +144,7 @@ describe("generateHelp", () => {
|
|
|
138
144
|
name: "forge.doctor",
|
|
139
145
|
description: "Diagnose forge state.",
|
|
140
146
|
scope: "workspace",
|
|
141
|
-
|
|
147
|
+
acceptsAllFlag: false,
|
|
142
148
|
flags: {},
|
|
143
149
|
cacheable: false,
|
|
144
150
|
execute: async () => ({ exitCode: 0 }),
|
|
@@ -147,7 +153,7 @@ describe("generateHelp", () => {
|
|
|
147
153
|
name: "forge.init",
|
|
148
154
|
description: "Deploy forge.",
|
|
149
155
|
scope: "workspace",
|
|
150
|
-
|
|
156
|
+
acceptsAllFlag: false,
|
|
151
157
|
flags: {},
|
|
152
158
|
cacheable: false,
|
|
153
159
|
execute: async () => ({ exitCode: 0 }),
|
|
@@ -167,7 +173,7 @@ describe("generateHelp", () => {
|
|
|
167
173
|
name: "forge.init",
|
|
168
174
|
description: "Deploy forge.",
|
|
169
175
|
scope: "workspace",
|
|
170
|
-
|
|
176
|
+
acceptsAllFlag: false,
|
|
171
177
|
flags: {},
|
|
172
178
|
cacheable: false,
|
|
173
179
|
execute: async () => ({ exitCode: 0 }),
|
|
@@ -184,7 +190,7 @@ describe("generateHelp", () => {
|
|
|
184
190
|
name: "forge.init",
|
|
185
191
|
description: "Deploy forge.",
|
|
186
192
|
scope: "workspace",
|
|
187
|
-
|
|
193
|
+
acceptsAllFlag: false,
|
|
188
194
|
flags: {},
|
|
189
195
|
cacheable: false,
|
|
190
196
|
execute: async () => ({ exitCode: 0 }),
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
</MODULE_CONTRACT>
|
|
5
5
|
<CHANGE_SUMMARY>
|
|
6
6
|
<item>RFC-0540: initial doctor binding notices tests.</item>
|
|
7
|
+
<item>RFC-1224: adrImplementStamp added to notice inventory and fixtures.</item>
|
|
8
|
+
<item>RFC-1224: preserve operator forge.yaml content on upgrade, promote adrImplementStamp binding</item>
|
|
7
9
|
</CHANGE_SUMMARY>
|
|
8
10
|
*/
|
|
9
11
|
|
|
@@ -58,7 +60,7 @@ async function setupMinimalProject(dir: string): Promise<void> {
|
|
|
58
60
|
await writeFile(join(dir, "PREFERENCES.md"), "# Test", "utf8");
|
|
59
61
|
}
|
|
60
62
|
|
|
61
|
-
test("doctor emits defaultable-binding-null notices for all
|
|
63
|
+
test("doctor emits defaultable-binding-null notices for all 6 forge-CLI bindings when null", async () => {
|
|
62
64
|
await setupMinimalProject(tempDir);
|
|
63
65
|
await writeForgeYaml(
|
|
64
66
|
tempDir,
|
|
@@ -96,11 +98,12 @@ bindings:
|
|
|
96
98
|
|
|
97
99
|
const result = await runDoctor({ argv: [], flags: {} }, mockContext(tempDir));
|
|
98
100
|
const notices = result.data?.bindings?.notices ?? [];
|
|
99
|
-
expect(notices).toHaveLength(
|
|
101
|
+
expect(notices).toHaveLength(6);
|
|
100
102
|
const keys = notices.map((n) => n.key);
|
|
101
103
|
expect(keys).toContain("commands.validateRfc");
|
|
102
104
|
expect(keys).toContain("commands.validateAdr");
|
|
103
105
|
expect(keys).toContain("commands.implementStamp");
|
|
106
|
+
expect(keys).toContain("commands.adrImplementStamp");
|
|
104
107
|
expect(keys).toContain("commands.specValidate");
|
|
105
108
|
expect(keys).toContain("commands.sessionSave");
|
|
106
109
|
for (const notice of notices) {
|
|
@@ -131,6 +134,7 @@ bindings:
|
|
|
131
134
|
validateRfc: "custom rfc validate command"
|
|
132
135
|
validateAdr: "custom adr validate command"
|
|
133
136
|
implementStamp: "custom stamp command"
|
|
137
|
+
adrImplementStamp: "custom adr stamp command"
|
|
134
138
|
typecheck: null
|
|
135
139
|
test: null
|
|
136
140
|
scopedBuild: null
|
|
@@ -172,6 +176,7 @@ bindings:
|
|
|
172
176
|
validateRfc: "npx forge rfc.validate --id {id} --json"
|
|
173
177
|
validateAdr: "npx forge adr.validate --id {id} --json"
|
|
174
178
|
implementStamp: "npx forge rfc.implement.stamp --id {id} --implementation-commit {commit}"
|
|
179
|
+
adrImplementStamp: "npx forge adr.implement.stamp --id {id} --implementation-commit {commit}"
|
|
175
180
|
typecheck: null
|
|
176
181
|
test: null
|
|
177
182
|
scopedBuild: null
|