@entelligentsia/forgecli 1.0.3 → 1.0.10
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 +44 -0
- package/README.md +2 -1
- package/dist/CHANGELOG-forge-plugin.md +100 -0
- package/dist/CHANGELOG-pi.md +94 -0
- package/dist/extensions/forgecli/forge-artifact-tool.js +27 -4
- package/dist/extensions/forgecli/forge-artifact-tool.js.map +1 -1
- package/dist/extensions/forgecli/forge-tools.js +2 -2
- package/dist/extensions/forgecli/forge-tools.js.map +1 -1
- package/dist/extensions/forgecli/subagent/phase-guard.js +15 -5
- package/dist/extensions/forgecli/subagent/phase-guard.js.map +1 -1
- package/dist/extensions/forgecli/subagent/phase-summary-map.d.ts +1 -0
- package/dist/extensions/forgecli/subagent/phase-summary-map.js +17 -0
- package/dist/extensions/forgecli/subagent/phase-summary-map.js.map +1 -1
- package/dist/forge-payload/.base-pack/workflows/_fragments/store-cli-verbs.md +18 -3
- package/dist/forge-payload/.base-pack/workflows/architect_approve.md +4 -5
- package/dist/forge-payload/.base-pack/workflows/collator_agent.md +1 -1
- package/dist/forge-payload/.base-pack/workflows/commit_task.md +2 -3
- package/dist/forge-payload/.base-pack/workflows/implement_plan.md +3 -2
- package/dist/forge-payload/.base-pack/workflows/orchestrate_task.md +41 -47
- package/dist/forge-payload/.base-pack/workflows/triage.md +2 -2
- package/dist/forge-payload/.base-pack/workflows/validate_task.md +2 -3
- package/dist/forge-payload/.claude-plugin/plugin.json +1 -1
- package/dist/forge-payload/.schemas/_defs/locator.schema.json +13 -0
- package/dist/forge-payload/.schemas/bug.schema.json +1 -0
- package/dist/forge-payload/.schemas/enum-catalog.json +2 -2
- package/dist/forge-payload/.schemas/migrations.json +63 -0
- package/dist/forge-payload/.schemas/sprint.schema.json +1 -0
- package/dist/forge-payload/.schemas/task.schema.json +1 -0
- package/dist/forge-payload/integrity.json +3 -3
- package/dist/forge-payload/meta/workflows/_fragments/store-cli-verbs.md +18 -3
- package/dist/forge-payload/meta/workflows/meta-approve.md +4 -5
- package/dist/forge-payload/meta/workflows/meta-bug-triage.md +2 -2
- package/dist/forge-payload/meta/workflows/meta-collate.md +1 -1
- package/dist/forge-payload/meta/workflows/meta-commit.md +2 -3
- package/dist/forge-payload/meta/workflows/meta-implement.md +3 -2
- package/dist/forge-payload/meta/workflows/meta-orchestrate.md +41 -47
- package/dist/forge-payload/meta/workflows/meta-validate.md +2 -3
- package/dist/forge-payload/schemas/_defs/locator.schema.json +13 -0
- package/dist/forge-payload/schemas/bug.schema.json +1 -0
- package/dist/forge-payload/schemas/enum-catalog.json +2 -2
- package/dist/forge-payload/schemas/sprint.schema.json +1 -0
- package/dist/forge-payload/schemas/structure-manifest.json +3 -2
- package/dist/forge-payload/schemas/task.schema.json +1 -0
- package/dist/forge-payload/tools/artifact-store.cjs +242 -0
- package/dist/forge-payload/tools/artifact.cjs +60 -120
- package/dist/forge-payload/tools/lib/artifact-kinds.cjs +95 -0
- package/dist/forge-payload/tools/lib/store-nlp.cjs +6 -0
- package/dist/forge-payload/tools/lib/store-query-exec.cjs +39 -5
- package/dist/forge-payload/tools/lib/suggest.cjs +2 -1
- package/dist/forge-payload/tools/preflight-gate.cjs +55 -5
- package/dist/forge-payload/tools/store-cli.cjs +50 -15
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/agent-harness.d.ts +5 -2
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/agent-harness.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/agent-harness.js +81 -18
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/agent-harness.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/branch-summarization.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/branch-summarization.js +1 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/branch-summarization.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/compaction.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/compaction.js +19 -24
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/compaction.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/session.d.ts +1 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/session.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/session.js +14 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/session.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/types.d.ts +22 -8
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/types.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/types.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
- package/node_modules/@earendil-works/pi-ai/README.md +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts +374 -122
- 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 +424 -232
- package/node_modules/@earendil-works/pi-ai/dist/models.generated.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.d.ts +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.js +38 -2
- package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.js +21 -12
- package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/azure-openai-responses.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/azure-openai-responses.js +6 -10
- package/node_modules/@earendil-works/pi-ai/dist/providers/azure-openai-responses.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/google-vertex.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/google-vertex.js +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/google-vertex.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/google.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/google.js +5 -3
- package/node_modules/@earendil-works/pi-ai/dist/providers/google.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/images/openrouter.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/images/openrouter.js +3 -4
- package/node_modules/@earendil-works/pi-ai/dist/providers/images/openrouter.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/mistral.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/mistral.js +2 -3
- package/node_modules/@earendil-works/pi-ai/dist/providers/mistral.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 +159 -78
- package/node_modules/@earendil-works/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/openai-completions.js +16 -11
- package/node_modules/@earendil-works/pi-ai/dist/providers/openai-completions.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/openai-responses-shared.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/openai-responses-shared.js +4 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/openai-responses-shared.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/openai-responses.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/openai-responses.js +6 -10
- package/node_modules/@earendil-works/pi-ai/dist/providers/openai-responses.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/simple-options.js +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/simple-options.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/stream.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/stream.js +14 -2
- package/node_modules/@earendil-works/pi-ai/dist/stream.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/types.d.ts +14 -4
- package/node_modules/@earendil-works/pi-ai/dist/types.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/types.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/abort-signals.d.ts +6 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/abort-signals.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/abort-signals.js +34 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/abort-signals.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/device-code.d.ts +9 -7
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/device-code.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/device-code.js +8 -7
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/device-code.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/github-copilot.js +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/github-copilot.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/index.d.ts +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/index.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/index.js +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/index.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/openai-codex.d.ts +10 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/openai-codex.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/openai-codex.js +179 -79
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/openai-codex.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/package.json +2 -2
- package/node_modules/@earendil-works/pi-coding-agent/CHANGELOG.md +94 -0
- package/node_modules/@earendil-works/pi-coding-agent/README.md +9 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/cli/args.d.ts +3 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/cli/args.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/cli/args.js +27 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/cli/args.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/config.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/config.js +15 -2
- package/node_modules/@earendil-works/pi-coding-agent/dist/config.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session-services.d.ts +1 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session-services.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session-services.js +1 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session-services.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.d.ts +5 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.js +28 -4
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/compaction/compaction.js +18 -24
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/runner.d.ts +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/runner.js +8 -2
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/types.d.ts +7 -5
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/model-registry.js +65 -13
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/model-resolver.js +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/resolve-config-value.d.ts +9 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/resolve-config-value.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/resolve-config-value.js +134 -11
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/resolve-config-value.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/sdk.d.ts +2 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/sdk.js +10 -6
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/sdk.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/session-manager.d.ts +6 -7
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/session-manager.js +75 -28
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/session-manager.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/settings-manager.d.ts +2 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/settings-manager.js +14 -9
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/system-prompt.js +0 -3
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/system-prompt.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 +7 -10
- 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/find.d.ts.map +1 -1
- 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.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 -7
- 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/read.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/read.js +6 -7
- 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/render-utils.d.ts +5 -2
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/render-utils.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/render-utils.js +17 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/render-utils.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 +5 -6
- 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/index.d.ts +2 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/index.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/index.js +2 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/index.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/main.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/main.js +69 -16
- package/node_modules/@earendil-works/pi-coding-agent/dist/main.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/migrations.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/migrations.js +118 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/migrations.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts +1 -3
- package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/login-dialog.js +2 -4
- package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/user-message.js +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/user-message.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +3 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/interactive-mode.js +59 -6
- package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/theme/theme.js +10 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/theme/theme.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 +3 -1
- 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/modes/rpc/rpc-types.d.ts +1 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-types.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/utils/deprecation.d.ts +4 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/utils/deprecation.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/utils/deprecation.js +13 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/utils/deprecation.js.map +1 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/utils/json.d.ts +3 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/utils/json.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/utils/json.js +7 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/utils/json.js.map +1 -0
- package/node_modules/@earendil-works/pi-coding-agent/docs/custom-provider.md +13 -10
- package/node_modules/@earendil-works/pi-coding-agent/docs/development.md +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/docs/extensions.md +12 -6
- package/node_modules/@earendil-works/pi-coding-agent/docs/models.md +25 -12
- package/node_modules/@earendil-works/pi-coding-agent/docs/providers.md +13 -5
- package/node_modules/@earendil-works/pi-coding-agent/docs/quickstart.md +1 -0
- package/node_modules/@earendil-works/pi-coding-agent/docs/rpc.md +2 -1
- package/node_modules/@earendil-works/pi-coding-agent/docs/sdk.md +6 -0
- package/node_modules/@earendil-works/pi-coding-agent/docs/session-format.md +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/docs/sessions.md +8 -0
- package/node_modules/@earendil-works/pi-coding-agent/docs/settings.md +7 -3
- package/node_modules/@earendil-works/pi-coding-agent/docs/terminal-setup.md +2 -0
- package/node_modules/@earendil-works/pi-coding-agent/docs/tui.md +2 -2
- package/node_modules/@earendil-works/pi-coding-agent/docs/usage.md +9 -0
- package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/README.md +1 -0
- package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/custom-provider-anthropic/index.ts +1 -1
- 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/index.ts +54 -3
- 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/git-merge-and-resolve.ts +115 -0
- package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/input-transform-streaming.ts +39 -0
- 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 +443 -61
- package/node_modules/@earendil-works/pi-coding-agent/package.json +6 -6
- package/node_modules/@earendil-works/pi-tui/README.md +2 -2
- package/node_modules/@earendil-works/pi-tui/dist/components/editor.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/editor.js +24 -83
- package/node_modules/@earendil-works/pi-tui/dist/components/editor.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/input.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/input.js +7 -55
- package/node_modules/@earendil-works/pi-tui/dist/components/input.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/markdown.d.ts +7 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/markdown.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/markdown.js +12 -2
- package/node_modules/@earendil-works/pi-tui/dist/components/markdown.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/index.d.ts +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/index.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/index.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/terminal-image.d.ts +1 -1
- 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 +34 -7
- 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 +33 -10
- package/node_modules/@earendil-works/pi-tui/dist/terminal.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/terminal.js +172 -37
- package/node_modules/@earendil-works/pi-tui/dist/terminal.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/utils.d.ts +6 -1
- package/node_modules/@earendil-works/pi-tui/dist/utils.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/utils.js +27 -15
- package/node_modules/@earendil-works/pi-tui/dist/utils.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/word-navigation.d.ts +25 -0
- package/node_modules/@earendil-works/pi-tui/dist/word-navigation.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-tui/dist/word-navigation.js +96 -0
- package/node_modules/@earendil-works/pi-tui/dist/word-navigation.js.map +1 -0
- package/node_modules/@earendil-works/pi-tui/package.json +2 -2
- package/node_modules/@entelligentsia/forge-compress/LICENSE +21 -0
- package/node_modules/@entelligentsia/forge-compress/README.md +85 -0
- package/node_modules/@mariozechner/clipboard/Cargo.toml +3 -3
- package/node_modules/@mariozechner/clipboard/index.d.ts +34 -20
- package/node_modules/@mariozechner/clipboard/index.js +546 -257
- package/node_modules/@mariozechner/clipboard/package.json +5 -6
- package/node_modules/@mariozechner/clipboard/package.json.prepack-backup +14 -14
- package/node_modules/@mariozechner/clipboard/src/lib.rs +4 -9
- package/node_modules/@mariozechner/clipboard-linux-x64-gnu/clipboard.linux-x64-gnu.node +0 -0
- package/node_modules/@mariozechner/clipboard-linux-x64-gnu/package.json +2 -2
- package/package.json +7 -7
- package/dist/forge-payload/.base-pack/commands/quiz-agent.md +0 -6
- package/dist/forge-payload/.base-pack/commands/retrospective.md +0 -6
- package/dist/forge-payload/.base-pack/commands/sprint-intake.md +0 -6
- package/dist/forge-payload/.base-pack/commands/sprint-plan.md +0 -6
- package/dist/forge-payload/commands/calibrate.md +0 -10
- package/dist/forge-payload/commands/materialize.md +0 -119
- package/dist/forge-payload/commands/migrate.md +0 -12
- package/dist/forge-payload/commands/quiz-agent.md +0 -6
- package/dist/forge-payload/commands/regenerate.md +0 -6
- package/dist/forge-payload/commands/store-query.md +0 -6
- package/dist/forge-payload/commands/store-repair.md +0 -6
- package/dist/forge-payload/commands/update-tools.md +0 -10
- package/dist/forge-payload/meta/templates/meta-retrospective.md +0 -28
- package/dist/forge-payload/tools/prompts/sprint-plan-prompt.md +0 -70
- package/dist/forge-payload/tools/schemas/task-list.schema.json +0 -53
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/execution-env.d.ts +0 -4
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/execution-env.d.ts.map +0 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/execution-env.js +0 -3
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/execution-env.js.map +0 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/repo/jsonl.d.ts +0 -20
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/repo/jsonl.d.ts.map +0 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/repo/jsonl.js +0 -92
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/repo/jsonl.js.map +0 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/repo/memory.d.ts +0 -18
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/repo/memory.d.ts.map +0 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/repo/memory.js +0 -42
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/repo/memory.js.map +0 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/repo/shared.d.ts +0 -10
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/repo/shared.d.ts.map +0 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/repo/shared.js +0 -31
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/repo/shared.js.map +0 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/storage/jsonl.d.ts +0 -30
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/storage/jsonl.d.ts.map +0 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/storage/jsonl.js +0 -170
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/storage/jsonl.js.map +0 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/storage/memory.d.ts +0 -26
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/storage/memory.d.ts.map +0 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/storage/memory.js +0 -90
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/storage/memory.js.map +0 -1
- package/node_modules/@mariozechner/clipboard-linux-x64-musl/README.md +0 -3
- package/node_modules/@mariozechner/clipboard-linux-x64-musl/clipboard.linux-x64-musl.node +0 -0
- package/node_modules/@mariozechner/clipboard-linux-x64-musl/package.json +0 -25
|
@@ -14,59 +14,26 @@
|
|
|
14
14
|
|
|
15
15
|
const fs = require('fs');
|
|
16
16
|
const path = require('path');
|
|
17
|
-
const { execFileSync } = require('child_process');
|
|
18
17
|
const { findProjectRoot } = require('./lib/project-root.cjs');
|
|
19
18
|
|
|
20
19
|
// ── Artifact catalog ─────────────────────────────────────────────────────────
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
'review-plan-summary': { filename: 'REVIEW-PLAN-SUMMARY.json', type: 'json' },
|
|
39
|
-
'implementation-summary': { filename: 'IMPLEMENTATION-SUMMARY.json', type: 'json' },
|
|
40
|
-
'review-code-summary': { filename: 'REVIEW-CODE-SUMMARY.json', type: 'json' },
|
|
41
|
-
'review-impl-summary': { filename: 'REVIEW-IMPL-SUMMARY.json', type: 'json' },
|
|
42
|
-
'validation-summary': { filename: 'VALIDATION-SUMMARY.json', type: 'json' },
|
|
43
|
-
'approve-summary': { filename: 'APPROVE-SUMMARY.json', type: 'json' },
|
|
44
|
-
'commit-summary': { filename: 'COMMIT-SUMMARY.json', type: 'json' },
|
|
45
|
-
'triage-summary': { filename: 'TRIAGE-SUMMARY.json', type: 'json' },
|
|
46
|
-
'writeback-summary': { filename: 'WRITEBACK-SUMMARY.json', type: 'json' },
|
|
47
|
-
'collation-summary': { filename: 'COLLATION-SUMMARY.json', type: 'json' },
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
// Per-entity filename overrides. Bug-mode plans and plan-summaries use the
|
|
51
|
-
// BUG_FIX_PLAN prefix to match the long-standing forge convention and the
|
|
52
|
-
// preflight-gate.cjs expectations for review-plan in bug mode. Without this
|
|
53
|
-
// override, plan-fix (routed via plan_task.md post FORGE-BUG-040) writes
|
|
54
|
-
// PLAN.md and review-plan preflight then fails "artifact missing:
|
|
55
|
-
// BUG_FIX_PLAN.md" — see FORGE-BUG-041.
|
|
56
|
-
const ARTIFACT_FILENAME_OVERRIDES = {
|
|
57
|
-
bug: {
|
|
58
|
-
'plan': 'BUG_FIX_PLAN.md',
|
|
59
|
-
'plan-summary': 'BUG-FIX-PLAN-SUMMARY.json',
|
|
60
|
-
},
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
function resolveArtifactFilename(entity, artifactName) {
|
|
64
|
-
const override = ARTIFACT_FILENAME_OVERRIDES[entity];
|
|
65
|
-
if (override && override[artifactName]) return override[artifactName];
|
|
66
|
-
return ARTIFACT_CATALOG[artifactName].filename;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const ARTIFACT_NAMES = Object.keys(ARTIFACT_CATALOG).sort();
|
|
20
|
+
//
|
|
21
|
+
// The catalog, bug-mode overrides, and filename resolution now live in the
|
|
22
|
+
// canonical registry at lib/artifact-kinds.cjs (ADR artifact-resolution Phase 1),
|
|
23
|
+
// consumed here and by store-cli.cjs so there is ONE source of truth.
|
|
24
|
+
const {
|
|
25
|
+
ARTIFACT_CATALOG,
|
|
26
|
+
ARTIFACT_FILENAME_OVERRIDES,
|
|
27
|
+
ARTIFACT_NAMES,
|
|
28
|
+
resolveArtifactFilename,
|
|
29
|
+
} = require('./lib/artifact-kinds.cjs');
|
|
30
|
+
|
|
31
|
+
// The provider seam (ArtifactStore/FsArtifactImpl) and entity-dir resolution
|
|
32
|
+
// live in artifact-store.cjs (ADR Phase 3). This CLI is a thin layer over the
|
|
33
|
+
// facade: it owns arg parsing, @-file expansion, JSON validation, and display;
|
|
34
|
+
// all filesystem access goes through the provider.
|
|
35
|
+
const artifactStore = require('./artifact-store.cjs');
|
|
36
|
+
const { ArtifactStore, FsArtifactImpl, resolveEntityDir } = artifactStore;
|
|
70
37
|
|
|
71
38
|
// ── Summary JSON validation ──────────────────────────────────────────────────
|
|
72
39
|
|
|
@@ -88,66 +55,6 @@ function validateSummaryJson(content) {
|
|
|
88
55
|
return null;
|
|
89
56
|
}
|
|
90
57
|
|
|
91
|
-
// ── Entity path resolution ───────────────────────────────────────────────────
|
|
92
|
-
|
|
93
|
-
/** Read a store record via store-cli and return its `path` field, or null on failure. */
|
|
94
|
-
function readStorePath(entity, entityId, toolDir, projectRoot) {
|
|
95
|
-
const cliPath = path.join(toolDir, 'store-cli.cjs');
|
|
96
|
-
try {
|
|
97
|
-
const result = execFileSync('node', [cliPath, 'read', entity, entityId, '--json'], {
|
|
98
|
-
cwd: projectRoot,
|
|
99
|
-
encoding: 'utf8',
|
|
100
|
-
timeout: 10_000,
|
|
101
|
-
});
|
|
102
|
-
const record = JSON.parse(result);
|
|
103
|
-
if (typeof record.path === 'string' && record.path.length > 0) {
|
|
104
|
-
// Defensive: if the path ends with a file extension, the store record
|
|
105
|
-
// was written with a filename (e.g. "…/PROGRESS.md") instead of the
|
|
106
|
-
// directory. Strip the trailing filename to get the entity directory.
|
|
107
|
-
const p = record.path;
|
|
108
|
-
if (/\.(md|json)$/i.test(p)) return path.dirname(p);
|
|
109
|
-
return p;
|
|
110
|
-
}
|
|
111
|
-
} catch (_) {
|
|
112
|
-
// Store unavailable or record not found — fall through.
|
|
113
|
-
}
|
|
114
|
-
return null;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Resolve entity directory using the store record's `path` field when available,
|
|
119
|
-
* falling back to ID-only construction.
|
|
120
|
-
*/
|
|
121
|
-
function resolveEntityDir(entity, entityId, engineeringPath, toolDir, projectRoot) {
|
|
122
|
-
switch (entity) {
|
|
123
|
-
case 'bug': {
|
|
124
|
-
const storePath = readStorePath('bug', entityId, toolDir, projectRoot);
|
|
125
|
-
if (storePath) return storePath;
|
|
126
|
-
return path.join(engineeringPath, 'bugs', entityId);
|
|
127
|
-
}
|
|
128
|
-
case 'sprint': {
|
|
129
|
-
const storePath = readStorePath('sprint', entityId, toolDir, projectRoot);
|
|
130
|
-
if (storePath) return storePath;
|
|
131
|
-
return path.join(engineeringPath, 'sprints', entityId);
|
|
132
|
-
}
|
|
133
|
-
case 'task': {
|
|
134
|
-
const storePath = readStorePath('task', entityId, toolDir, projectRoot);
|
|
135
|
-
if (storePath) return storePath;
|
|
136
|
-
// Fallback: derive from sprint prefix + sprint record path.
|
|
137
|
-
const match = entityId.match(/^(.+-S\d+)-T\d+$/);
|
|
138
|
-
if (!match) return null;
|
|
139
|
-
const sprintId = match[1];
|
|
140
|
-
const sprintPath = readStorePath('sprint', sprintId, toolDir, projectRoot);
|
|
141
|
-
if (sprintPath) {
|
|
142
|
-
return path.join(sprintPath, entityId);
|
|
143
|
-
}
|
|
144
|
-
return path.join(engineeringPath, 'sprints', sprintId, entityId);
|
|
145
|
-
}
|
|
146
|
-
default:
|
|
147
|
-
return null;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
58
|
// ── CLI ───────────────────────────────────────────────────────────────────────
|
|
152
59
|
|
|
153
60
|
if (require.main === module) {
|
|
@@ -163,6 +70,9 @@ if (argv.length === 0 || argv[0] === '--help' || argv[0] === '-h') {
|
|
|
163
70
|
' read <entity> <entityId> <artifact> Read artifact content',
|
|
164
71
|
' write <entity> <entityId> <artifact> <content|@file>',
|
|
165
72
|
' Write artifact (content or @/path/to/file)',
|
|
73
|
+
' exists <entity> <entityId> <artifact> Exit 0 if present, 2 if absent',
|
|
74
|
+
' url <entity> <entityId> <artifact> Print the backend URL (file:// for fs)',
|
|
75
|
+
' delete <entity> <entityId> <artifact> Delete an artifact',
|
|
166
76
|
'',
|
|
167
77
|
'Entities: task, bug, sprint',
|
|
168
78
|
`Known artifacts: ${ARTIFACT_NAMES.join(', ')}`,
|
|
@@ -211,6 +121,14 @@ if (!entityDir) {
|
|
|
211
121
|
|
|
212
122
|
const absDir = path.resolve(projectRoot, entityDir);
|
|
213
123
|
|
|
124
|
+
// Provider instance — all filesystem access for read/write/exists/url/delete
|
|
125
|
+
// goes through the facade (ADR Phase 3). Wired with the already-resolved dir so
|
|
126
|
+
// the CLI and the provider agree on location without a second store read.
|
|
127
|
+
const store = new ArtifactStore(new FsArtifactImpl({
|
|
128
|
+
projectRoot, engineeringPath, toolDir,
|
|
129
|
+
resolveDir: () => entityDir,
|
|
130
|
+
}));
|
|
131
|
+
|
|
214
132
|
// ── list ────────────────────────────────────────────────────────────────────
|
|
215
133
|
|
|
216
134
|
if (subcmd === 'list') {
|
|
@@ -262,16 +180,41 @@ if (!catalogEntry) {
|
|
|
262
180
|
}
|
|
263
181
|
|
|
264
182
|
const resolvedFilename = resolveArtifactFilename(entity, artifactName);
|
|
265
|
-
const
|
|
183
|
+
const displayPath = path.join(entityDir, resolvedFilename);
|
|
184
|
+
const handle = { entity, entityId, kind: artifactName };
|
|
266
185
|
|
|
267
186
|
// ── read ─────────────────────────────────────────────────────────────────────
|
|
268
187
|
|
|
269
188
|
if (subcmd === 'read') {
|
|
270
|
-
if (!
|
|
271
|
-
process.stderr.write(`Artifact not found: ${
|
|
189
|
+
if (!store.exists(handle)) {
|
|
190
|
+
process.stderr.write(`Artifact not found: ${displayPath}\n`);
|
|
272
191
|
process.exit(2);
|
|
273
192
|
}
|
|
274
|
-
process.stdout.write(
|
|
193
|
+
process.stdout.write(store.read(handle));
|
|
194
|
+
process.exit(0);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// ── exists ─────────────────────────────────────────────────────────────────────
|
|
198
|
+
|
|
199
|
+
if (subcmd === 'exists') {
|
|
200
|
+
// Boolean check: always exit 0 with a "true"/"false" token so callers
|
|
201
|
+
// (including the forge-cli subprocess surface) never treat absence as an error.
|
|
202
|
+
process.stdout.write(store.exists(handle) ? 'true\n' : 'false\n');
|
|
203
|
+
process.exit(0);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// ── url ────────────────────────────────────────────────────────────────────────
|
|
207
|
+
|
|
208
|
+
if (subcmd === 'url') {
|
|
209
|
+
process.stdout.write(store.url(handle) + '\n');
|
|
210
|
+
process.exit(0);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// ── delete ─────────────────────────────────────────────────────────────────────
|
|
214
|
+
|
|
215
|
+
if (subcmd === 'delete') {
|
|
216
|
+
const removed = store.delete(handle);
|
|
217
|
+
process.stdout.write(removed ? `Deleted ${displayPath}\n` : `Nothing to delete: ${displayPath}\n`);
|
|
275
218
|
process.exit(0);
|
|
276
219
|
}
|
|
277
220
|
|
|
@@ -308,15 +251,12 @@ if (subcmd === 'write') {
|
|
|
308
251
|
}
|
|
309
252
|
}
|
|
310
253
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
process.stdout.write(
|
|
314
|
-
`Wrote ${Buffer.byteLength(content, 'utf8')} bytes to ${path.join(entityDir, resolvedFilename)}\n`
|
|
315
|
-
);
|
|
254
|
+
const res = store.write(handle, content);
|
|
255
|
+
process.stdout.write(`Wrote ${res.bytes} bytes to ${displayPath}\n`);
|
|
316
256
|
process.exit(0);
|
|
317
257
|
}
|
|
318
258
|
|
|
319
|
-
process.stderr.write(`Unknown subcommand: ${subcmd}. Valid: list, read, write\n`);
|
|
259
|
+
process.stderr.write(`Unknown subcommand: ${subcmd}. Valid: list, read, write, exists, url, delete\n`);
|
|
320
260
|
process.exit(1);
|
|
321
261
|
|
|
322
262
|
} // end if (require.main === module)
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// ── Canonical artifact-kind registry ─────────────────────────────────────────
|
|
4
|
+
//
|
|
5
|
+
// Single source of truth for artifact filenames, bug-mode filename overrides,
|
|
6
|
+
// and the phase→kind mapping. Extracted from artifact.cjs per ADR
|
|
7
|
+
// `doc/decisions/artifact-resolution-abstraction.md` (Phase 1) so that
|
|
8
|
+
// artifact.cjs, store-cli.cjs (set-summary / set-bug-summary), and the
|
|
9
|
+
// forge-cli `forge_artifact` surface all consume ONE catalog instead of
|
|
10
|
+
// maintaining parallel copies.
|
|
11
|
+
//
|
|
12
|
+
// Renaming an artifact file is a one-line edit here.
|
|
13
|
+
|
|
14
|
+
const ARTIFACT_CATALOG = {
|
|
15
|
+
'plan': { filename: 'PLAN.md', type: 'md' },
|
|
16
|
+
'plan-review': { filename: 'PLAN_REVIEW.md', type: 'md' },
|
|
17
|
+
'progress': { filename: 'PROGRESS.md', type: 'md' },
|
|
18
|
+
'code-review': { filename: 'CODE_REVIEW.md', type: 'md' },
|
|
19
|
+
'validation-report': { filename: 'VALIDATION_REPORT.md', type: 'md' },
|
|
20
|
+
'architect-approval': { filename: 'ARCHITECT_APPROVAL.md', type: 'md' },
|
|
21
|
+
'triage': { filename: 'TRIAGE.md', type: 'md' },
|
|
22
|
+
'bug-report': { filename: 'BUG_REPORT.md', type: 'md' },
|
|
23
|
+
'index': { filename: 'INDEX.md', type: 'md' },
|
|
24
|
+
'task-prompt': { filename: 'TASK_PROMPT.md', type: 'md' },
|
|
25
|
+
'sprint-requirements': { filename: 'SPRINT_REQUIREMENTS.md', type: 'md' },
|
|
26
|
+
'sprint-completion-review': { filename: 'SPRINT_COMPLETION_REVIEW.md', type: 'md' },
|
|
27
|
+
'cost-report': { filename: 'COST_REPORT.md', type: 'md' },
|
|
28
|
+
'timesheet': { filename: 'TIMESHEET.md', type: 'md' },
|
|
29
|
+
'plan-summary': { filename: 'PLAN-SUMMARY.json', type: 'json' },
|
|
30
|
+
'review-plan-summary': { filename: 'REVIEW-PLAN-SUMMARY.json', type: 'json' },
|
|
31
|
+
'implementation-summary': { filename: 'IMPLEMENTATION-SUMMARY.json', type: 'json' },
|
|
32
|
+
'review-code-summary': { filename: 'REVIEW-CODE-SUMMARY.json', type: 'json' },
|
|
33
|
+
'review-impl-summary': { filename: 'REVIEW-IMPL-SUMMARY.json', type: 'json' },
|
|
34
|
+
'validation-summary': { filename: 'VALIDATION-SUMMARY.json', type: 'json' },
|
|
35
|
+
'approve-summary': { filename: 'APPROVE-SUMMARY.json', type: 'json' },
|
|
36
|
+
'commit-summary': { filename: 'COMMIT-SUMMARY.json', type: 'json' },
|
|
37
|
+
'triage-summary': { filename: 'TRIAGE-SUMMARY.json', type: 'json' },
|
|
38
|
+
'writeback-summary': { filename: 'WRITEBACK-SUMMARY.json', type: 'json' },
|
|
39
|
+
'collation-summary': { filename: 'COLLATION-SUMMARY.json', type: 'json' },
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// Per-entity filename overrides. Bug-mode plans and plan-summaries use the
|
|
43
|
+
// BUG_FIX_PLAN prefix to match the long-standing forge convention and the
|
|
44
|
+
// preflight-gate.cjs expectations for review-plan in bug mode. Without this
|
|
45
|
+
// override, plan-fix (routed via plan_task.md post FORGE-BUG-040) writes
|
|
46
|
+
// PLAN.md and review-plan preflight then fails "artifact missing:
|
|
47
|
+
// BUG_FIX_PLAN.md" — see FORGE-BUG-041.
|
|
48
|
+
const ARTIFACT_FILENAME_OVERRIDES = {
|
|
49
|
+
bug: {
|
|
50
|
+
'plan': 'BUG_FIX_PLAN.md',
|
|
51
|
+
'plan-summary': 'BUG-FIX-PLAN-SUMMARY.json',
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
// Phase → artifact-kind. Phases use underscore spellings (mirror of
|
|
56
|
+
// store-helpers VALID_SUMMARY_PHASES); kinds use the hyphenated catalog keys.
|
|
57
|
+
// This is the mapping set-summary / set-bug-summary use to self-resolve the
|
|
58
|
+
// sidecar JSON file from a record's path, so callers never hand-build paths.
|
|
59
|
+
const PHASE_TO_KIND = {
|
|
60
|
+
'plan': 'plan-summary',
|
|
61
|
+
'review_plan': 'review-plan-summary',
|
|
62
|
+
'implementation': 'implementation-summary',
|
|
63
|
+
'code_review': 'review-code-summary',
|
|
64
|
+
'validation': 'validation-summary',
|
|
65
|
+
'triage': 'triage-summary',
|
|
66
|
+
'approve': 'approve-summary',
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
function resolveArtifactFilename(entity, artifactName) {
|
|
70
|
+
const override = ARTIFACT_FILENAME_OVERRIDES[entity];
|
|
71
|
+
if (override && override[artifactName]) return override[artifactName];
|
|
72
|
+
const entry = ARTIFACT_CATALOG[artifactName];
|
|
73
|
+
if (!entry) throw new Error(`unknown artifact kind: ${artifactName}`);
|
|
74
|
+
return entry.filename;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Resolve the phase-summary sidecar filename for an entity. Applies the
|
|
78
|
+
// phase→kind map, then the per-entity filename override (so a bug's "plan"
|
|
79
|
+
// summary becomes BUG-FIX-PLAN-SUMMARY.json).
|
|
80
|
+
function resolveSummaryFilename(entity, phase) {
|
|
81
|
+
const kind = PHASE_TO_KIND[phase];
|
|
82
|
+
if (!kind) throw new Error(`unknown phase: ${phase}`);
|
|
83
|
+
return resolveArtifactFilename(entity, kind);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const ARTIFACT_NAMES = Object.keys(ARTIFACT_CATALOG).sort();
|
|
87
|
+
|
|
88
|
+
module.exports = {
|
|
89
|
+
ARTIFACT_CATALOG,
|
|
90
|
+
ARTIFACT_FILENAME_OVERRIDES,
|
|
91
|
+
ARTIFACT_NAMES,
|
|
92
|
+
PHASE_TO_KIND,
|
|
93
|
+
resolveArtifactFilename,
|
|
94
|
+
resolveSummaryFilename,
|
|
95
|
+
};
|
|
@@ -99,6 +99,12 @@ function parseIntentNLP(intent) {
|
|
|
99
99
|
outer:
|
|
100
100
|
for (let i = 0; i < words.length; i++) {
|
|
101
101
|
if (consumed.has(i)) continue;
|
|
102
|
+
// "with <entity>" (and "<entity> for") are FK-follow directives handled in
|
|
103
|
+
// Stage 4 — they must NOT be treated as the primary entity. Otherwise an
|
|
104
|
+
// explicit anchored ID (e.g. "WI-S19-T04 with sprint with feature") loses
|
|
105
|
+
// its entity to the follow-word, its filter is stripped as invalid, and the
|
|
106
|
+
// query degrades into a full-store scan.
|
|
107
|
+
if (i > 0 && words[i - 1] === 'with') continue;
|
|
102
108
|
const w = words[i];
|
|
103
109
|
if (i + 1 < words.length) {
|
|
104
110
|
const bigram = w + ' ' + words[i + 1];
|
|
@@ -5,6 +5,14 @@ const path = require('path');
|
|
|
5
5
|
const { extractExcerpt, loadForgeConfig, findIndexPath } = require('./store-facade.cjs');
|
|
6
6
|
const { extractKeywordsFromIntent } = require('./store-nlp.cjs');
|
|
7
7
|
|
|
8
|
+
// Default safety cap for NLP listings without an explicit limit. Prevents an
|
|
9
|
+
// unbounded query from dumping the entire store into an LLM's context (a single
|
|
10
|
+
// uncapped query consumed ~28% of a plan run's input tokens — see
|
|
11
|
+
// doc/plans/store-query-nlp-response-shape-improvement.md). Callers that need
|
|
12
|
+
// everything use the exact `--sprint`/`--task` flag paths (which bypass this) or
|
|
13
|
+
// pass an explicit limit.
|
|
14
|
+
const DEFAULT_NLP_LIMIT = 25;
|
|
15
|
+
|
|
8
16
|
function escapeRe(s) {
|
|
9
17
|
return String(s).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
10
18
|
}
|
|
@@ -128,7 +136,7 @@ function executeQuery(plan, store, cfg) {
|
|
|
128
136
|
const trace = [];
|
|
129
137
|
const traverse = plan.traverse || plan;
|
|
130
138
|
const singMap = { bug: 'bugs', task: 'tasks', sprint: 'sprints', feature: 'features' };
|
|
131
|
-
|
|
139
|
+
let primary = singMap[traverse.primary] || traverse.primary || 'tasks';
|
|
132
140
|
let filter = { ...(traverse.filter || {}) };
|
|
133
141
|
const follow = traverse.follow || [];
|
|
134
142
|
const kwMatch = traverse.keywordMatch || {};
|
|
@@ -138,6 +146,7 @@ function executeQuery(plan, store, cfg) {
|
|
|
138
146
|
|
|
139
147
|
// Validate + strip invalid filters
|
|
140
148
|
const validation = validatePlan(plan);
|
|
149
|
+
const stripped = {};
|
|
141
150
|
if (validation.warnings.length > 0) {
|
|
142
151
|
const validators = buildFieldValidators();
|
|
143
152
|
const fields = validators[primary];
|
|
@@ -145,14 +154,17 @@ function executeQuery(plan, store, cfg) {
|
|
|
145
154
|
for (const key of Object.keys(filter)) {
|
|
146
155
|
if (!fields[key]) {
|
|
147
156
|
trace.push(`stripped invalid filter key: ${key}`);
|
|
157
|
+
stripped[key] = filter[key];
|
|
148
158
|
delete filter[key];
|
|
149
159
|
} else {
|
|
150
160
|
const spec = fields[key];
|
|
151
161
|
if (spec instanceof RegExp && !spec.test(String(filter[key]))) {
|
|
152
162
|
trace.push(`stripped filter ${key}="${filter[key]}" (value mismatch)`);
|
|
163
|
+
stripped[key] = filter[key];
|
|
153
164
|
delete filter[key];
|
|
154
165
|
} else if (Array.isArray(spec) && !spec.includes(String(filter[key]))) {
|
|
155
166
|
trace.push(`stripped filter ${key}="${filter[key]}" (not in enum)`);
|
|
167
|
+
stripped[key] = filter[key];
|
|
156
168
|
delete filter[key];
|
|
157
169
|
}
|
|
158
170
|
}
|
|
@@ -160,6 +172,21 @@ function executeQuery(plan, store, cfg) {
|
|
|
160
172
|
}
|
|
161
173
|
}
|
|
162
174
|
|
|
175
|
+
// Re-route on a stripped record-anchoring ID: an explicit taskId/bugId that
|
|
176
|
+
// was stripped because `primary` disagreed means the caller named a specific
|
|
177
|
+
// record. Honour it (re-route primary + restore the filter) instead of
|
|
178
|
+
// degrading into a full-collection scan. This is the engine-layer floor that
|
|
179
|
+
// backs up the parser fix in store-nlp.cjs.
|
|
180
|
+
const ID_ROUTE = { taskId: 'tasks', bugId: 'bugs' };
|
|
181
|
+
for (const idKey of Object.keys(ID_ROUTE)) {
|
|
182
|
+
if (stripped[idKey] !== undefined && primary !== ID_ROUTE[idKey]) {
|
|
183
|
+
trace.push(`re-routed primary ${primary} → ${ID_ROUTE[idKey]} (anchored ${idKey}="${stripped[idKey]}")`);
|
|
184
|
+
primary = ID_ROUTE[idKey];
|
|
185
|
+
filter[idKey] = stripped[idKey];
|
|
186
|
+
break;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
163
190
|
// List primary entities
|
|
164
191
|
let entities;
|
|
165
192
|
switch (primary) {
|
|
@@ -201,10 +228,16 @@ function executeQuery(plan, store, cfg) {
|
|
|
201
228
|
return { query: cfg.query || '', path: 'intent-nlp', traversalTrace: trace, count: totalMatched, results: [], relatedFileRefs: [], totalMatched };
|
|
202
229
|
}
|
|
203
230
|
|
|
204
|
-
// Limit
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
231
|
+
// Limit — honour an explicit limit; otherwise apply a default safety cap so an
|
|
232
|
+
// unbounded NLP listing never dumps the whole collection into the model's
|
|
233
|
+
// context. `truncated` + `totalMatched` let the caller detect and, if needed,
|
|
234
|
+
// re-query with an explicit limit or the exact-flag path.
|
|
235
|
+
const effectiveLimit = traverse.limit || DEFAULT_NLP_LIMIT;
|
|
236
|
+
let truncated = false;
|
|
237
|
+
if (entities.length > effectiveLimit) {
|
|
238
|
+
trace.push(`limited to ${effectiveLimit} (of ${totalMatched})${traverse.limit ? '' : ' [default cap]'}`);
|
|
239
|
+
entities = entities.slice(0, effectiveLimit);
|
|
240
|
+
truncated = true;
|
|
208
241
|
}
|
|
209
242
|
|
|
210
243
|
// Build results + follow FKs
|
|
@@ -263,6 +296,7 @@ function executeQuery(plan, store, cfg) {
|
|
|
263
296
|
results: allResults,
|
|
264
297
|
totalMatched,
|
|
265
298
|
returned: allResults.length,
|
|
299
|
+
truncated,
|
|
266
300
|
limit: traverse.limit || null,
|
|
267
301
|
sort: traverse.sort || null,
|
|
268
302
|
relatedFileRefs: [...new Set(relatedFiles)],
|
|
@@ -90,7 +90,8 @@ const DRIFT_MAP = {
|
|
|
90
90
|
'task-completed': ['task-committed'],
|
|
91
91
|
'implemented': ['implementing'],
|
|
92
92
|
'set': ['set-summary'],
|
|
93
|
-
'start': ['startTimestamp']
|
|
93
|
+
'start': ['startTimestamp'],
|
|
94
|
+
'create': ['write']
|
|
94
95
|
};
|
|
95
96
|
|
|
96
97
|
// ---------------------------------------------------------------------------
|
|
@@ -113,7 +113,49 @@ function describePredicate(pred) {
|
|
|
113
113
|
return `${pred.field} ${pred.op} ${pred.value}`;
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
-
module.exports = { preflight, resolveTaskArtifactDir, resolveSprintArtifactDir };
|
|
116
|
+
module.exports = { preflight, resolveTaskArtifactDir, resolveSprintArtifactDir, deriveSprintTaskFromArtifactPath };
|
|
117
|
+
|
|
118
|
+
// Derive {sprint} and {task} substitutions directly from a task's artifact path
|
|
119
|
+
// (task.path) when that path is a directory under `<engineeringRoot>/sprints/`.
|
|
120
|
+
//
|
|
121
|
+
// task.path is the authoritative artifact location — it is where the plan /
|
|
122
|
+
// implement phases actually write PLAN.md, REVIEW.md, etc. Splitting it tolerates
|
|
123
|
+
// ANY nesting depth and ANY on-disk naming, so a single rule covers both the
|
|
124
|
+
// modern 2-level layout (`sprints/<sprint>/<task>/`) and legacy 3-level layouts
|
|
125
|
+
// (`sprints/<sprint>/tasks/<task>/`) whose on-disk sprint dir name need not equal
|
|
126
|
+
// sprintId (e.g. sprintId "S19" → dir "sprint_19_platform_ux_improvements"). The
|
|
127
|
+
// directory-scan resolution (resolveSprintArtifactDir + resolveTaskArtifactDir)
|
|
128
|
+
// cannot express the `tasks/` nesting, which is what broke review-plan preflight
|
|
129
|
+
// for heterogeneous-layout projects (walkinto.in S19/S32/S33).
|
|
130
|
+
//
|
|
131
|
+
// {task} = the last path segment (the artifact directory name)
|
|
132
|
+
// {sprint} = everything between `sprints/` and that last segment, joined by "/"
|
|
133
|
+
//
|
|
134
|
+
// File-vs-dir guard: if task.path ends in a filename (has an extension), the
|
|
135
|
+
// artifact directory is its PARENT — strip the filename first. This prevents the
|
|
136
|
+
// bogus `.../TASK_PROMPT.md/PLAN.md` (ENOTDIR) seen when a project stores
|
|
137
|
+
// task.path as a file inside the artifact dir.
|
|
138
|
+
//
|
|
139
|
+
// Returns null when the path is absent, or not under `<engineeringRoot>/sprints/`
|
|
140
|
+
// (e.g. a forge/ source-file path — see regression S12-T06), or resolves to
|
|
141
|
+
// fewer than 2 directory segments. In every null case the caller falls back to
|
|
142
|
+
// the directory-scan resolution, preserving prior behaviour.
|
|
143
|
+
function deriveSprintTaskFromArtifactPath(taskPath, engineeringRoot) {
|
|
144
|
+
if (!taskPath) return null;
|
|
145
|
+
let norm = String(taskPath).replace(/\\/g, '/').replace(/\/+$/, '');
|
|
146
|
+
// File-vs-dir guard — drop a trailing filename so we split on the dir.
|
|
147
|
+
if (/\.[a-zA-Z0-9]+$/.test(norm)) {
|
|
148
|
+
norm = norm.replace(/\/[^/]*$/, '');
|
|
149
|
+
}
|
|
150
|
+
const er = String(engineeringRoot || 'engineering').replace(/\/+$/, '');
|
|
151
|
+
const prefix = er + '/sprints/';
|
|
152
|
+
if (!norm.startsWith(prefix)) return null;
|
|
153
|
+
const segs = norm.slice(prefix.length).split('/').filter(Boolean);
|
|
154
|
+
if (segs.length < 2) return null;
|
|
155
|
+
const task = segs[segs.length - 1];
|
|
156
|
+
const sprint = segs.slice(0, -1).join('/');
|
|
157
|
+
return { sprint, task };
|
|
158
|
+
}
|
|
117
159
|
|
|
118
160
|
// CLI shim: `node preflight-gate.cjs --phase <name> --task <taskId> [--bug <bugId>] [--workflow <name>]`
|
|
119
161
|
// exit codes: 0 ok, 1 gate(s) failed, 2 invalid args / missing definitions
|
|
@@ -246,10 +288,18 @@ if (require.main === module) {
|
|
|
246
288
|
// name is used both as the {sprint} substitution and as the directory in
|
|
247
289
|
// which resolveTaskArtifactDir scans for task subdirectories.
|
|
248
290
|
const sprintId = taskRecord ? taskRecord.sprintId : undefined;
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
291
|
+
// Primary resolution: derive {sprint}/{task} straight from task.path (the
|
|
292
|
+
// authoritative artifact directory). This honours arbitrary layout nesting —
|
|
293
|
+
// including legacy 3-level `sprints/<sprint>/tasks/<task>/` trees the
|
|
294
|
+
// directory-scan resolution below cannot express. Falls back to the scan when
|
|
295
|
+
// task.path is not an artifact dir under sprints/ (e.g. a forge/ source file).
|
|
296
|
+
const derived = taskRecord ? deriveSprintTaskFromArtifactPath(taskRecord.path, engineeringRoot) : null;
|
|
297
|
+
const resolvedSprintDir = derived
|
|
298
|
+
? derived.sprint
|
|
299
|
+
: (sprintId ? (resolveSprintArtifactDir(sprintId, engineeringRoot) || sprintId) : undefined);
|
|
300
|
+
const taskArtifactDir = derived
|
|
301
|
+
? derived.task
|
|
302
|
+
: resolveTaskArtifactDir(taskRecord, engineeringRoot, undefined, resolvedSprintDir);
|
|
253
303
|
// Fallback: if task.path points to a file (e.g., TASK_PROMPT.md) we want
|
|
254
304
|
// the *directory* segment, not the filename. Without this, a project that
|
|
255
305
|
// stores task.path as the prompt file would propagate "TASK_PROMPT.md" as
|
|
@@ -55,6 +55,7 @@ const { validateRecord, NULLABLE_FIELDS } = require('./lib/validate.js');
|
|
|
55
55
|
|
|
56
56
|
// FORGE-S22-T03: suggestion engine for "Did you mean?" on validation/transition errors
|
|
57
57
|
const { suggest, suggestEntityType, formatSuggestion } = require('./lib/suggest.cjs');
|
|
58
|
+
const { resolveSummaryFilename, PHASE_TO_KIND } = require('./lib/artifact-kinds.cjs');
|
|
58
59
|
|
|
59
60
|
// Valid phase keys for summaries (dot-delimited → underscore in JSON key)
|
|
60
61
|
const VALID_SUMMARY_PHASES = new Set(['plan', 'review_plan', 'implementation', 'code_review', 'validation', 'triage', 'approve']);
|
|
@@ -432,8 +433,8 @@ Commands:
|
|
|
432
433
|
progress-clear <sprintOrBugId> Clear (truncate) the progress log
|
|
433
434
|
write-collation-state '<json>' Write COLLATION_STATE.json
|
|
434
435
|
validate <entity> '<json>' Validate against schema without writing
|
|
435
|
-
set-summary <taskId> <phase> <jsonFile> Set a phase summary on a task record
|
|
436
|
-
set-bug-summary <bugId> <phase> <jsonFile> Set a phase summary on a bug record
|
|
436
|
+
set-summary <taskId> <phase> [<jsonFile>] Set a phase summary on a task record (sidecar auto-resolved from record.path when jsonFile omitted)
|
|
437
|
+
set-bug-summary <bugId> <phase> [<jsonFile>] Set a phase summary on a bug record (sidecar auto-resolved from record.path when jsonFile omitted)
|
|
437
438
|
describe <entity> Print the JSON Schema for an entity
|
|
438
439
|
template <entity> Print a canonical sample record (required fields populated)
|
|
439
440
|
|
|
@@ -1289,9 +1290,50 @@ function _setSummaryOnEntity(entityKind, entityId, phase, summaryFilePath) {
|
|
|
1289
1290
|
process.exit(1);
|
|
1290
1291
|
}
|
|
1291
1292
|
|
|
1293
|
+
// Load entity first — its `path` is the authoritative artifact directory and
|
|
1294
|
+
// is needed both to self-resolve the sidecar (when no file arg is given) and
|
|
1295
|
+
// to merge the summary below.
|
|
1296
|
+
const record = entityKind === 'task' ? store.getTask(entityId) : store.getBug(entityId);
|
|
1297
|
+
if (!record) {
|
|
1298
|
+
console.error(`${entityKind} not found: ${entityId}`);
|
|
1299
|
+
process.exit(1);
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1302
|
+
// ADR artifact-resolution Phase 1: when the caller omits the JSON file, derive
|
|
1303
|
+
// the sidecar from record.path + the canonical phase→filename map. The agent
|
|
1304
|
+
// never hand-builds the path (kills the Class-1 failures + the arity bug).
|
|
1305
|
+
let selfResolved = false;
|
|
1306
|
+
if (!summaryFilePath) {
|
|
1307
|
+
if (typeof record.path !== 'string' || record.path.length === 0) {
|
|
1308
|
+
console.error(`Cannot self-resolve summary sidecar: ${entityKind} ${entityId} has no "path". Pass an explicit <jsonFile>.`);
|
|
1309
|
+
process.exit(1);
|
|
1310
|
+
}
|
|
1311
|
+
// record.path is the entity directory; defensively strip a trailing filename.
|
|
1312
|
+
const dir = /\.(md|json)$/i.test(record.path) ? path.dirname(record.path) : record.path;
|
|
1313
|
+
summaryFilePath = path.join(dir, resolveSummaryFilename(entityKind, phase));
|
|
1314
|
+
selfResolved = true;
|
|
1315
|
+
}
|
|
1316
|
+
|
|
1292
1317
|
// Read and validate summary JSON
|
|
1293
1318
|
if (!fs.existsSync(summaryFilePath)) {
|
|
1294
|
-
|
|
1319
|
+
// v1.0.10: self-resolve looks for the CANONICAL filename. If an agent wrote a
|
|
1320
|
+
// non-canonical sidecar (e.g. VALIDATE-SUMMARY.json via the Write tool instead
|
|
1321
|
+
// of forge_artifact's VALIDATION-SUMMARY.json), surface the near-name file so
|
|
1322
|
+
// the error is fixable in one step rather than a silent dead-end.
|
|
1323
|
+
let hint = '';
|
|
1324
|
+
if (selfResolved) {
|
|
1325
|
+
try {
|
|
1326
|
+
const dir = path.dirname(summaryFilePath);
|
|
1327
|
+
const expected = path.basename(summaryFilePath);
|
|
1328
|
+
const nearby = fs.readdirSync(dir).filter((f) => f !== expected && f.endsWith('.json') && /summary/i.test(f));
|
|
1329
|
+
if (nearby.length > 0) {
|
|
1330
|
+
const kind = PHASE_TO_KIND[phase];
|
|
1331
|
+
hint = ` (expected ${expected}; found ${nearby.join(', ')} in the same dir — write the sidecar via ` +
|
|
1332
|
+
`forge_artifact artifact:"${kind}", or rename it to ${expected})`;
|
|
1333
|
+
}
|
|
1334
|
+
} catch (_) { /* dir unreadable — fall back to the plain message */ }
|
|
1335
|
+
}
|
|
1336
|
+
console.error(`Summary file not found: ${summaryFilePath}${hint}`);
|
|
1295
1337
|
process.exit(1);
|
|
1296
1338
|
}
|
|
1297
1339
|
|
|
@@ -1309,14 +1351,7 @@ function _setSummaryOnEntity(entityKind, entityId, phase, summaryFilePath) {
|
|
|
1309
1351
|
process.exit(1);
|
|
1310
1352
|
}
|
|
1311
1353
|
|
|
1312
|
-
//
|
|
1313
|
-
const record = entityKind === 'task' ? store.getTask(entityId) : store.getBug(entityId);
|
|
1314
|
-
if (!record) {
|
|
1315
|
-
console.error(`${entityKind} not found: ${entityId}`);
|
|
1316
|
-
process.exit(1);
|
|
1317
|
-
}
|
|
1318
|
-
|
|
1319
|
-
// Merge summary
|
|
1354
|
+
// Merge summary (record was loaded above for path resolution)
|
|
1320
1355
|
if (!record.summaries) record.summaries = {};
|
|
1321
1356
|
record.summaries[phase] = summary;
|
|
1322
1357
|
|
|
@@ -1394,8 +1429,8 @@ function cmdSetSummary() {
|
|
|
1394
1429
|
const phase = args[2];
|
|
1395
1430
|
const summaryFile = args[3];
|
|
1396
1431
|
|
|
1397
|
-
if (!taskId || !phase
|
|
1398
|
-
console.error('Usage: store-cli.cjs set-summary <taskId> <phase> <jsonFile>');
|
|
1432
|
+
if (!taskId || !phase) {
|
|
1433
|
+
console.error('Usage: store-cli.cjs set-summary <taskId> <phase> [<jsonFile>]');
|
|
1399
1434
|
process.exit(1);
|
|
1400
1435
|
}
|
|
1401
1436
|
|
|
@@ -1407,8 +1442,8 @@ function cmdSetBugSummary() {
|
|
|
1407
1442
|
const phase = args[2];
|
|
1408
1443
|
const summaryFile = args[3];
|
|
1409
1444
|
|
|
1410
|
-
if (!bugId || !phase
|
|
1411
|
-
console.error('Usage: store-cli.cjs set-bug-summary <bugId> <phase> <jsonFile>');
|
|
1445
|
+
if (!bugId || !phase) {
|
|
1446
|
+
console.error('Usage: store-cli.cjs set-bug-summary <bugId> <phase> [<jsonFile>]');
|
|
1412
1447
|
process.exit(1);
|
|
1413
1448
|
}
|
|
1414
1449
|
|