@entelligentsia/forgecli 0.21.0 → 1.0.2
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 +21 -0
- package/README.md +31 -33
- package/dist/CHANGELOG-forge-plugin.md +118 -0
- package/dist/CHANGELOG-pi.md +24 -1
- package/dist/bin/forgecli.d.ts +2 -0
- package/dist/bin/forgecli.js +6 -0
- package/dist/bin/forgecli.js.map +1 -0
- package/dist/extensions/forgecli/add-pipeline.js +1 -1
- package/dist/extensions/forgecli/add-pipeline.js.map +1 -1
- package/dist/extensions/forgecli/add-task.js +1 -1
- package/dist/extensions/forgecli/add-task.js.map +1 -1
- package/dist/extensions/forgecli/approve.js +17 -2
- package/dist/extensions/forgecli/approve.js.map +1 -1
- package/dist/extensions/forgecli/calibrate.js +11 -8
- package/dist/extensions/forgecli/calibrate.js.map +1 -1
- package/dist/extensions/forgecli/collate.js +1 -1
- package/dist/extensions/forgecli/collate.js.map +1 -1
- package/dist/extensions/forgecli/commit.js +17 -2
- package/dist/extensions/forgecli/commit.js.map +1 -1
- package/dist/extensions/forgecli/enhance.js +1 -1
- package/dist/extensions/forgecli/enhance.js.map +1 -1
- package/dist/extensions/forgecli/forge-artifact-tool.d.ts +6 -8
- package/dist/extensions/forgecli/forge-artifact-tool.js +80 -195
- package/dist/extensions/forgecli/forge-artifact-tool.js.map +1 -1
- package/dist/extensions/forgecli/forge-commands.js +57 -18
- package/dist/extensions/forgecli/forge-commands.js.map +1 -1
- package/dist/extensions/forgecli/forge-init/phase4-register.js +6 -7
- package/dist/extensions/forgecli/forge-init/phase4-register.js.map +1 -1
- package/dist/extensions/forgecli/forge-init/run-phases.d.ts +4 -0
- package/dist/extensions/forgecli/forge-init/run-phases.js +304 -0
- package/dist/extensions/forgecli/forge-init/run-phases.js.map +1 -0
- package/dist/extensions/forgecli/forge-init/verifiers.d.ts +14 -5
- package/dist/extensions/forgecli/forge-init/verifiers.js +79 -62
- package/dist/extensions/forgecli/forge-init/verifiers.js.map +1 -1
- package/dist/extensions/forgecli/forge-init.js +131 -76
- package/dist/extensions/forgecli/forge-init.js.map +1 -1
- package/dist/extensions/forgecli/forge-subagent.d.ts +9 -0
- package/dist/extensions/forgecli/forge-subagent.js +11 -6
- package/dist/extensions/forgecli/forge-subagent.js.map +1 -1
- package/dist/extensions/forgecli/forge-tools.d.ts +28 -4
- package/dist/extensions/forgecli/forge-tools.js +122 -73
- package/dist/extensions/forgecli/forge-tools.js.map +1 -1
- package/dist/extensions/forgecli/health-check.js +3 -3
- package/dist/extensions/forgecli/health-check.js.map +1 -1
- package/dist/extensions/forgecli/hook-dispatcher.d.ts +1 -1
- package/dist/extensions/forgecli/hooks/check-update.d.ts +8 -0
- package/dist/extensions/forgecli/hooks/check-update.js +29 -1
- package/dist/extensions/forgecli/hooks/check-update.js.map +1 -1
- package/dist/extensions/forgecli/hooks/post-init-hook.js +6 -6
- package/dist/extensions/forgecli/hooks/post-init-hook.js.map +1 -1
- package/dist/extensions/forgecli/hooks/post-sprint-hook.js +6 -6
- package/dist/extensions/forgecli/hooks/post-sprint-hook.js.map +1 -1
- package/dist/extensions/forgecli/hooks/triage-error.js +1 -0
- package/dist/extensions/forgecli/hooks/triage-error.js.map +1 -1
- package/dist/extensions/forgecli/implement.js +20 -2
- package/dist/extensions/forgecli/implement.js.map +1 -1
- package/dist/extensions/forgecli/index.js +39 -32
- package/dist/extensions/forgecli/index.js.map +1 -1
- package/dist/extensions/forgecli/lib/pipeline-guard.d.ts +41 -0
- package/dist/extensions/forgecli/lib/pipeline-guard.js +100 -0
- package/dist/extensions/forgecli/lib/pipeline-guard.js.map +1 -0
- package/dist/extensions/forgecli/loaders/persona-skill-loader.js +2 -2
- package/dist/extensions/forgecli/loaders/persona-skill-loader.js.map +1 -1
- package/dist/extensions/forgecli/migrate.d.ts +3 -0
- package/dist/extensions/forgecli/migrate.js +4 -2
- package/dist/extensions/forgecli/migrate.js.map +1 -1
- package/dist/extensions/forgecli/plan.js +21 -2
- package/dist/extensions/forgecli/plan.js.map +1 -1
- package/dist/extensions/forgecli/quiz-agent.js +7 -7
- package/dist/extensions/forgecli/quiz-agent.js.map +1 -1
- package/dist/extensions/forgecli/regenerate.js +49 -18
- package/dist/extensions/forgecli/regenerate.js.map +1 -1
- package/dist/extensions/forgecli/remove-command.js +1 -1
- package/dist/extensions/forgecli/remove-command.js.map +1 -1
- package/dist/extensions/forgecli/report-bug.js +1 -1
- package/dist/extensions/forgecli/report-bug.js.map +1 -1
- package/dist/extensions/forgecli/retrospective.js +9 -9
- package/dist/extensions/forgecli/retrospective.js.map +1 -1
- package/dist/extensions/forgecli/review-code.d.ts +13 -0
- package/dist/extensions/forgecli/review-code.js +62 -3
- package/dist/extensions/forgecli/review-code.js.map +1 -1
- package/dist/extensions/forgecli/review-plan.d.ts +13 -0
- package/dist/extensions/forgecli/review-plan.js +65 -3
- package/dist/extensions/forgecli/review-plan.js.map +1 -1
- package/dist/extensions/forgecli/skill-curator-subagent.d.ts +2 -1
- package/dist/extensions/forgecli/skill-curator-subagent.js +2 -1
- package/dist/extensions/forgecli/skill-curator-subagent.js.map +1 -1
- package/dist/extensions/forgecli/sprint-intake.js +6 -6
- package/dist/extensions/forgecli/sprint-intake.js.map +1 -1
- package/dist/extensions/forgecli/sprint-plan.js +9 -9
- package/dist/extensions/forgecli/sprint-plan.js.map +1 -1
- package/dist/extensions/forgecli/status-command.js +1 -1
- package/dist/extensions/forgecli/status-command.js.map +1 -1
- package/dist/extensions/forgecli/store-query.js +11 -11
- package/dist/extensions/forgecli/store-query.js.map +1 -1
- package/dist/extensions/forgecli/store-repair.js +7 -7
- package/dist/extensions/forgecli/store-repair.js.map +1 -1
- package/dist/extensions/forgecli/validate.js +17 -2
- package/dist/extensions/forgecli/validate.js.map +1 -1
- package/dist/forge-payload/.base-pack/commands/check-agent.md +22 -0
- package/dist/forge-payload/.base-pack/commands/new-sprint.md +22 -0
- package/dist/forge-payload/.base-pack/commands/plan-sprint.md +22 -0
- package/dist/forge-payload/.base-pack/commands/quiz-agent.md +2 -18
- package/dist/forge-payload/.base-pack/commands/retro.md +22 -0
- package/dist/forge-payload/.base-pack/commands/retrospective.md +2 -18
- package/dist/forge-payload/.base-pack/commands/sprint-intake.md +2 -18
- package/dist/forge-payload/.base-pack/commands/sprint-plan.md +2 -18
- package/dist/forge-payload/.base-pack/workflows/_fragments/friction-emit.md +2 -2
- package/dist/forge-payload/.base-pack/workflows/_fragments/generation-instructions.md +4 -4
- package/dist/forge-payload/.base-pack/workflows/_fragments/iron-laws.md +1 -1
- package/dist/forge-payload/.base-pack/workflows/architect_approve.md +13 -1
- package/dist/forge-payload/.base-pack/workflows/commit_task.md +12 -1
- package/dist/forge-payload/.base-pack/workflows/enhance.md +6 -6
- package/dist/forge-payload/.base-pack/workflows/fix_bug.md +1 -1
- package/dist/forge-payload/.base-pack/workflows/implement_plan.md +14 -2
- package/dist/forge-payload/.base-pack/workflows/migrate_structural.md +2 -2
- package/dist/forge-payload/.base-pack/workflows/orchestrate_task.md +20 -4
- package/dist/forge-payload/.base-pack/workflows/plan_task.md +14 -2
- package/dist/forge-payload/.base-pack/workflows/review_code.md +37 -7
- package/dist/forge-payload/.base-pack/workflows/review_plan.md +36 -6
- package/dist/forge-payload/.base-pack/workflows/run_sprint.md +2 -2
- package/dist/forge-payload/.base-pack/workflows/validate_task.md +37 -7
- package/dist/forge-payload/.claude-plugin/plugin.json +1 -1
- package/dist/forge-payload/.schemas/config.schema.json +0 -5
- package/dist/forge-payload/.schemas/enum-catalog.json +9 -13
- package/dist/forge-payload/.schemas/migrations.json +54 -0
- package/dist/forge-payload/agents/tomoshibi.md +150 -6
- package/dist/forge-payload/commands/add-pipeline.md +1 -1
- package/dist/forge-payload/commands/add-task.md +1 -1
- package/dist/forge-payload/commands/calibrate.md +4 -350
- package/dist/forge-payload/commands/check-agent.md +38 -0
- package/dist/forge-payload/commands/config.md +3 -113
- package/dist/forge-payload/commands/enhance.md +5 -32
- package/dist/forge-payload/commands/health.md +155 -13
- package/dist/forge-payload/commands/init.md +25 -31
- package/dist/forge-payload/commands/migrate.md +6 -154
- package/dist/forge-payload/commands/quiz-agent.md +2 -34
- package/dist/forge-payload/commands/rebuild.md +664 -0
- package/dist/forge-payload/commands/regenerate.md +2 -774
- package/dist/forge-payload/commands/remove.md +10 -13
- package/dist/forge-payload/commands/repair.md +187 -0
- package/dist/forge-payload/commands/search.md +73 -0
- package/dist/forge-payload/commands/status.md +105 -0
- package/dist/forge-payload/commands/store-query.md +2 -69
- package/dist/forge-payload/commands/store-repair.md +2 -183
- package/dist/forge-payload/commands/update-tools.md +4 -50
- package/dist/forge-payload/commands/update.md +64 -58
- package/dist/forge-payload/hooks/check-update.cjs +1 -1
- package/dist/forge-payload/hooks/post-init.cjs +2 -2
- package/dist/forge-payload/hooks/post-sprint.cjs +2 -2
- package/dist/forge-payload/hooks/triage-error.cjs +11 -10
- package/dist/forge-payload/init/phases/phase-1-collect.md +138 -0
- package/dist/forge-payload/init/phases/phase-2-discover.md +127 -0
- package/dist/forge-payload/init/phases/phase-3-materialize.md +113 -0
- package/dist/forge-payload/init/phases/phase-4-register.md +159 -0
- package/dist/forge-payload/integrity.json +21 -24
- package/dist/forge-payload/meta/fragments/tool-discipline.md +22 -0
- package/dist/forge-payload/meta/templates/meta-retro.md +28 -0
- package/dist/forge-payload/meta/workflows/_fragments/friction-emit.md +2 -2
- package/dist/forge-payload/meta/workflows/_fragments/generation-instructions.md +4 -4
- package/dist/forge-payload/meta/workflows/_fragments/iron-laws.md +1 -1
- package/dist/forge-payload/meta/workflows/meta-approve.md +13 -1
- package/dist/forge-payload/meta/workflows/meta-check-agent.md +138 -0
- package/dist/forge-payload/meta/workflows/meta-commit.md +12 -1
- package/dist/forge-payload/meta/workflows/meta-enhance.md +5 -5
- package/dist/forge-payload/meta/workflows/meta-fix-bug.md +1 -1
- package/dist/forge-payload/meta/workflows/meta-implement.md +13 -1
- package/dist/forge-payload/meta/workflows/meta-migrate.md +3 -3
- package/dist/forge-payload/meta/workflows/meta-new-sprint.md +84 -0
- package/dist/forge-payload/meta/workflows/meta-orchestrate.md +20 -4
- package/dist/forge-payload/meta/workflows/meta-plan-sprint.md +152 -0
- package/dist/forge-payload/meta/workflows/meta-plan-task.md +13 -1
- package/dist/forge-payload/meta/workflows/meta-retro.md +73 -0
- package/dist/forge-payload/meta/workflows/meta-review-implementation.md +37 -7
- package/dist/forge-payload/meta/workflows/meta-review-plan.md +36 -6
- package/dist/forge-payload/meta/workflows/meta-validate.md +37 -7
- package/dist/forge-payload/schemas/config.schema.json +0 -5
- package/dist/forge-payload/schemas/enum-catalog.json +9 -13
- package/dist/forge-payload/schemas/structure-manifest.json +6 -8
- package/dist/forge-payload/tools/artifact.cjs +295 -0
- package/dist/forge-payload/tools/banners.cjs +3 -4
- package/dist/forge-payload/tools/build-context-pack.cjs +1 -1
- package/dist/forge-payload/tools/check-structure.cjs +8 -3
- package/dist/forge-payload/tools/store-cli.cjs +67 -7
- package/dist/forge-payload/tools/substitute-placeholders.cjs +1 -1
- package/dist/forge-payload/tools/verify-apply.cjs +75 -0
- package/dist/forge-payload/tools/verify-phase.cjs +259 -0
- package/node_modules/@earendil-works/pi-agent-core/package.json +2 -2
- package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts +0 -17
- package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/models.generated.js +21 -38
- package/node_modules/@earendil-works/pi-ai/dist/models.generated.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/openai-codex-responses.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/openai-codex-responses.js +5 -4
- package/node_modules/@earendil-works/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.d.ts +2 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.js +5 -2
- package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/package.json +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/CHANGELOG.md +24 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/cli/file-processor.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/cli/file-processor.js +2 -3
- package/node_modules/@earendil-works/pi-coding-agent/dist/cli/file-processor.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/output-guard.d.ts +1 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/output-guard.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/output-guard.js +52 -22
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/output-guard.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/package-manager.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/package-manager.js +16 -4
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/package-manager.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/bash.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/bash.js +45 -50
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/edit.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/edit.js +43 -81
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/edit.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/file-mutation-queue.js +27 -12
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/file-mutation-queue.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/find.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/find.js +2 -3
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/find.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/grep.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/grep.js +3 -3
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/grep.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/ls.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/ls.js +5 -5
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/ls.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/path-utils.d.ts +2 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/path-utils.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/path-utils.js +37 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/path-utils.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/read.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/read.js +9 -8
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/read.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/write.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/write.js +20 -35
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/write.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-client.d.ts +3 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-client.js +64 -7
- package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-client.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-mode.js +15 -3
- package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/utils/clipboard-native.d.ts +3 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/utils/clipboard-native.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/utils/clipboard-native.js +14 -8
- package/node_modules/@earendil-works/pi-coding-agent/dist/utils/clipboard-native.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/utils/image-resize-core.d.ts +30 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/utils/image-resize-core.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/utils/image-resize-core.js +124 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/utils/image-resize-core.js.map +1 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/utils/image-resize-worker.d.ts +2 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/utils/image-resize-worker.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/utils/image-resize-worker.js +31 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/utils/image-resize-worker.js.map +1 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/utils/image-resize.d.ts +7 -27
- package/node_modules/@earendil-works/pi-coding-agent/dist/utils/image-resize.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/utils/image-resize.js +75 -115
- package/node_modules/@earendil-works/pi-coding-agent/dist/utils/image-resize.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/docs/terminal-setup.md +6 -0
- package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/sandbox/package.json +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/with-deps/package.json +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/npm-shrinkwrap.json +12 -14
- package/node_modules/@earendil-works/pi-coding-agent/package.json +5 -5
- package/node_modules/@earendil-works/pi-tui/dist/native-modifiers.d.ts +3 -0
- package/node_modules/@earendil-works/pi-tui/dist/native-modifiers.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-tui/dist/native-modifiers.js +53 -0
- package/node_modules/@earendil-works/pi-tui/dist/native-modifiers.js.map +1 -0
- package/node_modules/@earendil-works/pi-tui/dist/terminal-image.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/terminal-image.js +4 -1
- package/node_modules/@earendil-works/pi-tui/dist/terminal-image.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/terminal.d.ts +2 -0
- package/node_modules/@earendil-works/pi-tui/dist/terminal.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/terminal.js +13 -1
- package/node_modules/@earendil-works/pi-tui/dist/terminal.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/native/darwin/prebuilds/darwin-arm64/darwin-modifiers.node +0 -0
- package/node_modules/@earendil-works/pi-tui/native/darwin/prebuilds/darwin-x64/darwin-modifiers.node +0 -0
- package/node_modules/@earendil-works/pi-tui/package.json +2 -2
- package/package.json +6 -6
- package/dist/extensions/forgecli/forge-init/phase-descriptors.d.ts +0 -72
- package/dist/extensions/forgecli/forge-init/phase-descriptors.js +0 -359
- package/dist/extensions/forgecli/forge-init/phase-descriptors.js.map +0 -1
- package/dist/extensions/forgecli/forge-init/prompts.d.ts +0 -10
- package/dist/extensions/forgecli/forge-init/prompts.js +0 -91
- package/dist/extensions/forgecli/forge-init/prompts.js.map +0 -1
- package/dist/extensions/forgecli/lib/store-error-remediation.d.ts +0 -65
- package/dist/extensions/forgecli/lib/store-error-remediation.js +0 -298
- package/dist/extensions/forgecli/lib/store-error-remediation.js.map +0 -1
- package/dist/forge-payload/hooks/check-update.js +0 -378
- package/dist/forge-payload/hooks/forge-permissions.js +0 -164
- package/dist/forge-payload/hooks/triage-error.js +0 -77
- package/dist/forge-payload/hooks/validate-write.js +0 -250
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
// Forge tool: artifact
|
|
5
|
+
// Read, write, or list phase artifacts (PLAN.md, PROGRESS.md, *-SUMMARY.json, etc.)
|
|
6
|
+
// for a task, bug, or sprint. Resolves paths from entity store record.
|
|
7
|
+
//
|
|
8
|
+
// Usage:
|
|
9
|
+
// node artifact.cjs read <entity> <entityId> <artifact>
|
|
10
|
+
// node artifact.cjs write <entity> <entityId> <artifact> <content|@file>
|
|
11
|
+
// node artifact.cjs list <entity> <entityId>
|
|
12
|
+
//
|
|
13
|
+
// Exit codes: 0 = success, 1 = usage/validation error, 2 = not found
|
|
14
|
+
|
|
15
|
+
const fs = require('fs');
|
|
16
|
+
const path = require('path');
|
|
17
|
+
const { execFileSync } = require('child_process');
|
|
18
|
+
const { findProjectRoot } = require('./lib/project-root.cjs');
|
|
19
|
+
|
|
20
|
+
// ── Artifact catalog ─────────────────────────────────────────────────────────
|
|
21
|
+
|
|
22
|
+
const ARTIFACT_CATALOG = {
|
|
23
|
+
'plan': { filename: 'PLAN.md', type: 'md' },
|
|
24
|
+
'plan-review': { filename: 'PLAN_REVIEW.md', type: 'md' },
|
|
25
|
+
'progress': { filename: 'PROGRESS.md', type: 'md' },
|
|
26
|
+
'code-review': { filename: 'CODE_REVIEW.md', type: 'md' },
|
|
27
|
+
'validation-report': { filename: 'VALIDATION_REPORT.md', type: 'md' },
|
|
28
|
+
'architect-approval': { filename: 'ARCHITECT_APPROVAL.md', type: 'md' },
|
|
29
|
+
'triage': { filename: 'TRIAGE.md', type: 'md' },
|
|
30
|
+
'bug-report': { filename: 'BUG_REPORT.md', type: 'md' },
|
|
31
|
+
'index': { filename: 'INDEX.md', type: 'md' },
|
|
32
|
+
'cost-report': { filename: 'COST_REPORT.md', type: 'md' },
|
|
33
|
+
'timesheet': { filename: 'TIMESHEET.md', type: 'md' },
|
|
34
|
+
'plan-summary': { filename: 'PLAN-SUMMARY.json', type: 'json' },
|
|
35
|
+
'review-plan-summary': { filename: 'REVIEW-PLAN-SUMMARY.json', type: 'json' },
|
|
36
|
+
'implementation-summary': { filename: 'IMPLEMENTATION-SUMMARY.json', type: 'json' },
|
|
37
|
+
'review-code-summary': { filename: 'REVIEW-CODE-SUMMARY.json', type: 'json' },
|
|
38
|
+
'review-impl-summary': { filename: 'REVIEW-IMPL-SUMMARY.json', type: 'json' },
|
|
39
|
+
'validation-summary': { filename: 'VALIDATION-SUMMARY.json', type: 'json' },
|
|
40
|
+
'approve-summary': { filename: 'APPROVE-SUMMARY.json', type: 'json' },
|
|
41
|
+
'commit-summary': { filename: 'COMMIT-SUMMARY.json', type: 'json' },
|
|
42
|
+
'triage-summary': { filename: 'TRIAGE-SUMMARY.json', type: 'json' },
|
|
43
|
+
'writeback-summary': { filename: 'WRITEBACK-SUMMARY.json', type: 'json' },
|
|
44
|
+
'collation-summary': { filename: 'COLLATION-SUMMARY.json', type: 'json' },
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const ARTIFACT_NAMES = Object.keys(ARTIFACT_CATALOG).sort();
|
|
48
|
+
|
|
49
|
+
// ── Summary JSON validation ──────────────────────────────────────────────────
|
|
50
|
+
|
|
51
|
+
const SUMMARY_REQUIRED = ['objective', 'key_changes', 'verdict', 'written_at'];
|
|
52
|
+
|
|
53
|
+
function validateSummaryJson(content) {
|
|
54
|
+
let obj;
|
|
55
|
+
try {
|
|
56
|
+
obj = JSON.parse(content);
|
|
57
|
+
} catch (e) {
|
|
58
|
+
return `Invalid JSON: ${e.message}`;
|
|
59
|
+
}
|
|
60
|
+
const missing = SUMMARY_REQUIRED.filter((f) => !(f in obj));
|
|
61
|
+
if (missing.length > 0) return `Missing required fields: ${missing.join(', ')}`;
|
|
62
|
+
if (typeof obj.objective !== 'string') return `"objective" must be a string`;
|
|
63
|
+
if (!Array.isArray(obj.key_changes)) return `"key_changes" must be an array`;
|
|
64
|
+
if (typeof obj.verdict !== 'string') return `"verdict" must be a string`;
|
|
65
|
+
if (typeof obj.written_at !== 'string') return `"written_at" must be a string`;
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// ── Entity path resolution ───────────────────────────────────────────────────
|
|
70
|
+
|
|
71
|
+
/** Read a store record via store-cli and return its `path` field, or null on failure. */
|
|
72
|
+
function readStorePath(entity, entityId, toolDir, projectRoot) {
|
|
73
|
+
const cliPath = path.join(toolDir, 'store-cli.cjs');
|
|
74
|
+
try {
|
|
75
|
+
const result = execFileSync('node', [cliPath, 'read', entity, entityId, '--json'], {
|
|
76
|
+
cwd: projectRoot,
|
|
77
|
+
encoding: 'utf8',
|
|
78
|
+
timeout: 10_000,
|
|
79
|
+
});
|
|
80
|
+
const record = JSON.parse(result);
|
|
81
|
+
if (typeof record.path === 'string' && record.path.length > 0) {
|
|
82
|
+
// Defensive: if the path ends with a file extension, the store record
|
|
83
|
+
// was written with a filename (e.g. "…/PROGRESS.md") instead of the
|
|
84
|
+
// directory. Strip the trailing filename to get the entity directory.
|
|
85
|
+
const p = record.path;
|
|
86
|
+
if (/\.(md|json)$/i.test(p)) return path.dirname(p);
|
|
87
|
+
return p;
|
|
88
|
+
}
|
|
89
|
+
} catch (_) {
|
|
90
|
+
// Store unavailable or record not found — fall through.
|
|
91
|
+
}
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Resolve entity directory using the store record's `path` field when available,
|
|
97
|
+
* falling back to ID-only construction.
|
|
98
|
+
*/
|
|
99
|
+
function resolveEntityDir(entity, entityId, engineeringPath, toolDir, projectRoot) {
|
|
100
|
+
switch (entity) {
|
|
101
|
+
case 'bug': {
|
|
102
|
+
const storePath = readStorePath('bug', entityId, toolDir, projectRoot);
|
|
103
|
+
if (storePath) return storePath;
|
|
104
|
+
return path.join(engineeringPath, 'bugs', entityId);
|
|
105
|
+
}
|
|
106
|
+
case 'sprint': {
|
|
107
|
+
const storePath = readStorePath('sprint', entityId, toolDir, projectRoot);
|
|
108
|
+
if (storePath) return storePath;
|
|
109
|
+
return path.join(engineeringPath, 'sprints', entityId);
|
|
110
|
+
}
|
|
111
|
+
case 'task': {
|
|
112
|
+
const storePath = readStorePath('task', entityId, toolDir, projectRoot);
|
|
113
|
+
if (storePath) return storePath;
|
|
114
|
+
// Fallback: derive from sprint prefix + sprint record path.
|
|
115
|
+
const match = entityId.match(/^(.+-S\d+)-T\d+$/);
|
|
116
|
+
if (!match) return null;
|
|
117
|
+
const sprintId = match[1];
|
|
118
|
+
const sprintPath = readStorePath('sprint', sprintId, toolDir, projectRoot);
|
|
119
|
+
if (sprintPath) {
|
|
120
|
+
return path.join(sprintPath, entityId);
|
|
121
|
+
}
|
|
122
|
+
return path.join(engineeringPath, 'sprints', sprintId, entityId);
|
|
123
|
+
}
|
|
124
|
+
default:
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// ── CLI ───────────────────────────────────────────────────────────────────────
|
|
130
|
+
|
|
131
|
+
if (require.main === module) {
|
|
132
|
+
|
|
133
|
+
const argv = process.argv.slice(2);
|
|
134
|
+
|
|
135
|
+
if (argv.length === 0 || argv[0] === '--help' || argv[0] === '-h') {
|
|
136
|
+
process.stderr.write([
|
|
137
|
+
'Usage: node artifact.cjs <subcommand> <entity> <entityId> [artifact] [content|@file]',
|
|
138
|
+
'',
|
|
139
|
+
'Subcommands:',
|
|
140
|
+
' list <entity> <entityId> List existing artifacts',
|
|
141
|
+
' read <entity> <entityId> <artifact> Read artifact content',
|
|
142
|
+
' write <entity> <entityId> <artifact> <content|@file>',
|
|
143
|
+
' Write artifact (content or @/path/to/file)',
|
|
144
|
+
'',
|
|
145
|
+
'Entities: task, bug, sprint',
|
|
146
|
+
`Known artifacts: ${ARTIFACT_NAMES.join(', ')}`,
|
|
147
|
+
'',
|
|
148
|
+
'Exit codes: 0=success, 1=usage/validation error, 2=not found',
|
|
149
|
+
].join('\n') + '\n');
|
|
150
|
+
process.exit(1);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const [subcmd, entity, entityId] = argv;
|
|
154
|
+
|
|
155
|
+
if (!subcmd || !entity || !entityId) {
|
|
156
|
+
process.stderr.write('Usage: artifact.cjs <list|read|write> <entity> <entityId> [artifact] [content]\n');
|
|
157
|
+
process.exit(1);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const VALID_ENTITIES = ['task', 'bug', 'sprint'];
|
|
161
|
+
if (!VALID_ENTITIES.includes(entity)) {
|
|
162
|
+
process.stderr.write(`Unknown entity type: ${entity}. Valid: ${VALID_ENTITIES.join(', ')}\n`);
|
|
163
|
+
process.exit(1);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const projectRoot = findProjectRoot();
|
|
167
|
+
if (!projectRoot) {
|
|
168
|
+
process.stderr.write('Cannot find project root (.forge/config.json not found)\n');
|
|
169
|
+
process.exit(1);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Read engineering path from config
|
|
173
|
+
let engineeringPath = 'engineering';
|
|
174
|
+
try {
|
|
175
|
+
const cfg = JSON.parse(fs.readFileSync(path.join(projectRoot, '.forge', 'config.json'), 'utf8'));
|
|
176
|
+
if (typeof cfg.paths?.engineering === 'string') engineeringPath = cfg.paths.engineering;
|
|
177
|
+
} catch (_) { /* default */ }
|
|
178
|
+
|
|
179
|
+
const toolDir = __dirname;
|
|
180
|
+
|
|
181
|
+
const entityDir = resolveEntityDir(entity, entityId, engineeringPath, toolDir, projectRoot);
|
|
182
|
+
if (!entityDir) {
|
|
183
|
+
process.stderr.write(
|
|
184
|
+
`Cannot resolve ${entity} directory for "${entityId}". ` +
|
|
185
|
+
`Expected ID pattern: task=PREFIX-SNN-TNN, bug=PREFIX-BNN[-slug], sprint=PREFIX-SNN.\n`
|
|
186
|
+
);
|
|
187
|
+
process.exit(1);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const absDir = path.resolve(projectRoot, entityDir);
|
|
191
|
+
|
|
192
|
+
// ── list ────────────────────────────────────────────────────────────────────
|
|
193
|
+
|
|
194
|
+
if (subcmd === 'list') {
|
|
195
|
+
if (!fs.existsSync(absDir)) {
|
|
196
|
+
process.stdout.write(`No artifacts found — directory does not exist: ${entityDir}/\n`);
|
|
197
|
+
process.exit(0);
|
|
198
|
+
}
|
|
199
|
+
const files = fs.readdirSync(absDir).filter((f) => f.endsWith('.md') || f.endsWith('.json'));
|
|
200
|
+
const known = [];
|
|
201
|
+
const other = [];
|
|
202
|
+
for (const f of files) {
|
|
203
|
+
const catalogEntry = Object.entries(ARTIFACT_CATALOG).find(([, v]) => v.filename === f);
|
|
204
|
+
if (catalogEntry) {
|
|
205
|
+
known.push(` ${catalogEntry[0]} → ${f}`);
|
|
206
|
+
} else {
|
|
207
|
+
other.push(` (unlisted) ${f}`);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
const lines = [`Artifacts in ${entityDir}/:`];
|
|
211
|
+
if (known.length > 0) lines.push(...known);
|
|
212
|
+
if (other.length > 0) lines.push(...other);
|
|
213
|
+
if (known.length === 0 && other.length === 0) lines.push(' (empty)');
|
|
214
|
+
process.stdout.write(lines.join('\n') + '\n');
|
|
215
|
+
process.exit(0);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// ── read / write — need artifact name ───────────────────────────────────────
|
|
219
|
+
|
|
220
|
+
const artifactName = argv[3];
|
|
221
|
+
if (!artifactName) {
|
|
222
|
+
process.stderr.write(`"artifact" is required for ${subcmd}. Known: ${ARTIFACT_NAMES.join(', ')}\n`);
|
|
223
|
+
process.exit(1);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
const catalogEntry = ARTIFACT_CATALOG[artifactName];
|
|
227
|
+
if (!catalogEntry) {
|
|
228
|
+
const suggestions = ARTIFACT_NAMES.filter((n) => n.includes(artifactName.toLowerCase()));
|
|
229
|
+
process.stderr.write(
|
|
230
|
+
`Unknown artifact "${artifactName}". Known: ${ARTIFACT_NAMES.join(', ')}.` +
|
|
231
|
+
(suggestions.length > 0 ? ` Did you mean: ${suggestions.join(', ')}?` : '') + '\n'
|
|
232
|
+
);
|
|
233
|
+
process.exit(1);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const filePath = path.join(absDir, catalogEntry.filename);
|
|
237
|
+
|
|
238
|
+
// ── read ─────────────────────────────────────────────────────────────────────
|
|
239
|
+
|
|
240
|
+
if (subcmd === 'read') {
|
|
241
|
+
if (!fs.existsSync(filePath)) {
|
|
242
|
+
process.stderr.write(`Artifact not found: ${path.join(entityDir, catalogEntry.filename)}\n`);
|
|
243
|
+
process.exit(2);
|
|
244
|
+
}
|
|
245
|
+
process.stdout.write(fs.readFileSync(filePath, 'utf8'));
|
|
246
|
+
process.exit(0);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// ── write ─────────────────────────────────────────────────────────────────────
|
|
250
|
+
|
|
251
|
+
if (subcmd === 'write') {
|
|
252
|
+
let rawContent = argv[4];
|
|
253
|
+
if (!rawContent) {
|
|
254
|
+
process.stderr.write('"content" is required for write. Pass inline or use @/path/to/file for large content.\n');
|
|
255
|
+
process.exit(1);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// @-prefix convention: read content from file when arg starts with @
|
|
259
|
+
let content;
|
|
260
|
+
if (rawContent.startsWith('@')) {
|
|
261
|
+
const contentFile = rawContent.slice(1);
|
|
262
|
+
if (!fs.existsSync(contentFile)) {
|
|
263
|
+
process.stderr.write(`@-file not found: ${contentFile}\n`);
|
|
264
|
+
process.exit(1);
|
|
265
|
+
}
|
|
266
|
+
content = fs.readFileSync(contentFile, 'utf8');
|
|
267
|
+
} else {
|
|
268
|
+
content = rawContent;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
if (catalogEntry.type === 'json') {
|
|
272
|
+
const validationError = validateSummaryJson(content);
|
|
273
|
+
if (validationError) {
|
|
274
|
+
process.stderr.write(
|
|
275
|
+
`Summary validation failed for ${catalogEntry.filename}: ${validationError}. ` +
|
|
276
|
+
`Required fields: ${SUMMARY_REQUIRED.join(', ')}.\n`
|
|
277
|
+
);
|
|
278
|
+
process.exit(1);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
fs.mkdirSync(absDir, { recursive: true });
|
|
283
|
+
fs.writeFileSync(filePath, content, 'utf8');
|
|
284
|
+
process.stdout.write(
|
|
285
|
+
`Wrote ${Buffer.byteLength(content, 'utf8')} bytes to ${path.join(entityDir, catalogEntry.filename)}\n`
|
|
286
|
+
);
|
|
287
|
+
process.exit(0);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
process.stderr.write(`Unknown subcommand: ${subcmd}. Valid: list, read, write\n`);
|
|
291
|
+
process.exit(1);
|
|
292
|
+
|
|
293
|
+
} // end if (require.main === module)
|
|
294
|
+
|
|
295
|
+
module.exports = { ARTIFACT_CATALOG, ARTIFACT_NAMES, validateSummaryJson, resolveEntityDir };
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
// node banners.cjs --plain forge
|
|
32
32
|
// node banners.cjs --subtitle "Forging your SDLC"
|
|
33
33
|
// node banners.cjs --progress 5 12 "Templates"
|
|
34
|
-
// node banners.cjs --phase 7 12 "Workflows" ember
|
|
34
|
+
// node banners.cjs --phase 7 12 "Workflows" ember
|
|
35
35
|
|
|
36
36
|
// ─── Plain-mode detection ─────────────────────────────────────────────────────
|
|
37
37
|
// Resolved at call-time so tests can flip env vars dynamically.
|
|
@@ -61,14 +61,13 @@ const f = (r, g, b) => `\x1b[38;2;${r};${g};${b}m`;
|
|
|
61
61
|
// ─── Mode tints ───────────────────────────────────────────────────────────────
|
|
62
62
|
// Mode-aware accent colour for progress bars and subtitles. Used by phaseHeader.
|
|
63
63
|
const MODE_TINTS = {
|
|
64
|
-
fast: [255, 208, 122], // lantern yellow
|
|
65
64
|
full: [255, 138, 60], // ember orange
|
|
66
65
|
};
|
|
67
66
|
|
|
68
67
|
// ─── Zen blue ─────────────────────────────────────────────────────────────────
|
|
69
68
|
// System-wide horizontal-rule tint. Applied to em-dash separators in
|
|
70
|
-
// phaseHeader
|
|
71
|
-
//
|
|
69
|
+
// phaseHeader and ruleLine. Picked to read calm and cool without competing
|
|
70
|
+
// with banner colours.
|
|
72
71
|
const ZEN_BLUE = [100, 140, 200];
|
|
73
72
|
|
|
74
73
|
// ─── Banner registry ───────────────────────────────────────────────────────────
|
|
@@ -196,7 +196,7 @@ function buildContextPack({ archDir, existingPackPath }) {
|
|
|
196
196
|
if (realLineCount > PACK_LINE_LIMIT) {
|
|
197
197
|
// Keep PACK_LINE_LIMIT - 1 lines so the marker fits within the cap
|
|
198
198
|
const truncated = splitLines.slice(0, PACK_LINE_LIMIT - 1);
|
|
199
|
-
truncated.push('<!-- TRUNCATED: pack exceeded 400 lines. Architecture KB has grown beyond summary capacity. Run /forge:
|
|
199
|
+
truncated.push('<!-- TRUNCATED: pack exceeded 400 lines. Architecture KB has grown beyond summary capacity. Run /forge:rebuild after pruning docs. -->');
|
|
200
200
|
markdown = truncated.join('\n') + '\n';
|
|
201
201
|
}
|
|
202
202
|
|
|
@@ -59,11 +59,16 @@ function checkNamespaces(manifest, projectRoot, options = {}) {
|
|
|
59
59
|
|
|
60
60
|
for (const [nsKey, ns] of Object.entries(manifest.namespaces)) {
|
|
61
61
|
const logicalKey = ns.logicalKey || nsKey;
|
|
62
|
-
|
|
62
|
+
const configHasPath = resolvedConfigPaths[logicalKey] && typeof resolvedConfigPaths[logicalKey] === 'string';
|
|
63
|
+
let resolvedDir = configHasPath
|
|
63
64
|
? resolvedConfigPaths[logicalKey]
|
|
64
65
|
: ns.dir;
|
|
65
|
-
|
|
66
|
-
|
|
66
|
+
// When config provides the path, use it verbatim (it already includes any
|
|
67
|
+
// prefix subdirectory). Only apply the prefixed append when falling back
|
|
68
|
+
// to the manifest's base dir.
|
|
69
|
+
if (ns.prefixed && !configHasPath) {
|
|
70
|
+
const suffix = projectPrefix || getCommandsSubdir('forge');
|
|
71
|
+
resolvedDir = resolvedDir + '/' + suffix;
|
|
67
72
|
}
|
|
68
73
|
const absDir = path.join(projectRoot, resolvedDir);
|
|
69
74
|
|
|
@@ -558,10 +558,17 @@ function cmdWrite() {
|
|
|
558
558
|
function cmdRead() {
|
|
559
559
|
const entity = args[1];
|
|
560
560
|
const id = args[2];
|
|
561
|
-
const asJson
|
|
561
|
+
const asJson = args.includes('--json');
|
|
562
|
+
const noSummaries = args.includes('--no-summaries');
|
|
563
|
+
|
|
564
|
+
let fieldsProjection = null;
|
|
565
|
+
const fieldsIdx = args.indexOf('--fields');
|
|
566
|
+
if (fieldsIdx !== -1 && args[fieldsIdx + 1] && !args[fieldsIdx + 1].startsWith('--')) {
|
|
567
|
+
fieldsProjection = args[fieldsIdx + 1].split(',').map((f) => f.trim()).filter(Boolean);
|
|
568
|
+
}
|
|
562
569
|
|
|
563
570
|
if (!entity || !id) {
|
|
564
|
-
console.error('Usage: store-cli.cjs read <entity> <id> [--json]');
|
|
571
|
+
console.error('Usage: store-cli.cjs read <entity> <id> [--json] [--no-summaries] [--fields <comma-list>]');
|
|
565
572
|
process.exit(1);
|
|
566
573
|
}
|
|
567
574
|
|
|
@@ -590,10 +597,19 @@ function cmdRead() {
|
|
|
590
597
|
process.exit(1);
|
|
591
598
|
}
|
|
592
599
|
|
|
600
|
+
// Apply projection before formatting
|
|
601
|
+
let projected = record;
|
|
602
|
+
if (noSummaries) {
|
|
603
|
+
projected = Object.fromEntries(Object.entries(projected).filter(([k]) => k !== 'summaries'));
|
|
604
|
+
}
|
|
605
|
+
if (fieldsProjection) {
|
|
606
|
+
projected = Object.fromEntries(fieldsProjection.map((f) => [f, projected[f]]).filter(([, v]) => v !== undefined));
|
|
607
|
+
}
|
|
608
|
+
|
|
593
609
|
if (asJson) {
|
|
594
|
-
console.log(JSON.stringify(
|
|
610
|
+
console.log(JSON.stringify(projected));
|
|
595
611
|
} else {
|
|
596
|
-
console.log(JSON.stringify(
|
|
612
|
+
console.log(JSON.stringify(projected, null, 2));
|
|
597
613
|
}
|
|
598
614
|
}
|
|
599
615
|
|
|
@@ -601,7 +617,7 @@ function cmdList() {
|
|
|
601
617
|
const entity = args[1];
|
|
602
618
|
|
|
603
619
|
if (!entity) {
|
|
604
|
-
console.error('Usage: store-cli.cjs list <entity> [key=value ...]');
|
|
620
|
+
console.error('Usage: store-cli.cjs list <entity> [key=value ...] [--no-summaries] [--fields <comma-list>] [--limit N] [--count]');
|
|
605
621
|
process.exit(1);
|
|
606
622
|
}
|
|
607
623
|
|
|
@@ -610,9 +626,27 @@ function cmdList() {
|
|
|
610
626
|
process.exit(1);
|
|
611
627
|
}
|
|
612
628
|
|
|
613
|
-
// Parse key=value filter pairs from remaining args
|
|
629
|
+
// Parse projection flags and key=value filter pairs from remaining args
|
|
630
|
+
const noSummaries = args.includes('--no-summaries');
|
|
631
|
+
const countOnly = args.includes('--count');
|
|
632
|
+
|
|
633
|
+
let fieldsProjection = null;
|
|
634
|
+
const fieldsIdx = args.indexOf('--fields');
|
|
635
|
+
if (fieldsIdx !== -1 && args[fieldsIdx + 1] && !args[fieldsIdx + 1].startsWith('--')) {
|
|
636
|
+
fieldsProjection = args[fieldsIdx + 1].split(',').map((f) => f.trim()).filter(Boolean);
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
let limitN = null;
|
|
640
|
+
const limitIdx = args.indexOf('--limit');
|
|
641
|
+
if (limitIdx !== -1 && args[limitIdx + 1] && !args[limitIdx + 1].startsWith('--')) {
|
|
642
|
+
const n = parseInt(args[limitIdx + 1], 10);
|
|
643
|
+
if (!isNaN(n) && n >= 0) limitN = n;
|
|
644
|
+
}
|
|
645
|
+
|
|
614
646
|
const filter = {};
|
|
615
647
|
for (let i = 2; i < args.length; i++) {
|
|
648
|
+
// Skip flag arguments and their value arguments
|
|
649
|
+
if (args[i].startsWith('--')) { i++; continue; }
|
|
616
650
|
const eqIdx = args[i].indexOf('=');
|
|
617
651
|
if (eqIdx > 0) {
|
|
618
652
|
const key = args[i].slice(0, eqIdx);
|
|
@@ -623,7 +657,33 @@ function cmdList() {
|
|
|
623
657
|
}
|
|
624
658
|
}
|
|
625
659
|
|
|
626
|
-
|
|
660
|
+
let records = listEntities(entity, Object.keys(filter).length > 0 ? filter : undefined);
|
|
661
|
+
|
|
662
|
+
// --count: emit bare integer and exit (mutually exclusive with other flags)
|
|
663
|
+
if (countOnly) {
|
|
664
|
+
console.log(String(records.length));
|
|
665
|
+
return;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
// --limit: truncate after filtering
|
|
669
|
+
if (limitN !== null) {
|
|
670
|
+
records = records.slice(0, limitN);
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
// Apply projection
|
|
674
|
+
if (fieldsProjection || noSummaries) {
|
|
675
|
+
records = records.map((rec) => {
|
|
676
|
+
let projected = rec;
|
|
677
|
+
if (noSummaries) {
|
|
678
|
+
projected = Object.fromEntries(Object.entries(projected).filter(([k]) => k !== 'summaries'));
|
|
679
|
+
}
|
|
680
|
+
if (fieldsProjection) {
|
|
681
|
+
projected = Object.fromEntries(fieldsProjection.map((f) => [f, projected[f]]).filter(([, v]) => v !== undefined));
|
|
682
|
+
}
|
|
683
|
+
return projected;
|
|
684
|
+
});
|
|
685
|
+
}
|
|
686
|
+
|
|
627
687
|
console.log(JSON.stringify(records, null, 2));
|
|
628
688
|
}
|
|
629
689
|
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* output to the appropriate output directories.
|
|
10
10
|
*
|
|
11
11
|
* Output path mapping (--target claude-code, default):
|
|
12
|
-
* base-pack/commands/ → <outRoot>/.claude/commands
|
|
12
|
+
* base-pack/commands/ → <outRoot>/.claude/commands/<prefix>/
|
|
13
13
|
* base-pack/personas/ → <outRoot>/.forge/personas/
|
|
14
14
|
* base-pack/skills/ → <outRoot>/.forge/skills/
|
|
15
15
|
* base-pack/workflows/ → <outRoot>/.forge/workflows/
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
// Forge tool: verify-apply
|
|
5
|
+
// Verify that claimed file modifications actually landed on disk by checking
|
|
6
|
+
// each path against the generation-manifest baseline.
|
|
7
|
+
//
|
|
8
|
+
// Usage: node verify-apply.cjs <path1> [<path2> ...]
|
|
9
|
+
//
|
|
10
|
+
// Output: JSON to stdout:
|
|
11
|
+
// { "modified": [...], "unchanged": [...], "untracked": [...], "missing": [...] }
|
|
12
|
+
//
|
|
13
|
+
// Exit codes:
|
|
14
|
+
// 0 = all paths verified modified (success — agent claim was correct)
|
|
15
|
+
// 1 = any unchanged paths present (agent claim was wrong — re-apply needed)
|
|
16
|
+
// 2 = usage error (no paths provided)
|
|
17
|
+
|
|
18
|
+
const { spawnSync } = require('child_process');
|
|
19
|
+
const path = require('path');
|
|
20
|
+
const { findProjectRoot } = require('./lib/project-root.cjs');
|
|
21
|
+
|
|
22
|
+
if (require.main === module) {
|
|
23
|
+
|
|
24
|
+
const claimedPaths = process.argv.slice(2);
|
|
25
|
+
|
|
26
|
+
if (claimedPaths.length === 0) {
|
|
27
|
+
process.stderr.write('Usage: node verify-apply.cjs <path1> [<path2> ...]\n');
|
|
28
|
+
process.exit(2);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const projectRoot = findProjectRoot() || process.cwd();
|
|
32
|
+
const toolDir = __dirname;
|
|
33
|
+
const manifestTool = path.join(toolDir, 'generation-manifest.cjs');
|
|
34
|
+
|
|
35
|
+
const result = {
|
|
36
|
+
modified: [],
|
|
37
|
+
unchanged: [],
|
|
38
|
+
untracked: [],
|
|
39
|
+
missing: [],
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
for (const claimedPath of claimedPaths) {
|
|
43
|
+
const r = spawnSync('node', [manifestTool, 'check', claimedPath], {
|
|
44
|
+
cwd: projectRoot,
|
|
45
|
+
encoding: 'utf8',
|
|
46
|
+
timeout: 5_000,
|
|
47
|
+
});
|
|
48
|
+
switch (r.status) {
|
|
49
|
+
case 0:
|
|
50
|
+
result.unchanged.push(claimedPath);
|
|
51
|
+
break;
|
|
52
|
+
case 1:
|
|
53
|
+
result.modified.push(claimedPath);
|
|
54
|
+
break;
|
|
55
|
+
case 2:
|
|
56
|
+
result.untracked.push(claimedPath);
|
|
57
|
+
break;
|
|
58
|
+
case 3:
|
|
59
|
+
result.missing.push(claimedPath);
|
|
60
|
+
break;
|
|
61
|
+
default:
|
|
62
|
+
// Spawn error, timeout, or unrecognized exit code — safety default: missing
|
|
63
|
+
result.missing.push(claimedPath);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
process.stdout.write(JSON.stringify(result, null, 2) + '\n');
|
|
68
|
+
|
|
69
|
+
// Exit 1 if any unchanged paths (agent claim was wrong)
|
|
70
|
+
if (result.unchanged.length > 0) {
|
|
71
|
+
process.exit(1);
|
|
72
|
+
}
|
|
73
|
+
process.exit(0);
|
|
74
|
+
|
|
75
|
+
} // end if (require.main === module)
|