@event4u/agent-config 16.4.0 → 17.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.augment-plugin/marketplace.json +3 -3
- package/.augment-plugin/plugin.json +1 -1
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/skills/install-agent-config/SKILL.md +4 -4
- package/CHANGELOG.md +483 -669
- package/CONTRIBUTING.md +47 -0
- package/README.md +25 -25
- package/dist/agent-src/commands/{design.md → agent-design.md} +11 -7
- package/dist/agent-src/commands/agents/init.md +66 -3
- package/dist/agent-src/commands/agents/user/init.md +3 -0
- package/dist/agent-src/commands/{optimize/deep.md → analyze/and-optimize.md} +72 -33
- package/dist/agent-src/commands/analyze/inbox.md +168 -37
- package/dist/agent-src/commands/analyze/pr.md +144 -0
- package/dist/agent-src/commands/analyze/{repo.md → reference.md} +85 -14
- package/dist/agent-src/commands/analyze/roadmap-repos.md +19 -10
- package/dist/agent-src/commands/analyze.md +28 -12
- package/dist/agent-src/commands/audit.md +115 -0
- package/dist/agent-src/commands/brand/review.md +13 -2
- package/dist/agent-src/commands/brand/tokens.md +3 -3
- package/dist/agent-src/commands/brand/voice.md +8 -5
- package/dist/agent-src/commands/brand.md +2 -2
- package/dist/agent-src/commands/challenge-me/closure.md +25 -0
- package/dist/agent-src/commands/design-system/import.md +8 -3
- package/dist/agent-src/commands/design-system/sync.md +98 -0
- package/dist/agent-src/commands/design-system.md +6 -1
- package/dist/agent-src/commands/evals/analyze.json +44 -0
- package/dist/agent-src/commands/evals/audit.json +12 -0
- package/dist/agent-src/commands/evals/retro.json +12 -0
- package/dist/agent-src/commands/fix/ci.md +10 -8
- package/dist/agent-src/commands/ghostwriter/write.md +22 -0
- package/dist/agent-src/commands/memory/learn-low-impact.md +70 -83
- package/dist/agent-src/commands/memory/propose.md +12 -0
- package/dist/agent-src/commands/memory.md +1 -1
- package/dist/agent-src/commands/optimize.md +4 -3
- package/dist/agent-src/commands/post-as/me.md +18 -0
- package/dist/agent-src/commands/pr/create.md +17 -342
- package/dist/agent-src/commands/pr/merge.md +129 -368
- package/dist/agent-src/commands/retro.md +121 -0
- package/dist/agent-src/commands/review/routing.md +1 -1
- package/dist/agent-src/commands/roadmap/next.md +4 -1
- package/dist/agent-src/commands/roadmap/process-full.md +46 -333
- package/dist/agent-src/commands/roadmap/triage-parked.md +6 -2
- package/dist/agent-src/commands/team-knowledge/consolidate.md +2 -2
- package/dist/agent-src/commands/team-knowledge.md +1 -1
- package/dist/agent-src/commands/threat-model.md +1 -1
- package/dist/agent-src/commands/upstream-contribute.md +91 -101
- package/dist/agent-src/commands/worktree/cleanup.md +18 -11
- package/dist/agent-src/contexts/contracts/consumer-agents-md-guide.md +54 -0
- package/dist/agent-src/contexts/execution/analysis-loop.md +137 -0
- package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +3 -3
- package/dist/agent-src/contexts/execution/decision-closure-execution.md +1 -1
- package/dist/agent-src/contexts/execution/host-capability-manifest.md +6 -0
- package/dist/agent-src/contexts/execution/orchestration-telemetry.md +11 -4
- package/dist/agent-src/contexts/execution/pr-create-branches-content.md +250 -0
- package/dist/agent-src/contexts/execution/pr-create-branches-freshness.md +150 -0
- package/dist/agent-src/contexts/execution/pr-merge-queue.md +287 -0
- package/dist/agent-src/contexts/execution/pr-merge-sync.md +276 -0
- package/dist/agent-src/contexts/execution/pr-merge-trust-boundary.md +69 -0
- package/dist/agent-src/contexts/execution/process-full-all.md +233 -0
- package/dist/agent-src/contexts/execution/process-full-delivery.md +231 -0
- package/dist/agent-src/contexts/execution/roadmap-execution-contract-branches.md +42 -0
- package/dist/agent-src/contexts/execution/roadmap-execution-contract.md +1 -35
- package/dist/agent-src/contexts/execution/roadmap-process-loop-close.md +235 -0
- package/dist/agent-src/contexts/execution/roadmap-process-loop-prescan.md +216 -0
- package/dist/agent-src/contexts/execution/roadmap-process-loop-run.md +253 -0
- package/dist/agent-src/contexts/execution/roadmap-process-loop-set.md +212 -0
- package/dist/agent-src/contexts/execution/roadmap-process-loop.md +25 -864
- package/dist/agent-src/contexts/execution/subagent-spawn-contract.md +14 -2
- package/dist/agent-src/contexts/execution/subagent-steering.md +65 -8
- package/dist/agent-src/contexts/model-recommendations.md +5 -5
- package/dist/agent-src/contexts/subagent-configuration.md +1 -1
- package/dist/agent-src/guidelines/agent-infra/api-cost-levers.md +4 -3
- package/dist/agent-src/guidelines/agent-infra/model-recommendation.md +11 -5
- package/dist/agent-src/guidelines/agent-infra/rule-body-migration-inventory.md +1 -1
- package/dist/agent-src/guidelines/agent-infra/self-improvement-pipeline.md +47 -24
- package/dist/agent-src/guidelines/design-antipatterns.md +6 -1
- package/dist/agent-src/guidelines/design-asset-discipline.md +17 -0
- package/dist/agent-src/guidelines/design-fidelity-routing.md +1 -0
- package/dist/agent-src/guidelines/php/api-design.md +10 -1
- package/dist/agent-src/rules/brand-source-of-truth.md +7 -6
- package/dist/agent-src/rules/code-provenance.md +1 -1
- package/dist/agent-src/rules/context-hygiene.md +0 -1
- package/dist/agent-src/rules/design-fidelity.md +12 -13
- package/dist/agent-src/rules/external-reference-deep-dive.md +2 -2
- package/dist/agent-src/rules/fix-what-you-see.md +1 -1
- package/dist/agent-src/rules/low-impact-corpus-privacy-floor.md +14 -15
- package/dist/agent-src/rules/missing-skill-recovery.md +12 -11
- package/dist/agent-src/rules/neighbour-precedence.md +1 -1
- package/dist/agent-src/rules/recurring-criticism.md +1 -1
- package/dist/agent-src/rules/roadmap-ci-steps-policy.md +0 -2
- package/dist/agent-src/rules/self-repair-loop.md +2 -2
- package/dist/agent-src/rules/token-budget-discipline.md +2 -2
- package/dist/agent-src/scripts/dashboard_mode.ts +4 -1
- package/dist/agent-src/scripts/roadmap_age.ts +175 -0
- package/dist/agent-src/scripts/update_roadmap_progress.ts +10 -2
- package/dist/agent-src/skills/accessibility-auditor/SKILL.md +3 -3
- package/dist/agent-src/skills/accessibility-auditor/data/aria-patterns.csv +2 -0
- package/dist/agent-src/skills/accessibility-auditor/data/manifest.json +3 -3
- package/dist/agent-src/skills/agent-security-review/SKILL.md +2 -2
- package/dist/agent-src/skills/agents-md-thin-root/SKILL.md +12 -4
- package/dist/agent-src/skills/ai-code-blindspots/SKILL.md +7 -0
- package/dist/agent-src/skills/ai-council/references/advanced-modes.md +11 -1
- package/dist/agent-src/skills/ai-council/references/cost-and-redaction.md +7 -0
- package/dist/agent-src/skills/ai-council/references/execution-modes.md +7 -0
- package/dist/agent-src/skills/ai-council/references/output-and-synthesis.md +19 -0
- package/dist/agent-src/skills/ai-council/references/procedure.md +7 -0
- package/dist/agent-src/skills/api-design/SKILL.md +2 -2
- package/dist/agent-src/skills/api-endpoint/SKILL.md +2 -2
- package/dist/agent-src/skills/authz-review/SKILL.md +5 -3
- package/dist/agent-src/skills/blade-ui/SKILL.md +2 -2
- package/dist/agent-src/skills/brand/SKILL.md +7 -3
- package/dist/agent-src/skills/brand-asset-generation/SKILL.md +13 -6
- package/dist/agent-src/skills/brand-audit/SKILL.md +2 -1
- package/dist/agent-src/skills/brand-identity/SKILL.md +5 -4
- package/dist/agent-src/skills/brand-strategy/SKILL.md +5 -4
- package/dist/agent-src/skills/brand-to-tokens/SKILL.md +18 -39
- package/dist/agent-src/skills/brand-to-tokens/templates/marp-brand-deck.md.example +2 -2
- package/dist/agent-src/skills/brand-to-tokens/templates/reveal-brand-deck.yaml +2 -2
- package/dist/agent-src/skills/canvas-design/SKILL.md +16 -4
- package/dist/agent-src/skills/competitive-positioning/SKILL.md +2 -2
- package/dist/agent-src/skills/composer-packages/SKILL.md +18 -0
- package/dist/agent-src/skills/condense-memory/SKILL.md +1 -1
- package/dist/agent-src/skills/content-funnel-design/SKILL.md +8 -1
- package/dist/agent-src/skills/context-authoring/SKILL.md +1 -1
- package/dist/agent-src/skills/context-document/SKILL.md +2 -2
- package/dist/agent-src/skills/corpus-grounding/SKILL.md +6 -6
- package/dist/agent-src/skills/corpus-grounding/scripts/decision_engine.ts +13 -11
- package/dist/agent-src/skills/corpus-grounding/scripts/ground.mjs +1706 -0
- package/dist/agent-src/skills/corpus-grounding/scripts/schema_validator.ts +7 -1
- package/dist/agent-src/skills/dashboard-design/SKILL.md +1 -1
- package/dist/agent-src/skills/data-flow-mapper/SKILL.md +5 -2
- package/dist/agent-src/skills/database/SKILL.md +5 -4
- package/dist/agent-src/skills/decision-record/references/weighted-matrix.md +12 -0
- package/dist/agent-src/skills/deep-reading-analyst/SKILL.md +1 -1
- package/dist/agent-src/skills/dependency-upgrade/SKILL.md +61 -11
- package/dist/agent-src/skills/description-assist/SKILL.md +1 -1
- package/dist/agent-src/skills/design-intelligence/SKILL.md +1 -1
- package/dist/agent-src/skills/design-intelligence/data/landing.csv +1 -1
- package/dist/agent-src/skills/design-intelligence/references/context-and-registers.md +10 -2
- package/dist/agent-src/skills/design-intelligence/references/design-languages.md +1 -1
- package/dist/agent-src/skills/design-intelligence/references/design-rules-checklist.md +4 -3
- package/dist/agent-src/skills/design-intelligence/references/integration-mapping.md +25 -22
- package/dist/agent-src/skills/{wireframe → design-review}/references/story-beat-ledger.schema.json +1 -1
- package/dist/agent-src/skills/design-review/references/verification-automation.md +11 -3
- package/dist/agent-src/skills/design-system-capture/SKILL.md +15 -10
- package/dist/agent-src/skills/design-system-capture/references/design-system-json.md +20 -5
- package/dist/agent-src/skills/design-system-capture/references/import-procedure.md +2 -2
- package/dist/agent-src/skills/design-tokens/SKILL.md +23 -23
- package/dist/agent-src/skills/design-tokens/scripts/tokens.mjs +1037 -0
- package/dist/agent-src/skills/design-tokens/scripts/tokens.ts +336 -13
- package/dist/agent-src/skills/design-tokens/templates/design-tokens-starter.json +52 -53
- package/dist/agent-src/skills/docker/SKILL.md +1 -1
- package/dist/agent-src/skills/estimate-ticket/SKILL.md +1 -1
- package/dist/agent-src/skills/existing-ui-audit/SKILL.md +14 -276
- package/dist/agent-src/skills/existing-ui-audit/procedure.yaml +44 -0
- package/dist/agent-src/skills/existing-ui-audit/references/anti-slop-cross-reference.md +1 -1
- package/dist/agent-src/skills/existing-ui-audit/references/steps/00-inspect-stack-and-input.md +4 -0
- package/dist/agent-src/skills/existing-ui-audit/references/steps/01-enumerate-components.md +26 -0
- package/dist/agent-src/skills/existing-ui-audit/references/steps/01b-detect-component-taxonomy.md +7 -0
- package/dist/agent-src/skills/existing-ui-audit/references/steps/02-identify-design-system.md +12 -0
- package/dist/agent-src/skills/existing-ui-audit/references/steps/03-detect-design-tokens.md +35 -0
- package/dist/agent-src/skills/existing-ui-audit/references/steps/04-detect-shadcn-inventory.md +13 -0
- package/dist/agent-src/skills/existing-ui-audit/references/steps/04b-live-storybook-read.md +26 -0
- package/dist/agent-src/skills/existing-ui-audit/references/steps/05-list-reusable-patterns.md +14 -0
- package/dist/agent-src/skills/existing-ui-audit/references/steps/06-match-candidates.md +52 -0
- package/dist/agent-src/skills/existing-ui-audit/references/steps/07-greenfield-branch.md +29 -0
- package/dist/agent-src/skills/existing-ui-audit/references/steps/08-a11y-baseline.md +40 -0
- package/dist/agent-src/skills/existing-ui-audit/references/steps/09-validate-and-write.md +5 -0
- package/dist/agent-src/skills/experiment-loop/SKILL.md +1 -1
- package/dist/agent-src/skills/fe-design/references/design-patterns.md +65 -4
- package/dist/agent-src/skills/fe-design/references/design-read-and-memory.md +1 -1
- package/dist/agent-src/skills/fe-design/references/source-led-port.md +1 -1
- package/dist/agent-src/skills/finishing-a-development-branch/SKILL.md +6 -6
- package/dist/agent-src/skills/flux/SKILL.md +1 -1
- package/dist/agent-src/skills/form-handler/SKILL.md +15 -2
- package/dist/agent-src/skills/frontend-render-security/SKILL.md +9 -0
- package/dist/agent-src/skills/git-workflow/SKILL.md +2 -2
- package/dist/agent-src/skills/git-workflow/references/branch-update.md +7 -0
- package/dist/agent-src/skills/git-workflow/references/commit-subject.md +12 -0
- package/dist/agent-src/skills/git-workflow/references/push-closes-its-loop.md +10 -0
- package/dist/agent-src/skills/gtm-launch/SKILL.md +8 -1
- package/dist/agent-src/skills/html-deck/SKILL.md +7 -2
- package/dist/agent-src/skills/humanizer/SKILL.md +16 -3
- package/dist/agent-src/skills/humanizer/references/anti-aiisms.md +13 -1
- package/dist/agent-src/skills/humanizer/references/fixtures.md +8 -0
- package/dist/agent-src/skills/iconography/SKILL.md +4 -2
- package/dist/agent-src/skills/image-provider-routing/SKILL.md +16 -5
- package/dist/agent-src/skills/js-library-packaging/SKILL.md +5 -4
- package/dist/agent-src/skills/js-library-packaging/scripts/check_package_surface.mjs +197 -0
- package/dist/agent-src/skills/judge-artifact-completeness/SKILL.md +1 -1
- package/dist/agent-src/skills/judge-security-auditor/SKILL.md +2 -2
- package/dist/agent-src/skills/launch-readiness/SKILL.md +18 -22
- package/dist/agent-src/skills/learning-to-rule-or-skill/SKILL.md +5 -5
- package/dist/agent-src/skills/livewire/SKILL.md +1 -1
- package/dist/agent-src/skills/llm-provider-knowledge/SKILL.md +18 -0
- package/dist/agent-src/skills/logo-generation/SKILL.md +21 -11
- package/dist/agent-src/skills/market-entry-analysis/SKILL.md +6 -1
- package/dist/agent-src/skills/markitdown/SKILL.md +1 -1
- package/dist/agent-src/skills/memory-consolidation/SKILL.md +2 -2
- package/dist/agent-src/skills/messaging-architecture/SKILL.md +8 -1
- package/dist/agent-src/skills/motion-choreographer/SKILL.md +2 -2
- package/dist/agent-src/skills/playwright-testing/SKILL.md +2 -0
- package/dist/agent-src/skills/positioning-strategy/SKILL.md +10 -2
- package/dist/agent-src/skills/prediction-pool-optimizer/references/ev-fixtures.md +13 -0
- package/dist/agent-src/skills/prediction-pool-optimizer/references/odds-and-bonus.md +7 -0
- package/dist/agent-src/skills/project-analysis-core/SKILL.md +1 -1
- package/dist/agent-src/skills/project-analysis-hypothesis-driven/SKILL.md +1 -1
- package/dist/agent-src/skills/project-analyzer/SKILL.md +14 -75
- package/dist/agent-src/skills/project-analyzer/procedure.yaml +39 -0
- package/dist/agent-src/skills/project-analyzer/references/steps/01-project-overview.md +9 -0
- package/dist/agent-src/skills/project-analyzer/references/steps/02-architecture.md +7 -0
- package/dist/agent-src/skills/project-analyzer/references/steps/03-data-layer.md +6 -0
- package/dist/agent-src/skills/project-analyzer/references/steps/04-business-domains.md +7 -0
- package/dist/agent-src/skills/project-analyzer/references/steps/05-api-surface.md +6 -0
- package/dist/agent-src/skills/project-analyzer/references/steps/06-service-map.md +6 -0
- package/dist/agent-src/skills/project-analyzer/references/steps/07-module-inventory.md +6 -0
- package/dist/agent-src/skills/project-analyzer/references/steps/08-infrastructure-and-testing.md +5 -0
- package/dist/agent-src/skills/project-analyzer/references/steps/09-agent-docs-audit.md +6 -0
- package/dist/agent-src/skills/project-analyzer/references/steps/10-gap-analysis.md +6 -0
- package/dist/agent-src/skills/quality-tools/references/js-ts-tools.md +10 -0
- package/dist/agent-src/skills/quality-tools/references/php-tools.md +13 -0
- package/dist/agent-src/skills/quality-tools/references/python-tools.md +11 -0
- package/dist/agent-src/skills/react-native-setup/SKILL.md +7 -2
- package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +5 -1
- package/dist/agent-src/skills/react-shadcn-ui/references/registry.md +13 -0
- package/dist/agent-src/skills/react-shadcn-ui/scripts/shadcn_add.mjs +315 -0
- package/dist/agent-src/skills/react-shadcn-ui/scripts/shadcn_add.ts +6 -6
- package/dist/agent-src/skills/receiving-code-review/SKILL.md +1 -1
- package/dist/agent-src/skills/refine-ticket/SKILL.md +2 -2
- package/dist/agent-src/skills/release-comms/SKILL.md +2 -1
- package/dist/agent-src/skills/repomix-packer/SKILL.md +2 -2
- package/dist/agent-src/skills/requesting-code-review/SKILL.md +3 -3
- package/dist/agent-src/skills/roadmap-management/references/archival.md +3 -3
- package/dist/agent-src/skills/roadmap-management/references/authoring.md +9 -2
- package/dist/agent-src/skills/roadmap-management/references/dashboard.md +3 -3
- package/dist/agent-src/skills/roadmap-management/references/lifecycle.md +3 -3
- package/dist/agent-src/skills/roadmap-writing/SKILL.md +4 -4
- package/dist/agent-src/skills/rtk-output-filtering/SKILL.md +1 -1
- package/dist/agent-src/skills/rule-writing/SKILL.md +1 -2
- package/dist/agent-src/skills/security/SKILL.md +41 -5
- package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +5 -3
- package/dist/agent-src/skills/skill-reviewer/SKILL.md +1 -1
- package/dist/agent-src/skills/skill-writing/SKILL.md +23 -8
- package/dist/agent-src/skills/skill-writing/references/section-patterns.md +19 -1
- package/dist/agent-src/skills/source-discovery/SKILL.md +3 -3
- package/dist/agent-src/skills/sql-writing/SKILL.md +2 -2
- package/dist/agent-src/skills/standards-from-config/SKILL.md +2 -2
- package/dist/agent-src/skills/storybook-workshop/SKILL.md +5 -0
- package/dist/agent-src/skills/storybook-workshop/scripts/story_contrast_floor.mjs +99 -0
- package/dist/agent-src/skills/subagent-orchestration/SKILL.md +13 -13
- package/dist/agent-src/skills/subagent-orchestration/prompts/README.md +4 -3
- package/dist/agent-src/skills/svg-authoring/SKILL.md +324 -0
- package/dist/agent-src/skills/systematic-debugging/SKILL.md +2 -2
- package/dist/agent-src/skills/tailwind-engineer/SKILL.md +8 -3
- package/dist/agent-src/skills/tailwind-engineer/scripts/tailwind_config_gen.mjs +482 -0
- package/dist/agent-src/skills/test-case-discovery/SKILL.md +1 -1
- package/dist/agent-src/skills/threat-modeling/SKILL.md +8 -1
- package/dist/agent-src/skills/threat-modeling/data/manifest.json +5 -2
- package/dist/agent-src/skills/threat-modeling/data/reasoning.csv +10 -10
- package/dist/agent-src/skills/threat-modeling/data/surfaces.csv +11 -10
- package/dist/agent-src/skills/threat-modeling/data/threats.csv +34 -20
- package/dist/agent-src/skills/type-design/SKILL.md +196 -0
- package/dist/agent-src/skills/type-design/references/font-spec.md +90 -0
- package/dist/agent-src/skills/type-design/references/gates.md +113 -0
- package/dist/agent-src/skills/type-design/references/toolchain.md +66 -0
- package/dist/agent-src/skills/typography-system/SKILL.md +21 -11
- package/dist/agent-src/skills/typography-system/references/worked-scales.md +85 -0
- package/dist/agent-src/skills/ui-apply-generic/SKILL.md +1 -1
- package/dist/agent-src/skills/universal-project-analysis/SKILL.md +1 -1
- package/dist/agent-src/skills/upstream-contribute/SKILL.md +120 -125
- package/dist/agent-src/skills/using-git-worktrees/SKILL.md +1 -0
- package/dist/agent-src/skills/verify-repair-loop/SKILL.md +1 -1
- package/dist/agent-src/skills/voice-and-tone-design/SKILL.md +71 -2
- package/dist/agent-src/skills/wireframe/SKILL.md +5 -2
- package/dist/agent-src/skills/worktree-lifecycle/SKILL.md +16 -14
- package/dist/agent-src/templates/AGENTS.md +1 -1
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/agents/proposal.example.md +1 -1
- package/dist/agent-src/templates/github-workflows/advisories-daily.yml +85 -0
- package/dist/agent-src/templates/roadmaps.md +39 -1
- package/dist/agent-src/templates/scripts/check_memory.ts +2 -2
- package/dist/agent-src/templates/scripts/historical-bug-patterns.example.yml +13 -1
- package/dist/agent-src/templates/scripts/work_engine/cli.ts +17 -0
- package/dist/agent-src/templates/scripts/work_engine/cli_args.ts +10 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/scaffold.ts +22 -13
- package/dist/agent-src/templates/scripts/work_engine/dispatcher.ts +18 -4
- package/dist/agent-src/templates/scripts/work_engine/procedure/checks.ts +283 -0
- package/dist/agent-src/templates/scripts/work_engine/procedure/run.ts +432 -0
- package/dist/agent-src/templates/scripts/work_engine/procedure/sidecar.ts +185 -0
- package/dist/agent-src/templates/scripts/work_engine/state.ts +3 -0
- package/dist/cli/commands/uiRender.js +265 -13
- package/dist/cli/commands/uiRenderAsset.js +1316 -0
- package/dist/cli/commands/uiRenderAssetCompare.js +752 -0
- package/dist/cli/commands/uiRenderAssetFonts.js +158 -0
- package/dist/cli/commands/uiRenderAssetGrid.js +265 -0
- package/dist/cli/commands/uiRenderAssetGrounds.js +323 -0
- package/dist/cli/commands/uiRenderAssetIsolation.js +85 -0
- package/dist/cli/commands/uiRenderAssetTypes.js +133 -0
- package/dist/cli/initRouting.js +1 -1
- package/dist/cli/main.js +47 -1
- package/dist/cli/mcp/dispatch.js +31 -9
- package/dist/cli/python/knowledge_ingest.js +7 -39
- package/dist/cli/python/workspace_secrets.js +4 -177
- package/dist/cli/registry.js +5 -2
- package/dist/cli-delegate/archive_completed_roadmaps.js +3 -2
- package/dist/cli-delegate/check_update_banner.js +635 -266
- package/dist/cli-delegate/{chunk-AED2VQGM.js → chunk-2CX7NWRB.js} +233 -437
- package/dist/cli-delegate/{chunk-F3QDG2GT.js → chunk-2SFOOFJJ.js} +259 -159
- package/dist/cli-delegate/chunk-2Y5AMLMY.js +136 -0
- package/dist/cli-delegate/{chunk-OKJUIAPS.js → chunk-4E2W63DA.js} +1 -62
- package/dist/cli-delegate/{chunk-6SRJTYJS.js → chunk-4SHNERBL.js} +37 -16
- package/dist/cli-delegate/chunk-5VO3RTMV.js +208 -0
- package/dist/cli-delegate/chunk-6E2LDY4F.js +27 -0
- package/dist/cli-delegate/{chunk-XQTPXKFA.js → chunk-6ZD2QZMN.js} +8 -17
- package/dist/cli-delegate/{chunk-6V5FMA3P.js → chunk-7CEI2YPS.js} +1 -1
- package/dist/cli-delegate/{chunk-DMSZHXZS.js → chunk-7DRWULEQ.js} +80 -7
- package/dist/cli-delegate/chunk-7NXCZSDL.js +54 -0
- package/dist/cli-delegate/chunk-AX3U3UWJ.js +328 -0
- package/dist/cli-delegate/{chunk-WOKWX5PL.js → chunk-BKALSTBZ.js} +18 -3
- package/dist/cli-delegate/chunk-BMGUGSY6.js +103 -0
- package/dist/cli-delegate/chunk-BYV46VRM.js +3309 -0
- package/dist/cli-delegate/{chunk-5GPULQBE.js → chunk-CAL76ADI.js} +4215 -682
- package/dist/cli-delegate/chunk-DSY6LLCQ.js +127 -0
- package/dist/cli-delegate/chunk-E6XNBVE4.js +581 -0
- package/dist/cli-delegate/{chunk-ZUZKZYCN.js → chunk-ESUNQ5XR.js} +46 -10
- package/dist/cli-delegate/{chunk-G5VVIZRC.js → chunk-F7HLSW6P.js} +1 -1
- package/dist/cli-delegate/chunk-FIEEOH5C.js +133 -0
- package/dist/cli-delegate/chunk-FKYZOWVD.js +719 -0
- package/dist/cli-delegate/chunk-GOMILC3O.js +918 -0
- package/dist/cli-delegate/chunk-I4KJYVPB.js +69 -0
- package/dist/cli-delegate/{chunk-JQOM7TTM.js → chunk-IDAOTDPE.js} +1 -100
- package/dist/cli-delegate/chunk-IROAQ77A.js +137 -0
- package/dist/cli-delegate/chunk-J2SJZICO.js +698 -0
- package/dist/cli-delegate/{chunk-6YQC2HLF.js → chunk-JHMMWNJ2.js} +54 -40
- package/dist/cli-delegate/{chunk-WQWXGIWB.js → chunk-M6CRG5O6.js} +165 -15
- package/dist/cli-delegate/{chunk-PHD7OOLE.js → chunk-MQ2UDEGV.js} +14 -3
- package/dist/cli-delegate/chunk-NTM7G2V4.js +220 -0
- package/dist/cli-delegate/chunk-PV7S5DPJ.js +175 -0
- package/dist/cli-delegate/{chunk-F7DQWYR5.js → chunk-RAXQOETZ.js} +6 -2
- package/dist/cli-delegate/{chunk-T7XSJSUQ.js → chunk-SIOMDAKL.js} +980 -784
- package/dist/cli-delegate/{chunk-KR6EM23A.js → chunk-TULVDQ4L.js} +3 -48
- package/dist/cli-delegate/chunk-UUYEKXKR.js +20 -0
- package/dist/cli-delegate/{chunk-7XGD2OEU.js → chunk-UXWHY6CQ.js} +2 -1
- package/dist/cli-delegate/{chunk-PWX7CKMD.js → chunk-VC3ECUEK.js} +1 -1
- package/dist/cli-delegate/{chunk-KXXWJTDO.js → chunk-WMNYVIYX.js} +1 -1
- package/dist/cli-delegate/chunk-XCY5KKUC.js +181 -0
- package/dist/cli-delegate/{chunk-H76PHZBI.js → chunk-XLY5G3CM.js} +14 -19
- package/dist/cli-delegate/cmd_adr_effective.js +41 -2
- package/dist/cli-delegate/cmd_analyze_session.js +7 -7
- package/dist/cli-delegate/cmd_brand_status.js +1287 -10
- package/dist/cli-delegate/cmd_ci_settle.js +330 -0
- package/dist/cli-delegate/cmd_conformance.js +669 -822
- package/dist/cli-delegate/cmd_doctor.js +26 -16
- package/dist/cli-delegate/cmd_doctor_neighbours.js +10 -7
- package/dist/cli-delegate/cmd_explain.js +9 -24
- package/dist/cli-delegate/cmd_export.js +14 -11
- package/dist/cli-delegate/cmd_fleet.js +5 -3
- package/dist/cli-delegate/cmd_git_convention.js +8 -4
- package/dist/cli-delegate/cmd_handoff.js +79 -242
- package/dist/cli-delegate/cmd_mcp_available.js +1 -1
- package/dist/cli-delegate/cmd_memory_get.js +4 -2
- package/dist/cli-delegate/cmd_migrate.js +2 -2
- package/dist/cli-delegate/cmd_packs_active.js +2 -2
- package/dist/cli-delegate/cmd_preflight.js +7 -5
- package/dist/cli-delegate/cmd_prune.js +16 -13
- package/dist/cli-delegate/cmd_route_audit.js +11 -8
- package/dist/cli-delegate/cmd_route_explain.js +649 -16
- package/dist/cli-delegate/cmd_session_recycle.js +15 -6
- package/dist/cli-delegate/cmd_settings_check.js +2 -2
- package/dist/cli-delegate/cmd_settings_get.js +1 -1
- package/dist/cli-delegate/cmd_settings_migrate.js +14 -11
- package/dist/cli-delegate/cmd_settings_set.js +1 -1
- package/dist/cli-delegate/cmd_sync.js +16 -13
- package/dist/cli-delegate/cmd_uninstall.js +185 -31
- package/dist/cli-delegate/cmd_update.js +67 -3
- package/dist/cli-delegate/cmd_upgrade.js +38 -7
- package/dist/cli-delegate/cmd_validate.js +16 -13
- package/dist/cli-delegate/cmd_versions.js +1 -1
- package/dist/cli-delegate/dashboard_mode.js +1 -1
- package/dist/cli-delegate/gate_execute.js +4 -3
- package/dist/cli-delegate/roadmap_age.js +22 -0
- package/dist/cli-delegate/roadmap_gates.js +4 -3
- package/dist/cli-delegate/update_roadmap_progress.js +3 -2
- package/dist/cli-delegate/upgrade_unattended-VVL6JLSX.js +541 -0
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +409 -201
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +8 -8
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +36 -27
- package/dist/discovery/trust-report.md +3 -3
- package/dist/discovery/workspaces.json +25 -16
- package/dist/hooks/chat_history.chunk.cjs +6852 -0
- package/dist/hooks/chat_history.chunk.cjs.sha256 +1 -0
- package/dist/hooks/dispatch.js +17706 -18627
- package/dist/hooks/dispatch.sha256 +1 -1
- package/dist/hooks/egress_engine.chunk.cjs +915 -0
- package/dist/hooks/egress_engine.chunk.cjs.sha256 +1 -0
- package/dist/hooks/svg_rules.chunk.cjs +1858 -0
- package/dist/hooks/svg_rules.chunk.cjs.sha256 +1 -0
- package/dist/install/conflict.js +36 -6
- package/dist/install/conflictTracker.js +81 -7
- package/dist/install/detect.js +3 -3
- package/dist/install/hostPermissionsAdapter.js +106 -0
- package/dist/install/install.mjs +3117 -1949
- package/dist/install/installThinLayer.js +1 -1
- package/dist/install/manifestFiles.js +21 -0
- package/dist/install/noGoDenyRows.js +300 -0
- package/dist/install/noGoRules.js +368 -0
- package/dist/install/ownershipLedger.js +133 -0
- package/dist/install/plan.js +1 -1
- package/dist/install/preflight.js +39 -8
- package/dist/install/preserve.js +74 -12
- package/dist/install/recordedOwnership.js +88 -5
- package/dist/install/rule_scope.js +20 -3
- package/dist/install/stagedRuntime.js +455 -0
- package/dist/install/toolsArg.js +19 -0
- package/dist/install/userPin.js +47 -0
- package/dist/install/wizard-plan.js +26 -4
- package/dist/mcp/awesome-mcp-servers.row.md +1 -1
- package/dist/mcp/mcp-cloudflare-catalogue.json +3 -2
- package/dist/mcp/registry-manifest.json +6 -5
- package/dist/mcp/server.json +3 -3
- package/dist/mcp/server.mjs +9814 -5333
- package/dist/router.json +1 -1
- package/dist/scripts/_lib/agent_settings.js +7 -12
- package/dist/scripts/_lib/asset_render_record.js +219 -0
- package/dist/scripts/_lib/claude_builtin_names.js +9 -4
- package/dist/scripts/_lib/claude_settings_hooks.js +102 -34
- package/dist/scripts/_lib/egress_rules.js +766 -0
- package/dist/scripts/_lib/environment_detector.js +24 -33
- package/dist/scripts/_lib/global_deploy_inventory.js +146 -9
- package/dist/scripts/_lib/guidelines_lane.js +10 -1
- package/dist/scripts/_lib/identifier_redaction.js +24 -0
- package/dist/scripts/_lib/installed_layer.js +17 -0
- package/dist/scripts/_lib/installed_layer_normalise.js +72 -0
- package/dist/scripts/_lib/lean_projection_mode.js +34 -152
- package/dist/scripts/_lib/project_tree_form.js +118 -0
- package/dist/scripts/_lib/scan_scope.js +105 -0
- package/dist/scripts/_lib/scoped_projection.js +133 -3
- package/dist/scripts/_lib/settings_removed_keys.js +29 -0
- package/dist/scripts/_lib/settings_renamed_keys.js +17 -5
- package/dist/scripts/_lib/subagent_native_fields.js +35 -0
- package/dist/scripts/_lib/svg_dom.js +284 -0
- package/dist/scripts/_lib/svg_filled_counter.js +285 -0
- package/dist/scripts/_lib/svg_geometry.js +477 -0
- package/dist/scripts/_lib/svg_motion.js +179 -0
- package/dist/scripts/_lib/svg_rules.js +1339 -0
- package/dist/scripts/_lib/svg_urls.js +67 -0
- package/dist/scripts/_lib/ui_surface.js +19 -0
- package/dist/scripts/_lib/verification_command.js +364 -0
- package/dist/scripts/_lib/workspace_secrets.js +229 -0
- package/dist/scripts/ai_council/seat_policy.js +27 -0
- package/dist/scripts/ai_council/transport_resolver.js +9 -10
- package/dist/scripts/condense.js +25 -29
- package/dist/scripts/lint_svg_asset.js +324 -0
- package/dist/server/io/substituteTemplate.js +2 -2
- package/dist/server/io/yamlIO.js +2 -2
- package/dist/server/routes/install.js +5 -1
- package/dist/server/routes/settings.js +2 -2
- package/dist/server/routes/wizard.js +1 -1
- package/dist/server/schemas/settings.js +22 -16
- package/dist/server/serverInfo.js +1 -1
- package/dist/shared/brandTokenDocument.js +47 -0
- package/dist/shared/brandTokenPaths.js +43 -0
- package/dist/shared/settingsCarveOut.js +0 -7
- package/dist/shared/skillRanking.js +103 -5
- package/dist/shared/userMd/formAdapter.js +16 -0
- package/dist/shared/userMd/schema.js +17 -0
- package/dist/ui/assets/index-w70Ado09.js +23 -0
- package/dist/ui/index.html +1 -1
- package/docs/MIGRATION.md +89 -2
- package/docs/THIRD-PARTY-NOTICES.md +27 -0
- package/docs/contracts/settings-classes.md +27 -9
- package/docs/guidelines/agent-infra/api-cost-levers.md +4 -3
- package/docs/guidelines/agent-infra/model-recommendation.md +11 -5
- package/docs/guidelines/agent-infra/rule-body-migration-inventory.md +1 -1
- package/docs/guidelines/agent-infra/self-improvement-pipeline.md +47 -24
- package/docs/guidelines/design-antipatterns.md +6 -1
- package/docs/guidelines/design-asset-discipline.md +17 -0
- package/docs/guidelines/design-fidelity-routing.md +1 -0
- package/docs/guidelines/php/api-design.md +10 -1
- package/llms.txt +12 -10
- package/package.json +15 -5
- package/src/agent-src/scripts/dashboard_mode.ts +4 -1
- package/src/agent-src/scripts/roadmap_age.ts +175 -0
- package/src/agent-src/scripts/update_roadmap_progress.ts +10 -2
- package/src/agent-src/templates/AGENTS.md +1 -1
- package/src/agent-src/templates/scripts/check_memory.ts +2 -2
- package/src/agent-src/templates/scripts/historical-bug-patterns.example.yml +13 -1
- package/src/agent-src/templates/scripts/work_engine/cli.ts +17 -0
- package/src/agent-src/templates/scripts/work_engine/cli_args.ts +10 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui/scaffold.ts +22 -13
- package/src/agent-src/templates/scripts/work_engine/dispatcher.ts +18 -4
- package/src/agent-src/templates/scripts/work_engine/procedure/checks.ts +283 -0
- package/src/agent-src/templates/scripts/work_engine/procedure/run.ts +432 -0
- package/src/agent-src/templates/scripts/work_engine/procedure/sidecar.ts +185 -0
- package/src/agent-src/templates/scripts/work_engine/state.ts +3 -0
- package/src/config/agent-settings.template.yml +120 -57
- package/src/config/agents-paths.yml +13 -7
- package/src/config/ci-local-parity.yml +44 -0
- package/src/config/continuity-surface.json +51 -2
- package/src/config/depth-audit-samples.json +5 -0
- package/src/config/discovery/command-verbs.yml +1 -0
- package/src/config/dispatch-economy-metrics.json +1 -0
- package/src/config/egress-mutations/class-precedence-swapped.json +7 -0
- package/src/config/egress-mutations/credential-token-restores.json +7 -0
- package/src/config/egress-mutations/iban-checksum-disabled.json +7 -0
- package/src/config/egress-mutations/raw-value-in-the-count-record.json +7 -0
- package/src/config/evaluator-budgets.json +4 -4
- package/src/config/gate-coverage.yml +149 -3
- package/src/config/gate-reachability-exemptions.json +3 -5
- package/src/config/gate-violation-baselines.json +29 -25
- package/src/config/gitignore-block.txt +6 -3
- package/src/config/hook-bundle-budget.json +34 -3
- package/src/config/hook-carrier-probes.json +30 -0
- package/src/config/hook-latency-budget.json +4 -2
- package/src/config/host-injection-effect.json +8 -1
- package/src/config/host-skill-frontmatter-keys.json +56 -0
- package/src/config/layer-form-brakes.json +4 -0
- package/src/config/layer-form-comparison-corpus.json +42 -0
- package/src/config/loop-surfaces.yaml +28 -47
- package/src/config/memory-twin-verdicts.yml +9 -1
- package/src/config/metric-registry.yml +40 -3
- package/src/config/pack-size-budget.json +15 -0
- package/src/config/procedure-core-budget.json +21 -0
- package/src/config/profiles/minimal.ini +1 -1
- package/src/config/project-tree-form.json +24 -0
- package/src/config/reach-channels.yml +3 -3
- package/src/config/reach-prescriptions-intake.yml +1 -1
- package/src/config/roadmap-step-size-baseline.json +118 -0
- package/src/config/routing-coverage-seed.json +100 -2
- package/src/config/skill-body-budget.json +686 -0
- package/src/config/skill-fork-pilot.json +17 -0
- package/src/config/skill-lifecycle-probes-codex.json +57 -0
- package/src/config/skill-lifecycle-probes.json +57 -0
- package/src/config/skill-output-shape.json +316 -0
- package/src/config/step-depth-table.json +58 -0
- package/src/config/turnaround-budget.json +90 -0
- package/src/install/conflict.ts +38 -6
- package/src/install/conflictTracker.ts +126 -8
- package/src/install/detect.ts +3 -3
- package/src/install/hostPermissionsAdapter.ts +136 -0
- package/src/install/installThinLayer.ts +6 -1
- package/src/install/manifestFiles.ts +24 -0
- package/src/install/noGoDenyRows.ts +368 -0
- package/src/install/noGoRules.ts +438 -0
- package/src/install/ownershipLedger.ts +180 -0
- package/src/install/plan.ts +1 -1
- package/src/install/preflight.ts +42 -10
- package/src/install/preserve.ts +94 -12
- package/src/install/recordedOwnership.ts +121 -3
- package/src/install/rule_scope.ts +20 -3
- package/src/install/stagedRuntime.ts +528 -0
- package/src/install/toolsArg.ts +16 -0
- package/src/install/types.ts +23 -2
- package/src/install/userPin.ts +54 -0
- package/src/install/wizard-plan.ts +25 -4
- package/src/scripts/_cli/_doctor_emit.ts +24 -0
- package/src/scripts/_cli/cmd_brand_status.ts +223 -12
- package/src/scripts/_cli/cmd_ci_settle.ts +32 -0
- package/src/scripts/_cli/cmd_doctor.ts +23 -44
- package/src/scripts/_cli/cmd_route_explain.ts +176 -2
- package/src/scripts/_cli/cmd_uninstall.ts +270 -26
- package/src/scripts/_cli/cmd_update.ts +34 -1
- package/src/scripts/_cli/cmd_upgrade.ts +38 -2
- package/src/scripts/_cli/detection_report.ts +7 -0
- package/src/scripts/_cli/doctor_execution.ts +1 -2
- package/src/scripts/_cli/doctor_install_mode.ts +39 -0
- package/src/scripts/_cli/doctor_network_posture.ts +3 -3
- package/src/scripts/_cli/doctor_ownership_ledger.ts +126 -0
- package/src/scripts/_cli/doctor_update_verdict.ts +104 -0
- package/src/scripts/_cli/explain_last/scrubber.ts +9 -21
- package/src/scripts/_cli/upgrade_unattended.ts +548 -0
- package/src/scripts/_dispatch.bash +42 -9
- package/src/scripts/_lib/activation_ladder.ts +1 -1
- package/src/scripts/_lib/advisory_inventory.ts +405 -0
- package/src/scripts/_lib/advisory_notice.ts +270 -0
- package/src/scripts/_lib/advisory_sources.ts +752 -0
- package/src/scripts/_lib/advisory_verdicts.ts +363 -0
- package/src/scripts/_lib/agent_artifact_location.ts +177 -0
- package/src/scripts/_lib/agent_settings.ts +7 -12
- package/src/scripts/_lib/arrival_record.ts +217 -0
- package/src/scripts/_lib/asset_render_record.ts +247 -0
- package/src/scripts/_lib/billing_grant.ts +4 -2
- package/src/scripts/_lib/brand_voice_slot.ts +258 -0
- package/src/scripts/_lib/canary_status.ts +24 -0
- package/src/scripts/_lib/cc_transcript.ts +276 -0
- package/src/scripts/_lib/changelog_eras.ts +83 -0
- package/src/scripts/_lib/claim_phrases.ts +71 -0
- package/src/scripts/_lib/classify_update.ts +171 -0
- package/src/scripts/_lib/claude_builtin_names.ts +9 -4
- package/src/scripts/_lib/claude_hook_scope.ts +195 -0
- package/src/scripts/_lib/claude_settings_hooks.ts +118 -34
- package/src/scripts/_lib/codex_resident_set.ts +460 -0
- package/src/scripts/_lib/codex_skill_finder.ts +225 -0
- package/src/scripts/_lib/confusables.ts +19 -0
- package/src/scripts/_lib/consumer_impact.ts +199 -0
- package/src/scripts/_lib/content_class.ts +127 -0
- package/src/scripts/_lib/counted_probe.ts +68 -1
- package/src/scripts/_lib/credential_deny_rows.ts +151 -0
- package/src/scripts/_lib/credential_files.ts +367 -0
- package/src/scripts/_lib/delivery_arm_experiment.ts +2 -2
- package/src/scripts/_lib/depth_flip.ts +141 -0
- package/src/scripts/_lib/design_lock.ts +117 -0
- package/src/scripts/_lib/design_sync_ledger.ts +142 -0
- package/src/scripts/_lib/design_sync_plan.ts +177 -0
- package/src/scripts/_lib/design_sync_reconcile.ts +159 -0
- package/src/scripts/_lib/design_sync_verify.ts +99 -0
- package/src/scripts/_lib/design_system_claude_design.ts +323 -0
- package/src/scripts/_lib/design_system_import.ts +84 -6
- package/src/scripts/_lib/dispatch_import_closure.ts +42 -11
- package/src/scripts/_lib/egress_credential_env.ts +35 -0
- package/src/scripts/_lib/egress_engine.ts +22 -0
- package/src/scripts/_lib/egress_known_values.ts +223 -0
- package/src/scripts/_lib/egress_normalize.ts +67 -0
- package/src/scripts/_lib/egress_prefixes.ts +42 -0
- package/src/scripts/_lib/egress_rules.ts +896 -0
- package/src/scripts/_lib/egress_rules_linearity.ts +56 -0
- package/src/scripts/_lib/egress_sender_scan.ts +290 -0
- package/src/scripts/_lib/egress_session_table.ts +510 -0
- package/src/scripts/_lib/egress_text.ts +63 -0
- package/src/scripts/_lib/egress_token.ts +252 -0
- package/src/scripts/_lib/empty_cycles.ts +1 -1
- package/src/scripts/_lib/environment_detector.ts +45 -30
- package/src/scripts/_lib/exemption_shape.ts +75 -1
- package/src/scripts/_lib/floor_posture.ts +185 -0
- package/src/scripts/_lib/forge_protection.ts +140 -2
- package/src/scripts/_lib/global_deploy_inventory.ts +159 -6
- package/src/scripts/_lib/guidelines_lane.ts +12 -1
- package/src/scripts/_lib/hand_kinds.ts +65 -0
- package/src/scripts/_lib/headless_invocation.ts +3 -3
- package/src/scripts/_lib/host_capability.ts +34 -2
- package/src/scripts/_lib/host_env_write.ts +39 -18
- package/src/scripts/_lib/host_listing_model.ts +14 -7
- package/src/scripts/_lib/identifier_redaction.ts +26 -0
- package/src/scripts/_lib/impact_bump.ts +70 -0
- package/src/scripts/_lib/install_reach_checks.ts +53 -1
- package/src/scripts/_lib/installed_layer.ts +31 -0
- package/src/scripts/_lib/installed_layer_normalise.ts +75 -0
- package/src/scripts/_lib/instructions_loaded_classify.ts +75 -0
- package/src/scripts/_lib/instructions_loaded_event.ts +53 -0
- package/src/scripts/_lib/knowledge_global_redaction.ts +2 -2
- package/src/scripts/_lib/layer_form_corpus.ts +165 -0
- package/src/scripts/_lib/layer_form_decision.ts +248 -0
- package/src/scripts/_lib/layer_form_evidence.ts +112 -0
- package/src/scripts/_lib/lean_projection_mode.ts +32 -161
- package/src/scripts/_lib/llm_proposer_transport.ts +1 -0
- package/src/scripts/_lib/loop_guards.ts +8 -120
- package/src/scripts/_lib/major_surface.ts +207 -0
- package/src/scripts/_lib/mcp_bridge.ts +30 -69
- package/src/scripts/_lib/merge_clearance_record.ts +384 -0
- package/src/scripts/_lib/neighbour_census.ts +18 -1
- package/src/scripts/_lib/orchestration_record.ts +61 -0
- package/src/scripts/_lib/outcome_vocabularies.ts +15 -23
- package/src/scripts/_lib/pin_advice.ts +49 -0
- package/src/scripts/_lib/platform_anchor.ts +222 -0
- package/src/scripts/_lib/procedure_checks.ts +5 -0
- package/src/scripts/_lib/project_tree_form.ts +134 -0
- package/src/scripts/_lib/projection_key_migration.ts +122 -0
- package/src/scripts/_lib/prompt_shape.ts +13 -2
- package/src/scripts/_lib/provenance_verify.ts +272 -0
- package/src/scripts/_lib/quota_parked.ts +27 -1
- package/src/scripts/_lib/ratification_artifact.ts +64 -1
- package/src/scripts/_lib/ratification_subject.ts +508 -46
- package/src/scripts/_lib/release_findings_ingest.ts +52 -5
- package/src/scripts/_lib/release_highlights.ts +72 -2
- package/src/scripts/_lib/release_settings_surface.ts +392 -0
- package/src/scripts/_lib/review_round.ts +134 -0
- package/src/scripts/_lib/roadmap_checkboxes.ts +1 -1
- package/src/scripts/_lib/roadmap_slug_lock.ts +254 -0
- package/src/scripts/_lib/roadmap_step_size.ts +75 -0
- package/src/scripts/_lib/run_checkpoint.ts +60 -3
- package/src/scripts/_lib/runtime_wiring_checks.ts +15 -1
- package/src/scripts/_lib/scope_guard.sh +64 -5
- package/src/scripts/_lib/scoped_projection.ts +136 -3
- package/src/scripts/_lib/secret_detector.ts +24 -103
- package/src/scripts/_lib/security_fix.ts +429 -0
- package/src/scripts/_lib/security_fix_context.ts +133 -0
- package/src/scripts/_lib/self_repair.ts +69 -39
- package/src/scripts/_lib/self_repair_outgoing.ts +209 -0
- package/src/scripts/_lib/self_repair_payload.ts +86 -0
- package/src/scripts/_lib/session_eol.ts +3 -0
- package/src/scripts/_lib/session_pr_watch.ts +207 -0
- package/src/scripts/_lib/session_register.ts +51 -1
- package/src/scripts/_lib/session_tag.ts +51 -0
- package/src/scripts/_lib/settings_removed_keys.ts +30 -0
- package/src/scripts/_lib/settings_renamed_keys.ts +19 -5
- package/src/scripts/_lib/skill_catalogue.ts +66 -25
- package/src/scripts/_lib/skill_fork_pilot.ts +121 -0
- package/src/scripts/_lib/skill_leases.ts +203 -0
- package/src/scripts/_lib/skill_listing_overrides.ts +294 -0
- package/src/scripts/_lib/skill_materialisation.ts +388 -0
- package/src/scripts/_lib/skill_materialisation_gate.ts +210 -0
- package/src/scripts/_lib/skill_materialisation_lock.ts +149 -0
- package/src/scripts/_lib/skill_materialisation_triggers.ts +96 -0
- package/src/scripts/_lib/skill_origin.ts +21 -1
- package/src/scripts/_lib/skill_reach.ts +342 -0
- package/src/scripts/_lib/source_shape.ts +7 -2
- package/src/scripts/_lib/sqlite_guard.ts +1 -1
- package/src/scripts/_lib/step_anatomy.ts +330 -0
- package/src/scripts/_lib/subagent_capsule.ts +8 -2
- package/src/scripts/_lib/subagent_native_fields.ts +30 -0
- package/src/scripts/_lib/subagent_spawn.ts +36 -0
- package/src/scripts/_lib/subagent_steering.ts +367 -0
- package/src/scripts/_lib/svg_dom.ts +318 -0
- package/src/scripts/_lib/svg_filled_counter.ts +287 -0
- package/src/scripts/_lib/svg_geometry.ts +480 -0
- package/src/scripts/_lib/svg_motion.ts +208 -0
- package/src/scripts/_lib/svg_rules.ts +1455 -0
- package/src/scripts/_lib/svg_urls.ts +72 -0
- package/src/scripts/_lib/test_delta.ts +89 -6
- package/src/scripts/_lib/tier_downshift_verdict.ts +222 -0
- package/src/scripts/_lib/tool_result_census.ts +62 -0
- package/src/scripts/_lib/trigger_routers.ts +1 -0
- package/src/scripts/_lib/turnaround_throughput.ts +378 -0
- package/src/scripts/_lib/ui_surface.ts +22 -0
- package/src/scripts/_lib/unattended_gates.ts +100 -0
- package/src/scripts/_lib/undeployed_fixes.ts +34 -0
- package/src/scripts/_lib/update_check.ts +143 -12
- package/src/scripts/_lib/update_invite.ts +116 -0
- package/src/scripts/_lib/update_notice.ts +259 -0
- package/src/scripts/_lib/verification_command.ts +59 -0
- package/src/scripts/_lib/verify_clause.ts +31 -19
- package/src/scripts/_lib/version_order.ts +146 -0
- package/src/scripts/_lib/worker_reuse.ts +191 -0
- package/src/scripts/_lib/workspace_secrets.ts +273 -0
- package/src/scripts/_lib/worktree_git.ts +67 -0
- package/src/scripts/_lib/worktree_ignored.ts +116 -0
- package/src/scripts/adoption_status.ts +330 -3
- package/src/scripts/adr_cite_check.ts +93 -0
- package/src/scripts/advisories.ts +803 -0
- package/src/scripts/ai-image/adapters/flux.sh +1 -0
- package/src/scripts/ai-image/adapters/gemini-image.sh +1 -0
- package/src/scripts/ai-image/adapters/ideogram.sh +1 -0
- package/src/scripts/ai-image/adapters/recraft.sh +1 -0
- package/src/scripts/ai-video/adapters/comfyui.sh +1 -0
- package/src/scripts/ai-video/adapters/fal.sh +1 -0
- package/src/scripts/ai-video/adapters/gemini-veo.sh +1 -0
- package/src/scripts/ai-video/adapters/higgsfield.sh +1 -0
- package/src/scripts/ai-video/adapters/kling.sh +1 -0
- package/src/scripts/ai-video/adapters/musetalk.sh +1 -0
- package/src/scripts/ai-video/adapters/openai-images.sh +1 -0
- package/src/scripts/ai-video/adapters/replicate.sh +1 -0
- package/src/scripts/ai-video/adapters/sora.sh +1 -0
- package/src/scripts/ai-video/adapters/syncso.sh +1 -0
- package/src/scripts/ai-video/stitch.sh +115 -2
- package/src/scripts/ai_council/airgap.ts +1 -0
- package/src/scripts/ai_council/api_transport.ts +27 -4
- package/src/scripts/ai_council/budget_guard.ts +300 -11
- package/src/scripts/ai_council/bundler.ts +20 -29
- package/src/scripts/ai_council/chairman.ts +17 -2
- package/src/scripts/ai_council/cli_agency_bounds.ts +158 -0
- package/src/scripts/ai_council/cli_launch_env.ts +54 -0
- package/src/scripts/ai_council/cli_least_agency_canary.ts +18 -2
- package/src/scripts/ai_council/clients.ts +55 -73
- package/src/scripts/ai_council/config.ts +16 -22
- package/src/scripts/ai_council/council_egress.ts +167 -0
- package/src/scripts/ai_council/exposure_ledger.ts +117 -0
- package/src/scripts/ai_council/free_hand_shadow.ts +276 -0
- package/src/scripts/ai_council/free_route.ts +216 -0
- package/src/scripts/ai_council/free_route_catalog.ts +173 -0
- package/src/scripts/ai_council/free_route_client.ts +95 -0
- package/src/scripts/ai_council/free_rung.ts +61 -0
- package/src/scripts/ai_council/hand_payload.ts +230 -0
- package/src/scripts/ai_council/hand_schemas.ts +123 -0
- package/src/scripts/ai_council/jury_aggregate.ts +155 -1
- package/src/scripts/ai_council/kind_flip.ts +221 -0
- package/src/scripts/ai_council/kind_flip_state.ts +19 -0
- package/src/scripts/ai_council/learn_low_impact_preview.ts +50 -22
- package/src/scripts/ai_council/modification_review.ts +98 -5
- package/src/scripts/ai_council/necessity.ts +7 -0
- package/src/scripts/ai_council/orchestrator.ts +16 -16
- package/src/scripts/ai_council/pricing.ts +10 -0
- package/src/scripts/ai_council/redact_low_impact_entry.ts +5 -2
- package/src/scripts/ai_council/response_render.ts +27 -4
- package/src/scripts/ai_council/round_reservations.ts +119 -0
- package/src/scripts/ai_council/route_chooser.ts +161 -0
- package/src/scripts/ai_council/route_liveness.ts +152 -0
- package/src/scripts/ai_council/route_member.ts +52 -0
- package/src/scripts/ai_council/seat_policy.ts +40 -0
- package/src/scripts/ai_council/seat_resume.ts +40 -0
- package/src/scripts/ai_council/shadow_dispatch.ts +13 -3
- package/src/scripts/ai_council/spend_gate.ts +18 -2
- package/src/scripts/ai_council/status_surface.ts +37 -0
- package/src/scripts/ai_council/transport_resolver.ts +15 -18
- package/src/scripts/analysis_analysts.ts +226 -0
- package/src/scripts/analysis_anchors.ts +140 -0
- package/src/scripts/analysis_and_optimize.ts +44 -0
- package/src/scripts/analysis_emit.ts +150 -0
- package/src/scripts/analysis_exchange.ts +186 -0
- package/src/scripts/analysis_gate.ts +158 -0
- package/src/scripts/analysis_inbox_final.ts +173 -0
- package/src/scripts/analysis_ledger.ts +119 -0
- package/src/scripts/analysis_pr_optimize.ts +219 -0
- package/src/scripts/analysis_pr_review.ts +240 -0
- package/src/scripts/analysis_pr_target.ts +121 -0
- package/src/scripts/analysis_prompts.ts +130 -0
- package/src/scripts/analysis_publish.ts +358 -0
- package/src/scripts/analysis_questions.ts +78 -0
- package/src/scripts/analysis_run.ts +248 -0
- package/src/scripts/analysis_run_record.ts +210 -0
- package/src/scripts/analysis_target.ts +343 -0
- package/src/scripts/analysis_validate.ts +161 -0
- package/src/scripts/anchor_eval_falsify.ts +1 -1
- package/src/scripts/arrival_report.ts +115 -0
- package/src/scripts/ask_transport.ts +284 -35
- package/src/scripts/backfill_model_tier.ts +4 -5
- package/src/scripts/before_complete_hook.ts +48 -2
- package/src/scripts/bench_hook_latency.ts +3 -3
- package/src/scripts/bench_procedure_cursor.ts +440 -0
- package/src/scripts/bootstrap.sh +3 -3
- package/src/scripts/build_exit_code_register.ts +440 -0
- package/src/scripts/build_proof.ts +23 -1
- package/src/scripts/cache_realization_report.ts +155 -14
- package/src/scripts/canary_liveness.ts +117 -0
- package/src/scripts/chat_history.ts +12 -15
- package/src/scripts/check_account_surface.ts +318 -0
- package/src/scripts/check_agent_artifact_location.ts +17 -160
- package/src/scripts/check_bundle_path_leakage.ts +6 -0
- package/src/scripts/check_ci_local_parity.ts +21 -13
- package/src/scripts/check_claims.ts +77 -2
- package/src/scripts/check_completion_review.ts +34 -1
- package/src/scripts/check_concern_admissions.ts +41 -5
- package/src/scripts/check_consumer_scope_flip.ts +1 -1
- package/src/scripts/check_context_paths.ts +2 -0
- package/src/scripts/check_council_layout.ts +9 -0
- package/src/scripts/check_credential_spelling.ts +267 -0
- package/src/scripts/check_egress_mutations.ts +239 -0
- package/src/scripts/check_enforcement_coverage.ts +16 -3
- package/src/scripts/check_estate_count.ts +16 -1
- package/src/scripts/check_finding_dispositions.ts +147 -0
- package/src/scripts/check_gate_coverage.ts +123 -21
- package/src/scripts/check_gate_reachability.ts +16 -2
- package/src/scripts/check_generator_sync.ts +46 -0
- package/src/scripts/check_hook_bundle_composition.ts +139 -1
- package/src/scripts/check_host_docs_digest.ts +142 -5
- package/src/scripts/check_kernel_edit_ratified.ts +301 -76
- package/src/scripts/check_kernel_rule_bundle.ts +14 -10
- package/src/scripts/check_knowledge_cards.ts +83 -3
- package/src/scripts/check_memory.ts +13 -3
- package/src/scripts/check_pack_size.ts +1 -1
- package/src/scripts/check_permission_deny_syntax.ts +247 -0
- package/src/scripts/check_platform_anchor.ts +243 -0
- package/src/scripts/check_proposal.ts +183 -1
- package/src/scripts/check_reach_channels.ts +5 -3
- package/src/scripts/check_references.ts +5 -2
- package/src/scripts/check_release_manifest_content.ts +33 -0
- package/src/scripts/check_release_pr_shape.ts +5 -0
- package/src/scripts/check_rule_invariants.ts +9 -1
- package/src/scripts/check_skill_body_budget.ts +343 -0
- package/src/scripts/check_skill_requires.ts +137 -1
- package/src/scripts/check_step_receipts.ts +246 -0
- package/src/scripts/check_structural_breaking.ts +7 -1
- package/src/scripts/check_suppression_hygiene.ts +8 -0
- package/src/scripts/check_test_weakening.ts +14 -0
- package/src/scripts/check_token_quality_golden.ts +5 -1
- package/src/scripts/check_update_banner.ts +50 -3
- package/src/scripts/check_verify_expectation_delta.ts +2 -1
- package/src/scripts/check_voice_lexicon.ts +531 -0
- package/src/scripts/ci_os_attribution.ts +327 -0
- package/src/scripts/ci_platform_scope.ts +69 -0
- package/src/scripts/ci_settle.ts +4 -1
- package/src/scripts/ci_status.ts +0 -1
- package/src/scripts/ci_time_to_green.ts +748 -0
- package/src/scripts/classify_merge_risk.ts +407 -19
- package/src/scripts/code_graph/sqlite_store.ts +1 -1
- package/src/scripts/compile_trigger_evals.ts +353 -0
- package/src/scripts/condense.ts +25 -31
- package/src/scripts/consumer_matrix.ts +61 -3
- package/src/scripts/council_availability_hook.ts +12 -4
- package/src/scripts/council_cli.ts +48 -38
- package/src/scripts/cross_repo_retrieve.ts +9 -72
- package/src/scripts/design_lock.ts +106 -0
- package/src/scripts/design_slop_rules.ts +30 -0
- package/src/scripts/design_sync.ts +264 -0
- package/src/scripts/design_system_import.ts +30 -13
- package/src/scripts/dispatch_economy_report.ts +46 -1
- package/src/scripts/dispatch_r2_reviewer.ts +41 -5
- package/src/scripts/egress_canary.ts +166 -0
- package/src/scripts/egress_sender_census.ts +101 -0
- package/src/scripts/external_sources_denylist.json +94 -12
- package/src/scripts/generate_catalog.ts +6 -2
- package/src/scripts/generate_owned_digest.ts +163 -0
- package/src/scripts/generate_reference_toc.ts +143 -0
- package/src/scripts/generate_subagent_floor.ts +11 -1
- package/src/scripts/handoff_context_hook.ts +34 -0
- package/src/scripts/hook_carrier_census.ts +263 -0
- package/src/scripts/hook_chunks.d.mts +12 -0
- package/src/scripts/hook_chunks.mjs +114 -0
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +65 -42
- package/src/scripts/hooks/block_config_weakening.ts +127 -3
- package/src/scripts/hooks/block_credential_reads.ts +165 -0
- package/src/scripts/hooks/block_no_verify.ts +47 -23
- package/src/scripts/hooks/block_speaking_inbox_dir.ts +54 -8
- package/src/scripts/hooks/category_a.ts +202 -25
- package/src/scripts/hooks/concern_failure_policy.ts +6 -6
- package/src/scripts/hooks/concern_registry.ts +31 -6
- package/src/scripts/hooks/concern_registry_types.ts +11 -0
- package/src/scripts/hooks/delegation_nudge_hook.ts +105 -15
- package/src/scripts/hooks/design_pass_hook.ts +199 -13
- package/src/scripts/hooks/dispatch_hook.ts +13 -12
- package/src/scripts/hooks/egress_engine_loader.ts +125 -0
- package/src/scripts/hooks/egress_stage.ts +440 -0
- package/src/scripts/hooks/hook_stdin.ts +29 -4
- package/src/scripts/hooks/host_docs_pages.ts +194 -0
- package/src/scripts/hooks/host_docs_pages.yaml +75 -0
- package/src/scripts/hooks/host_lowering.json +1 -1
- package/src/scripts/hooks/host_lowering.yaml +22 -21
- package/src/scripts/hooks/host_rate_marker_hook.ts +73 -0
- package/src/scripts/hooks/instructions_observer_hook.ts +170 -0
- package/src/scripts/hooks/interruption_ledger_hook.ts +1 -1
- package/src/scripts/hooks/lazy_concern.ts +148 -0
- package/src/scripts/hooks/orchestration_record_hook.ts +80 -2
- package/src/scripts/hooks/payload_stub.ts +16 -6
- package/src/scripts/hooks/permission_gate.ts +7 -7
- package/src/scripts/hooks/push_settle_hook.ts +32 -3
- package/src/scripts/hooks/replay_hook.ts +43 -0
- package/src/scripts/hooks/reread_guard_hook.ts +87 -10
- package/src/scripts/hooks/rtk_wrap_hook.ts +4 -3
- package/src/scripts/hooks/rule_inject_hook.ts +8 -1
- package/src/scripts/hooks/session_eol_hook.ts +48 -1
- package/src/scripts/hooks/source_first_gate_hook.ts +6 -8
- package/src/scripts/hooks/spawn_guard_shadow_hook.ts +203 -10
- package/src/scripts/hooks/state_io.ts +2 -2
- package/src/scripts/hooks/svg_obligation.ts +553 -0
- package/src/scripts/hooks/svg_rules_loader.ts +133 -0
- package/src/scripts/hooks/tool_result_bytes_hook.ts +14 -5
- package/src/scripts/hooks/turn_end_gate_hook.ts +5 -3
- package/src/scripts/hooks/ui_route_nudge_hook.ts +2 -12
- package/src/scripts/hooks_doctor.ts +31 -0
- package/src/scripts/hooks_status.ts +58 -3
- package/src/scripts/inbox_source_census.ts +74 -13
- package/src/scripts/install +25 -3
- package/src/scripts/install.ts +60 -91
- package/src/scripts/interruption_report.ts +11 -1
- package/src/scripts/layer_baseline_report.ts +267 -0
- package/src/scripts/learning_sidecar.ts +1 -1
- package/src/scripts/lint_agents_layout.ts +3 -0
- package/src/scripts/lint_blocker_citations.ts +104 -0
- package/src/scripts/lint_breaking_changes_index.ts +40 -7
- package/src/scripts/lint_consolidation_lineage.ts +150 -19
- package/src/scripts/lint_consumer_internal_refs.ts +90 -42
- package/src/scripts/lint_context_spine_usage.ts +21 -0
- package/src/scripts/lint_design_antipattern_parity.ts +39 -7
- package/src/scripts/lint_design_quality.ts +60 -12
- package/src/scripts/lint_evidence_artifacts.ts +31 -0
- package/src/scripts/lint_example_fences.ts +11 -2
- package/src/scripts/lint_ghostwriter_source.ts +42 -10
- package/src/scripts/lint_hook_manifest.ts +94 -0
- package/src/scripts/lint_marketplace_install_completeness.ts +4 -0
- package/src/scripts/lint_mcp_config_security.ts +9 -11
- package/src/scripts/lint_motion_authority_drift.ts +27 -0
- package/src/scripts/lint_plan_risk_register.ts +28 -1
- package/src/scripts/lint_positioning.ts +4 -4
- package/src/scripts/lint_provenance.ts +1 -0
- package/src/scripts/lint_roadmap_blockers.ts +65 -4
- package/src/scripts/lint_roadmap_complexity.ts +98 -0
- package/src/scripts/lint_skill_link_reach.ts +251 -9
- package/src/scripts/lint_skill_procedures.ts +252 -0
- package/src/scripts/lint_skill_scripts_readonly.ts +12 -1
- package/src/scripts/lint_subagent_determinism.ts +14 -1
- package/src/scripts/lint_svg_asset.ts +365 -0
- package/src/scripts/lint_ticked_unmet_criteria.ts +300 -21
- package/src/scripts/mcp_registry_submit.sh +2 -2
- package/src/scripts/mcp_server/consumer_tool_catalog.json +4 -4
- package/src/scripts/mcp_server/suggest_skill.ts +89 -4
- package/src/scripts/mcp_server/tools.ts +2 -33
- package/src/scripts/measure_skill_ranker_baseline.ts +203 -5
- package/src/scripts/measure_turn_end_gate.ts +61 -1
- package/src/scripts/merge_clearance.ts +225 -0
- package/src/scripts/migrate_command_suggestions.ts +1 -1
- package/src/scripts/network_sources.ts +236 -0
- package/src/scripts/no_go_deny_rows.ts +225 -0
- package/src/scripts/orchestration_record.ts +15 -2
- package/src/scripts/plan_test_shards.ts +103 -0
- package/src/scripts/pr_url_reminder_hook.ts +10 -0
- package/src/scripts/print_required_checks.ts +5 -5
- package/src/scripts/probe_depth_shadow.ts +406 -0
- package/src/scripts/probe_turnaround.ts +342 -10
- package/src/scripts/ratification_subject.ts +176 -0
- package/src/scripts/rdp_gate_classify.ts +1 -0
- package/src/scripts/rdp_quality_eval.ts +1 -0
- package/src/scripts/release.ts +26 -55
- package/src/scripts/release_drill.ts +52 -23
- package/src/scripts/release_env.ts +37 -0
- package/src/scripts/release_publication.ts +11 -1
- package/src/scripts/report_consumer_gate_reach.ts +233 -0
- package/src/scripts/report_merge_gate_load.ts +295 -0
- package/src/scripts/report_project_contract.ts +123 -0
- package/src/scripts/report_reducible_classes.ts +342 -0
- package/src/scripts/report_required_checks_drift.ts +5 -3
- package/src/scripts/report_skill_host_census.ts +199 -0
- package/src/scripts/report_standing_payload_by_host.ts +7 -7
- package/src/scripts/retro.ts +758 -0
- package/src/scripts/retro_facts.ts +575 -0
- package/src/scripts/retro_queue.ts +739 -0
- package/src/scripts/retro_session_facts.ts +218 -0
- package/src/scripts/retro_sweep.ts +493 -0
- package/src/scripts/retro_triage.ts +126 -0
- package/src/scripts/roadmap_context.ts +2 -2
- package/src/scripts/roadmap_drain_queue.ts +601 -0
- package/src/scripts/run_supervise.ts +24 -2
- package/src/scripts/schemas/agent-settings.schema.json +0 -16
- package/src/scripts/schemas/command.schema.json +3 -3
- package/src/scripts/schemas/review-findings.schema.json +8 -0
- package/src/scripts/schemas/skill.schema.json +7 -6
- package/src/scripts/schemas/subagent.schema.json +33 -2
- package/src/scripts/score_skill_selection.ts +5 -2
- package/src/scripts/second_brain_retrieval.ts +1 -0
- package/src/scripts/second_brain_run.ts +1 -0
- package/src/scripts/self_repair_cli.ts +563 -87
- package/src/scripts/self_review_gate.ts +59 -4
- package/src/scripts/session_register_hook.ts +91 -4
- package/src/scripts/sessions_cli.ts +100 -5
- package/src/scripts/skill_collision_clusters.ts +1 -1
- package/src/scripts/skill_tools/score_skill_relevance.ts +31 -2
- package/src/scripts/skill_trigger_eval.ts +4 -2
- package/src/scripts/source_adapters.ts +183 -0
- package/src/scripts/step_receipt.ts +100 -0
- package/src/scripts/sync_pr_branch.ts +4 -0
- package/src/scripts/test_council_qualification.ts +1 -1
- package/src/scripts/trigger_eval_grandfather.json +3 -49
- package/src/scripts/trigger_eval_rotation.ts +31 -3
- package/src/scripts/ui_conformance_probe.ts +405 -1
- package/src/scripts/update_counts.ts +230 -11
- package/src/scripts/update_invite_hook.ts +245 -0
- package/src/scripts/update_notice_hook.ts +298 -0
- package/src/scripts/validate_frontmatter.ts +85 -0
- package/src/scripts/worker_reuse_shadow_report.ts +121 -0
- package/src/scripts/worktree_cleanup_check.ts +915 -121
- package/src/server/io/yamlIO.ts +2 -2
- package/src/server/schemas/settings.ts +37 -23
- package/src/shared/brandTokenDocument.ts +46 -0
- package/src/shared/brandTokenPaths.ts +43 -0
- package/src/shared/settingsCarveOut.ts +0 -8
- package/src/shared/skillRanking.ts +106 -5
- package/src/shared/userMd/formAdapter.ts +15 -1
- package/src/shared/userMd/schema.ts +22 -0
- package/src/templates/agent-user.md +4 -0
- package/src/templates/agent-user.yml +4 -0
- package/dist/cli-delegate/chunk-523HCFYO.js +0 -90
- package/dist/cli-delegate/chunk-AL3RZ22D.js +0 -74
- package/dist/cli-delegate/chunk-KB5FZ655.js +0 -208
- package/dist/cli-delegate/chunk-MDPPKQCQ.js +0 -875
- package/dist/cli-delegate/chunk-MSUL5NYP.js +0 -1123
- package/dist/cli-delegate/chunk-OAFSJBHH.js +0 -272
- package/dist/ui/assets/index-C3djEJah.js +0 -23
- package/src/scripts/_lib/continuation_ladder.ts +0 -335
- package/src/scripts/hooks/run_continuation_hook.ts +0 -1524
|
@@ -1,1524 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* run_continuation — road-to-long-horizon-execution Phase 1 (H-1).
|
|
3
|
-
*
|
|
4
|
-
* The stop slot's first WORK-REMAINING concern. Every other stop concern is a
|
|
5
|
-
* quality or state concern; this one compares the session's contracted scope
|
|
6
|
-
* against roadmap checkbox state and, when contracted work remains, returns
|
|
7
|
-
* the dispatcher's block verdict with a continuation naming the next unchecked
|
|
8
|
-
* step and its `verify:` line. The dispatcher translates a stop-slot block to
|
|
9
|
-
* host exit 2, and the host feeds this concern's stderr back to the agent —
|
|
10
|
-
* that channel IS the re-engagement; no daemon, no second process.
|
|
11
|
-
*
|
|
12
|
-
* SHAPE PROVENANCE, and the three deliberate differences. The allow/deny-plus-
|
|
13
|
-
* continuation shape is claude-flow's `autopilotCheck` (commands/autopilot.ts
|
|
14
|
-
* @ fa13ee4, v3.38.12), verified at source in the roadmap's § 1. AC's version
|
|
15
|
-
* differs by design, not oversight:
|
|
16
|
-
*
|
|
17
|
-
* 1. The progress signal is the claimed roadmap's own checkboxes — the same
|
|
18
|
-
* artefact `roadmap-progress` already watches — never a parallel task
|
|
19
|
-
* file that can drift from the roadmap it mirrors.
|
|
20
|
-
* 2. Quality gates take precedence. Concerns run SEQUENTIALLY in chain
|
|
21
|
-
* order (dispatch_hook.ts § runner); this concern is registered AFTER
|
|
22
|
-
* `turn-end-gate`, and when the gate refused THIS turn (its refusal
|
|
23
|
-
* marker carries the turn ordinal) this concern defers. A turn refused
|
|
24
|
-
* for unverified claims is never re-engaged past the refusal — the
|
|
25
|
-
* upstream's naked "Do not stop until all are complete" is the
|
|
26
|
-
* anti-pattern this branch exists against.
|
|
27
|
-
* 3. Every re-engagement names the next step and its `verify:` line. A
|
|
28
|
-
* continuation that does not say what "continue" means just burns an
|
|
29
|
-
* iteration on re-orientation.
|
|
30
|
-
*
|
|
31
|
-
* CONTRACT GATING — when this concern is a no-op, which is almost always:
|
|
32
|
-
* · no roadmap claim for this session (`sessions:claim` never ran), or
|
|
33
|
-
* · the claimed roadmap's frontmatter `execution.mode` is anything but
|
|
34
|
-
* `autonomous` (absent, `interactive`, `phase-checkpoints` — a
|
|
35
|
-
* checkpointed run WANTS its phase-boundary conversation), or
|
|
36
|
-
* · replay mode, or the kill switch `AGENT_CONFIG_NO_RUN_CONTINUATION=1`.
|
|
37
|
-
* The claim file plus the mode field is the run contract this file consumes;
|
|
38
|
-
* it invents no second contract carrier.
|
|
39
|
-
*
|
|
40
|
-
* TERMINATION LADDER (Phase 1.1) — every rung a named event in
|
|
41
|
-
* `agents/runtime/state/run-continuation.jsonl`:
|
|
42
|
-
* contract absent → no-op (no event; the common case is silent)
|
|
43
|
-
* roadmap unreadable from the
|
|
44
|
-
* authoritative tree → allow (event: halt-roadmap-absent, ONCE PER
|
|
45
|
-
* ABSENCE EPISODE with a readable state and ONCE PER
|
|
46
|
-
* RUN without one — the two guards have different
|
|
47
|
-
* carriers: `absent_fires` resets on a successful
|
|
48
|
-
* read, the ledger guard cannot forget. So a second
|
|
49
|
-
* episode on an unparseable state is SILENT,
|
|
50
|
-
* only for a run this concern had already engaged
|
|
51
|
-
* on THIS roadmap — the keyed state is the
|
|
52
|
-
* discriminator. State absent stays silent,
|
|
53
|
-
* because nothing was ever driven. The budget is
|
|
54
|
-
* reclaimed only after `ABSENT_CONFIRM_FIRES`
|
|
55
|
-
* consecutive absent fires: one fire cannot tell
|
|
56
|
-
* an archival from a non-atomic rewrite, two can.
|
|
57
|
-
* Deliberately NOT in `HALT_ACTIONS` — it clears
|
|
58
|
-
* the budget rather than stamping `halted`, and
|
|
59
|
-
* the two are exclusive)
|
|
60
|
-
* transcript over the shared
|
|
61
|
-
* read cap → allow (event: inert-transcript-over-cap, ONCE
|
|
62
|
-
* per run. The concern cannot compute a turn
|
|
63
|
-
* ordinal past the cap, so it goes inert — and an
|
|
64
|
-
* inert mechanism that says nothing is
|
|
65
|
-
* indistinguishable from a healthy idle run,
|
|
66
|
-
* which is the failure this file exists over)
|
|
67
|
-
* plan premise moved → allow (event: halt-premise-invalidated, ONCE per
|
|
68
|
-
* run. Engaged-under fingerprint and newest
|
|
69
|
-
* observation both known and differing. Before the
|
|
70
|
-
* counter rungs: iterating against a stale plan
|
|
71
|
-
* does not make it current, and capping out would
|
|
72
|
-
* report `exhausted`, a budget word, for staleness.
|
|
73
|
-
* Never fires on traffic the run did not observe)
|
|
74
|
-
* quality-gate refusal → defer (event: deferred-quality-gate)
|
|
75
|
-
* duplicate stop fire → repeat the BLOCK, no count (event: none —
|
|
76
|
-
* an allow here would END the reply the block
|
|
77
|
-
* one event earlier exists to continue). A fire
|
|
78
|
-
* whose roadmap SOURCE changed is never a
|
|
79
|
-
* duplicate, whatever the counts say.
|
|
80
|
-
* scope complete (0 open,
|
|
81
|
-
* none blocked) → allow (event: complete; state cleared)
|
|
82
|
-
* remaining work externally
|
|
83
|
-
* impossible (0 open, ≥1
|
|
84
|
-
* blocked) → allow (event: blocked, ONCE per run, guarded by
|
|
85
|
-
* the LEDGER: the state is cleared like `complete`,
|
|
86
|
-
* so no field there outlives the event. A terminal
|
|
87
|
-
* outcome — not a sixth halt, never in
|
|
88
|
-
* `HALT_ACTIONS`, never stamped into `halted`.
|
|
89
|
-
* ADR-237 narrows what may legally wear a
|
|
90
|
-
* `blocked-by:` marker; semantics unchanged.)
|
|
91
|
-
* iterations ≥ MAX (25) → allow (event: halt-max-iterations)
|
|
92
|
-
* wall clock ≥ cap (4 h) → allow (event: halt-wall-clock)
|
|
93
|
-
* stall (3 engagements, no
|
|
94
|
-
* checkbox delta) → allow (event: halt-stall)
|
|
95
|
-
* otherwise → BLOCK + continue (event: engage)
|
|
96
|
-
*
|
|
97
|
-
* Every event this concern writes carries `workspace_root`, `session_root`,
|
|
98
|
-
* `session_cwd`, `git_dir`, `git_common_dir` and `claim_path` — the two-tree
|
|
99
|
-
* provenance, per `provenance()` below — plus `roadmap_path`, the file the
|
|
100
|
-
* open-step count on that same line was read from (round 4 finding 4). Seven
|
|
101
|
-
* fields. The count has been caught wrong in three separate rounds; if you add
|
|
102
|
-
* one, this line, `provenance()`s heading and the roadmap enumeration all move. Without them the ledger records that an
|
|
103
|
-
* engagement happened but not that it crossed the tree boundary the fix was
|
|
104
|
-
* about, and crossing it is the whole claim. This list is the file's canonical
|
|
105
|
-
* statement of the contract: R2 round 2 finding 4 caught it enumerating four
|
|
106
|
-
* fields while the function emitted five, which would have let a later edit drop
|
|
107
|
-
* one without contradicting any documented promise.
|
|
108
|
-
*
|
|
109
|
-
* Stall counts CONSECUTIVE ENGAGEMENTS whose open-step count did not move.
|
|
110
|
-
* The upstream stalls on 5-of-5 completed-count readings; AC's checkbox
|
|
111
|
-
* signal is finer-grained (a step in progress usually flips SOMETHING), so
|
|
112
|
-
* the default is tighter at 3 — pre-registered for revisit against Phase 4
|
|
113
|
-
* data in the roadmap, not tuned here.
|
|
114
|
-
*
|
|
115
|
-
* `[~]` (deferred) and `[-]` (cancelled) boxes are not open work — the
|
|
116
|
-
* vocabulary is `update_roadmap_progress.ts`'s. A step carrying a
|
|
117
|
-
* `blocked-by:` marker is open work this RUN cannot do, so it neither counts
|
|
118
|
-
* toward the open total nor gets named as the next step: re-engaging an
|
|
119
|
-
* agent into a step the roadmap itself declares blocked is a guaranteed
|
|
120
|
-
* stall, manufactured by the mechanism whose job is to detect one.
|
|
121
|
-
*
|
|
122
|
-
* FAIL-OPEN THROUGHOUT. severity: BLOCKING, fail_closed: false. Any read
|
|
123
|
-
* error, any malformed state, any surprise → EXIT_ALLOW. A continuation
|
|
124
|
-
* mechanism must never be the thing that blocks a stop for a reason nobody
|
|
125
|
-
* can see; the only BLOCK this file emits is the one that carries its own
|
|
126
|
-
* explanation on stderr.
|
|
127
|
-
*
|
|
128
|
-
* The severity word matters and this docblock had the wrong one. It read
|
|
129
|
-
* `advisory` — which the dispatcher enforces as a CEILING, downgrading any
|
|
130
|
-
* EXIT_BLOCK to WARN, so the whole mechanism was inert. That was round 1's
|
|
131
|
-
* critical finding; the manifest moved and this line did not, which round 3
|
|
132
|
-
* then caught as a doc contradicting the declaration it describes. Blocking
|
|
133
|
-
* and fail-open are not in tension: fail-open governs what happens when this
|
|
134
|
-
* file cannot decide, blocking governs what happens when it decides to
|
|
135
|
-
* continue.
|
|
136
|
-
*/
|
|
137
|
-
|
|
138
|
-
import * as fs from 'node:fs';
|
|
139
|
-
import { revokeBillingGrant } from '../_lib/billing_grant.js';
|
|
140
|
-
import * as path from 'node:path';
|
|
141
|
-
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
142
|
-
|
|
143
|
-
import { unwrap, type JsonObject, type JsonValue } from './envelope.js';
|
|
144
|
-
import { readHookStdin } from './hook_stdin.js';
|
|
145
|
-
import { is_replay_mode } from './state_io.js';
|
|
146
|
-
import { readTranscriptTail } from './turn_end_gate_hook.js';
|
|
147
|
-
import { resolve_claim, session_checkout } from '../session_register_hook.js';
|
|
148
|
-
import { git_common_dir, git_dir } from '../_lib/git_common_dir.js';
|
|
149
|
-
import {
|
|
150
|
-
deriveSessionKey,
|
|
151
|
-
parseRecord,
|
|
152
|
-
sessionRefusalFile,
|
|
153
|
-
} from '../_lib/turn_end_refusals.js';
|
|
154
|
-
import { phaseLines } from '../_lib/roadmap_checkboxes.js';
|
|
155
|
-
import { commandBearing, renderVerifyLine, type VerifyClause } from '../_lib/verify_clause.js';
|
|
156
|
-
|
|
157
|
-
/** Dispatcher-internal block code; the dispatcher maps stop-slot 1 → host 2. */
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* The gate's cap, IMPORTED rather than restated — the two must agree by
|
|
161
|
-
* construction, not by two numbers that happened to match.
|
|
162
|
-
*
|
|
163
|
-
* R2 round 2, finding 1, and it was critical. This file carried its own 2 MB
|
|
164
|
-
* ("same cap the interruption ledger reads its tail under") while
|
|
165
|
-
* `turn_end_gate_hook` uses 8 MB, and `readTranscriptTail` returns
|
|
166
|
-
* `turnOrdinal: 0` over its cap WITHOUT throwing. So on any 2-8 MB transcript
|
|
167
|
-
* the gate computed ordinal N and wrote `refused_turn: N`, this concern
|
|
168
|
-
* computed 0, `refusedThisTurn` compared `N === 0`, the defer was skipped, and
|
|
169
|
-
* the concern BLOCKED a stop the quality gate had just refused — silently, and
|
|
170
|
-
* in exactly the long-running regime this roadmap targets. That is Risk 1 of
|
|
171
|
-
* the register ("quality gates outrank continuation, always") inverted.
|
|
172
|
-
*
|
|
173
|
-
* Sharing the constant is the fix; a matching literal would re-introduce the
|
|
174
|
-
* same defect the next time one side is tuned.
|
|
175
|
-
*/
|
|
176
|
-
import { TRANSCRIPT_READ_MAX_BYTES } from './turn_end_gate_hook.js';
|
|
177
|
-
import {
|
|
178
|
-
atomicWriteJson,
|
|
179
|
-
readUnavailableDependency,
|
|
180
|
-
stallSignal,
|
|
181
|
-
type StallLevel,
|
|
182
|
-
} from '../_lib/loop_guards.js';
|
|
183
|
-
import { premiseMoved, readContextObservation } from '../_lib/context_observation.js';
|
|
184
|
-
import { RUN_TERMINAL_VOCABULARY_VERSION } from '../_lib/outcome_vocabularies.js';
|
|
185
|
-
import {
|
|
186
|
-
HALT_ACTIONS,
|
|
187
|
-
buildLedgerEvent, parseDeliveryState, type DeliveryState,
|
|
188
|
-
ladder,
|
|
189
|
-
MAX_ITERATIONS,
|
|
190
|
-
parseHaltStamp,
|
|
191
|
-
STALL_WINDOW,
|
|
192
|
-
terminalStateFor,
|
|
193
|
-
WALL_CLOCK_CAP_MS,
|
|
194
|
-
type LadderAction,
|
|
195
|
-
} from '../_lib/continuation_ladder.js';
|
|
196
|
-
import { EXIT_ALLOW, EXIT_BLOCK } from './exit_codes.js';
|
|
197
|
-
|
|
198
|
-
/**
|
|
199
|
-
* DECLARED in `_lib/continuation_ladder.ts`, re-exported here: one declaration,
|
|
200
|
-
* two import paths, no second copy to drift. That module's header says why the
|
|
201
|
-
* move happened (`road-to-wired-instruments` Phase 2).
|
|
202
|
-
*/
|
|
203
|
-
export {
|
|
204
|
-
HALT_ACTIONS,
|
|
205
|
-
ladder,
|
|
206
|
-
MAX_ITERATIONS,
|
|
207
|
-
parseHaltStamp,
|
|
208
|
-
STALL_WINDOW,
|
|
209
|
-
terminalStateFor,
|
|
210
|
-
WALL_CLOCK_CAP_MS,
|
|
211
|
-
type LadderAction,
|
|
212
|
-
};
|
|
213
|
-
|
|
214
|
-
/** Re-exported so a test can assert the IDENTITY, not two matching literals. */
|
|
215
|
-
export { TRANSCRIPT_READ_MAX_BYTES };
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
* The blocked-step marker, as § 3c of the process loop documents it. Anchored on
|
|
219
|
-
* the comment form with the id REQUIRED: this decides a terminal outcome and
|
|
220
|
-
* whether a budget is cleared, so prose merely mentioning the words must not
|
|
221
|
-
* remove a step from the open count.
|
|
222
|
-
*/
|
|
223
|
-
const BLOCKED_BY_MARKER = /<!--\s*blocked-by:\s*\S[^>]*-->/;
|
|
224
|
-
|
|
225
|
-
/** Tail bound for `eventAlreadyLogged` — the line it seeks is near the end. */
|
|
226
|
-
const LEDGER_TAIL_MAX_BYTES = 512 * 1024;
|
|
227
|
-
|
|
228
|
-
export const EVENTS_RELPATH = path.join(
|
|
229
|
-
'agents',
|
|
230
|
-
'runtime',
|
|
231
|
-
'state',
|
|
232
|
-
'run-continuation.jsonl',
|
|
233
|
-
);
|
|
234
|
-
const STATE_DIR_REL = path.join('agents', 'runtime', 'state');
|
|
235
|
-
|
|
236
|
-
/**
|
|
237
|
-
* How many consecutive absent-roadmap fires confirm the absence.
|
|
238
|
-
*
|
|
239
|
-
* Two, because that is the smallest number that separates the two causes: a
|
|
240
|
-
* non-atomic rewrite is open for well under one turn, an archival lasts across
|
|
241
|
-
* them. Round 7 findings 1 and 4 measured the cost of treating one fire as
|
|
242
|
-
* confirmation — an unbounded budget reset, repeatable.
|
|
243
|
-
*/
|
|
244
|
-
export const ABSENT_CONFIRM_FIRES = 2;
|
|
245
|
-
|
|
246
|
-
export interface RunState {
|
|
247
|
-
started_at: string;
|
|
248
|
-
iterations: number;
|
|
249
|
-
last_turn: number;
|
|
250
|
-
/** Open-step count recorded at each engagement, newest last. */
|
|
251
|
-
history: number[];
|
|
252
|
-
/**
|
|
253
|
-
* The derived stall level (Phase 6.6): `progressing` | `flat` | `stalled`.
|
|
254
|
-
* Written by the producer so a reader never re-derives it from `history`.
|
|
255
|
-
*/
|
|
256
|
-
stall?: StallLevel;
|
|
257
|
-
/**
|
|
258
|
-
* Set once the over-cap-transcript rung has reported this run inert.
|
|
259
|
-
*
|
|
260
|
-
* The rung fires on every stop for the rest of a long run, and one line saying
|
|
261
|
-
* so is information while a stream of identical lines is noise.
|
|
262
|
-
*/
|
|
263
|
-
inert_reported?: boolean;
|
|
264
|
-
/**
|
|
265
|
-
* CONSECUTIVE stop fires on which the roadmap was unreadable — a run of
|
|
266
|
-
* absences, not a total, which is why the main path deletes it on a successful
|
|
267
|
-
* read. At `ABSENT_CONFIRM_FIRES` the budget is reclaimed; below it the state
|
|
268
|
-
* is left alone. The absent branch says why one fire is not enough.
|
|
269
|
-
*/
|
|
270
|
-
absent_fires?: number;
|
|
271
|
-
/**
|
|
272
|
-
* The roadmap slug this state belongs to.
|
|
273
|
-
*
|
|
274
|
-
* Round 6 finding 2: the state is keyed on the session id alone, and one
|
|
275
|
-
* session may re-claim a different roadmap. A halt stamp is never cleared —
|
|
276
|
-
* only `complete` unlinks — so a later legitimate claim of roadmap B inherited
|
|
277
|
-
* A's stamp, emitted a halt line naming B without ever engaging, and reported
|
|
278
|
-
* A's iteration count under B's slug.
|
|
279
|
-
*
|
|
280
|
-
* Keying the FILE on the slug would have orphaned every state file in
|
|
281
|
-
* existence; recording the slug inside it does the same work and degrades
|
|
282
|
-
* cleanly. A mismatch is read as a fresh run, which is what it is.
|
|
283
|
-
*
|
|
284
|
-
* Optional so a state file written before this field parses unchanged; absent
|
|
285
|
-
* means "unknown roadmap" and is trusted, because the alternative is
|
|
286
|
-
* discarding a live budget on an upgrade.
|
|
287
|
-
*/
|
|
288
|
-
roadmap?: string;
|
|
289
|
-
/**
|
|
290
|
-
* The roadmap file the counts in `history` were read from.
|
|
291
|
-
*
|
|
292
|
-
* Round 4 finding 2: `resolveRoadmap` re-chooses the source tree on every
|
|
293
|
-
* fire, and `ladder`'s stall test compares the counts for equality — so a run
|
|
294
|
-
* whose source changed mid-flight compared numbers from two different
|
|
295
|
-
* documents. Both directions were wrong: a differing earlier count from the
|
|
296
|
-
* other tree reset a genuine stall streak, and a coincidentally equal one
|
|
297
|
-
* contributed a false match toward `halt-stall`. Recording the source lets a
|
|
298
|
-
* change reset the window, which is the only honest reading — the counts
|
|
299
|
-
* before the change measured a different file.
|
|
300
|
-
*
|
|
301
|
-
* Optional so a state file written before this field parses unchanged; absent
|
|
302
|
-
* means "unknown source", which resets once and then tracks.
|
|
303
|
-
*/
|
|
304
|
-
history_source?: string;
|
|
305
|
-
/** ISO stamp of the most recent engagement — half of the duplicate key. */
|
|
306
|
-
last_engaged_at?: string;
|
|
307
|
-
/**
|
|
308
|
-
* Which halt rung ended this run's budget, if one did. Set instead of
|
|
309
|
-
* deleting the state file, and the difference is the whole point: a host
|
|
310
|
-
* may fire `stop` several times for one reply, and a deleted state makes
|
|
311
|
-
* the next fire read `prev === null`, build `iterations: 0` with a fresh
|
|
312
|
-
* `started_at`, and engage again — so the 25-iteration cap bounded a
|
|
313
|
-
* 25-block and the 4 h clock restarted on every halt. The R2 review found
|
|
314
|
-
* this; the roadmap's Risk 2 ("the agent loops forever on a roadmap it
|
|
315
|
-
* cannot finish") named these rungs as its mitigation.
|
|
316
|
-
*/
|
|
317
|
-
halted?: LadderAction;
|
|
318
|
-
/**
|
|
319
|
-
* The fingerprint this run ENGAGED under — its plan premise, recorded once on
|
|
320
|
-
* the first engagement from `_lib/context_observation` and then left alone.
|
|
321
|
-
* Refreshing it every fire would make both sides of the premise comparison
|
|
322
|
-
* equal by construction and the rung unreachable. Absent means the run never
|
|
323
|
-
* observed one, which is never a disagreement (`premiseMoved`).
|
|
324
|
-
*/
|
|
325
|
-
context_fingerprint?: string;
|
|
326
|
-
/** DELIVERY position (8.1), written by the run; absent is no hold. */
|
|
327
|
-
delivery?: DeliveryState;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
/**
|
|
331
|
-
* A host may fire `stop` more than once for one reply (the turn-end gate
|
|
332
|
-
* documents the same quirk). The duplicate key is ordinal + open-count +
|
|
333
|
-
* a short window, because the ordinal ALONE is not a turn identity here:
|
|
334
|
-
* a re-engaged reply often lands in the same user turn, so its ordinal is
|
|
335
|
-
* unchanged even though real work happened — the open count is what moved.
|
|
336
|
-
*/
|
|
337
|
-
export const DUPLICATE_WINDOW_MS = 60 * 1000;
|
|
338
|
-
|
|
339
|
-
export function isDuplicateFire(
|
|
340
|
-
state: RunState | null,
|
|
341
|
-
turnOrdinal: number,
|
|
342
|
-
openCount: number,
|
|
343
|
-
nowMs: number,
|
|
344
|
-
roadmapSource?: string,
|
|
345
|
-
): boolean {
|
|
346
|
-
if (state === null) return false;
|
|
347
|
-
if (state.last_turn !== turnOrdinal) return false;
|
|
348
|
-
// Round 5 finding 6: this compared the recorded count against the fresh scan
|
|
349
|
-
// with no regard for which FILE either came from — the same cross-document
|
|
350
|
-
// comparison `history_source` exists to stop, in the one place that returns
|
|
351
|
-
// BLOCK without consuming an iteration or writing a line. A source change with
|
|
352
|
-
// a coincidentally equal count therefore erased a genuine engagement from the
|
|
353
|
-
// ledger the acceptance criteria are counted from. A changed source is never a
|
|
354
|
-
// duplicate fire.
|
|
355
|
-
// Round 7 finding 6: this read an ABSENT recorded source as a changed one, so
|
|
356
|
-
// the first fire after the upgrade that introduced the field failed to
|
|
357
|
-
// recognise a genuine duplicate — it consumed an iteration and appended an
|
|
358
|
-
// extra `engage` line to the ledger the acceptance criteria count from, which
|
|
359
|
-
// is the false count round 5 finding 6 added the guard to prevent. Both sides
|
|
360
|
-
// must be known before a difference means anything.
|
|
361
|
-
if (
|
|
362
|
-
state.history_source !== undefined &&
|
|
363
|
-
roadmapSource !== undefined &&
|
|
364
|
-
state.history_source !== roadmapSource
|
|
365
|
-
) {
|
|
366
|
-
return false;
|
|
367
|
-
}
|
|
368
|
-
if (state.history.length === 0 || state.history[state.history.length - 1] !== openCount) {
|
|
369
|
-
return false;
|
|
370
|
-
}
|
|
371
|
-
const at = Date.parse(state.last_engaged_at ?? '');
|
|
372
|
-
return Number.isFinite(at) && nowMs - at < DUPLICATE_WINDOW_MS;
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
export interface NextStep {
|
|
376
|
-
/** The step's own line, checkbox stripped, truncated for the message. */
|
|
377
|
-
text: string;
|
|
378
|
-
/** The step's `verify:` clause — command plus optional expectation. */
|
|
379
|
-
verify: VerifyClause | null;
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
export interface ScanResult {
|
|
383
|
-
/** Open (`- [ ]`) steps that are not `blocked-by:`-marked. */
|
|
384
|
-
open: number;
|
|
385
|
-
/** Open steps excluded because their line carries `blocked-by:`. */
|
|
386
|
-
blocked: number;
|
|
387
|
-
next: NextStep | null;
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
/**
|
|
391
|
-
* Frontmatter `execution.mode`, or null. Line-oriented on purpose: the
|
|
392
|
-
* frontmatter this repo writes is two levels deep at most, and a YAML parser
|
|
393
|
-
* on the Stop path is a dependency this read does not need.
|
|
394
|
-
*/
|
|
395
|
-
export function parseExecutionMode(text: string): string | null {
|
|
396
|
-
if (!text.startsWith('---')) return null;
|
|
397
|
-
const end = text.indexOf('\n---', 3);
|
|
398
|
-
if (end === -1) return null;
|
|
399
|
-
const fm = text.slice(0, end);
|
|
400
|
-
if (!/^execution:\s*$/m.test(fm)) return null;
|
|
401
|
-
const m = fm.match(/^\s+mode:\s*(\S+)\s*$/m);
|
|
402
|
-
return m ? m[1]! : null;
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
/**
|
|
406
|
-
* An OPEN step. The mark set is the dashboard's, narrowed to the one mark that
|
|
407
|
-
* means "not done": `[~]` and `[-]` are parked by a human decision, and `[x]`
|
|
408
|
-
* is finished. The BULLET set is the dashboard's in full, because a `*` bullet
|
|
409
|
-
* is a legitimate authoring shape that used to read as zero open steps.
|
|
410
|
-
*/
|
|
411
|
-
const OPEN_BOX = /^[ \t]*[-*][ \t]+\[ \][ \t]+(.*)$/;
|
|
412
|
-
|
|
413
|
-
/**
|
|
414
|
-
* Count open steps and pick the next one. `[~]` / `[-]` never match the open
|
|
415
|
-
* pattern; a `blocked-by:` marker on the step's own line excludes it from
|
|
416
|
-
* both the count and the pick (see the header for why).
|
|
417
|
-
*/
|
|
418
|
-
export function scanOpenSteps(text: string): ScanResult {
|
|
419
|
-
let open = 0;
|
|
420
|
-
let blocked = 0;
|
|
421
|
-
let next: NextStep | null = null;
|
|
422
|
-
// Phase spans only. A `- [ ]` under `## Acceptance criteria`,
|
|
423
|
-
// `## Blockers` or `## Risk Register` is a criterion, a gate or a risk
|
|
424
|
-
// row — never an executable step, and re-engaging on one is a guaranteed
|
|
425
|
-
// stall. See `_lib/roadmap_checkboxes.ts`.
|
|
426
|
-
const lines = phaseLines(text);
|
|
427
|
-
for (let i = 0; i < lines.length; i++) {
|
|
428
|
-
const line = lines[i] as string;
|
|
429
|
-
const m = OPEN_BOX.exec(line);
|
|
430
|
-
if (!m) continue;
|
|
431
|
-
// A step spans its own line plus the indented continuation lines under
|
|
432
|
-
// it, and the `verify:` command is conventionally written on one of
|
|
433
|
-
// those rather than inline. Gathered up to the next checkbox or
|
|
434
|
-
// heading, so one step never absorbs the next one's verify line.
|
|
435
|
-
const step: string[] = [line];
|
|
436
|
-
for (let j = i + 1; j < lines.length; j++) {
|
|
437
|
-
const cont = lines[j] as string;
|
|
438
|
-
if (cont.trim() === '') break;
|
|
439
|
-
if (/^[ \t]*[-*][ \t]+\[/.test(cont)) break;
|
|
440
|
-
if (/^#{1,6}[ \t]/.test(cont)) break;
|
|
441
|
-
if (!/^[ \t]/.test(cont)) break;
|
|
442
|
-
step.push(cont);
|
|
443
|
-
}
|
|
444
|
-
const full = step.join('\n');
|
|
445
|
-
const body = m[1] as string;
|
|
446
|
-
if (BLOCKED_BY_MARKER.test(body)) {
|
|
447
|
-
blocked += 1;
|
|
448
|
-
continue;
|
|
449
|
-
}
|
|
450
|
-
open += 1;
|
|
451
|
-
if (next === null) {
|
|
452
|
-
next = {
|
|
453
|
-
text: (() => {
|
|
454
|
-
const cleaned = body
|
|
455
|
-
.replace(/<!--.*?-->/g, '')
|
|
456
|
-
.replace(/\s+/g, ' ')
|
|
457
|
-
.trim();
|
|
458
|
-
return cleaned.length > 240 ? `${cleaned.slice(0, 237)}...` : cleaned;
|
|
459
|
-
})(),
|
|
460
|
-
verify: extractVerify(full),
|
|
461
|
-
};
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
return { open, blocked, next };
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
/**
|
|
468
|
-
* The step's `verify:` command, in either form the tree writes.
|
|
469
|
-
*
|
|
470
|
-
* R2 round 2, finding 10. Only the HTML-comment form was matched, and only on
|
|
471
|
-
* the step's OWN line — while 18 roadmaps, including both this branch ships,
|
|
472
|
-
* write the backticked form on a continuation line:
|
|
473
|
-
*
|
|
474
|
-
* - [ ] **1.0** do the thing
|
|
475
|
-
* `verify:` `./scripts-run src/scripts/lint_thing`
|
|
476
|
-
*
|
|
477
|
-
* So the continuation named a next step and omitted the command that proves it
|
|
478
|
-
* — and Risk 7 of the roadmap names exactly that command as its mitigation
|
|
479
|
-
* against a re-engagement that cannot check its own work.
|
|
480
|
-
*
|
|
481
|
-
* The comment form wins when both are present: it is the machine-readable one,
|
|
482
|
-
* and a step carrying both has a human-facing line and a tooling-facing line
|
|
483
|
-
* rather than two commands.
|
|
484
|
-
*
|
|
485
|
-
* The hook's narrowing only — a prose clause is not a command, and the
|
|
486
|
-
* continuation message renders commands. It parses nothing itself: a second
|
|
487
|
-
* copy of the arrow grammar is how this hook and `closure_scan` would drift,
|
|
488
|
-
* and a drifted grammar stops reading expectations without failing anything.
|
|
489
|
-
* `_lib/verify_clause.ts` owns the grammar and the sweep that keeps it single.
|
|
490
|
-
*/
|
|
491
|
-
export function extractVerify(stepText: string): VerifyClause | null {
|
|
492
|
-
return commandBearing(stepText);
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
/**
|
|
496
|
-
* Where a run's state lives: keyed on the session AND the roadmap.
|
|
497
|
-
*
|
|
498
|
-
* ## Round 6 keyed it on the session alone, and round 7 killed that
|
|
499
|
-
*
|
|
500
|
-
* Round 6 finding 2 observed that one session may re-claim, so a halt stamped on
|
|
501
|
-
* roadmap A was inherited by a later claim of roadmap B. It fixed that by
|
|
502
|
-
* recording the slug INSIDE the file and reading a mismatch as a fresh run —
|
|
503
|
-
* declining to key the path on the slug because that "would have orphaned every
|
|
504
|
-
* state file in existence".
|
|
505
|
-
*
|
|
506
|
-
* Round 7 findings 2 and 3 showed the in-file discriminator trades one defect for
|
|
507
|
-
* two. The absent-roadmap branch never applied it, so it reported A's iteration
|
|
508
|
-
* count under B's slug and deleted A's live state; and on the main path, nulling
|
|
509
|
-
* `prev` on a mismatch means the next write OVERWRITES A's halt stamp — so a
|
|
510
|
-
* halted roadmap became re-engageable with a full budget by the detour of
|
|
511
|
-
* claiming something else once. "A halt must NOT clear it" was not durable.
|
|
512
|
-
*
|
|
513
|
-
* One file cannot hold two roadmaps' budgets, which is what both findings say from
|
|
514
|
-
* opposite ends. So the path carries the slug, and the orphaning objection is
|
|
515
|
-
* answered by MIGRATING rather than by avoiding: `readRunState` falls back to the
|
|
516
|
-
* legacy per-session path when the keyed one is absent, and adopts it only when its
|
|
517
|
-
* recorded roadmap is absent or equal. A live budget survives the upgrade; a
|
|
518
|
-
* foreign one is not inherited.
|
|
519
|
-
*/
|
|
520
|
-
export function stateRelPath(runId: string, slug: string): string {
|
|
521
|
-
const safeRun = runId.replace(/[^A-Za-z0-9_-]/g, '_');
|
|
522
|
-
const safeSlug = slug.replace(/[^A-Za-z0-9_-]/g, '_');
|
|
523
|
-
return path.join(STATE_DIR_REL, `run-continuation-${safeRun}-${safeSlug}.json`);
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
/** The pre-round-7 path, read for migration and never written. */
|
|
527
|
-
export function legacyStateRelPath(runId: string): string {
|
|
528
|
-
const safe = runId.replace(/[^A-Za-z0-9_-]/g, '_');
|
|
529
|
-
return path.join(STATE_DIR_REL, `run-continuation-${safe}.json`);
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
/**
|
|
533
|
-
* This run's state, from the keyed path or — once, on migration — from the legacy
|
|
534
|
-
* per-session one.
|
|
535
|
-
*
|
|
536
|
-
* Returns the state and the file it came from, because the caller has to know
|
|
537
|
-
* whether it is looking at a keyed file (safe to delete) or a legacy one shared
|
|
538
|
-
* with other roadmaps (never deleted; the keyed write supersedes it).
|
|
539
|
-
*/
|
|
540
|
-
export function readRunState(
|
|
541
|
-
workspaceRoot: string,
|
|
542
|
-
runId: string,
|
|
543
|
-
slug: string,
|
|
544
|
-
): { state: RunState | null; from: 'keyed' | 'legacy' | 'none'; keyedFile: string } {
|
|
545
|
-
const keyedFile = path.join(workspaceRoot, stateRelPath(runId, slug));
|
|
546
|
-
const keyed = readState(keyedFile);
|
|
547
|
-
if (keyed !== null) return { state: keyed, from: 'keyed', keyedFile };
|
|
548
|
-
if (fileExists(keyedFile)) {
|
|
549
|
-
// Present but unreadable. NOT a migration case: adopting the legacy file
|
|
550
|
-
// here would silently replace a corrupt budget with a foreign one.
|
|
551
|
-
return { state: null, from: 'keyed', keyedFile };
|
|
552
|
-
}
|
|
553
|
-
const legacy = readState(path.join(workspaceRoot, legacyStateRelPath(runId)));
|
|
554
|
-
if (legacy === null) return { state: null, from: 'none', keyedFile };
|
|
555
|
-
// Adopted only when the legacy file is not another roadmap's.
|
|
556
|
-
if (legacy.roadmap !== undefined && legacy.roadmap !== slug) {
|
|
557
|
-
return { state: null, from: 'none', keyedFile };
|
|
558
|
-
}
|
|
559
|
-
return { state: legacy, from: 'legacy', keyedFile };
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
/**
|
|
563
|
-
* The only writer of a run-state file. Never throws — the state is a budget, and
|
|
564
|
-
* throwing here would turn an observability concern into a turn-end failure.
|
|
565
|
-
*
|
|
566
|
-
* RETURNS whether the write landed, and the return is load-bearing exactly once:
|
|
567
|
-
* the engage path must not BLOCK on a counter it could not persist, because there
|
|
568
|
-
* the ladder cannot bound the loop. Every other caller ignores it (fail-open).
|
|
569
|
-
*/
|
|
570
|
-
function writeState(file: string, state: RunState): boolean {
|
|
571
|
-
// ATOMIC (runtime-enforcement Phase 5.2): temp beside the target, then
|
|
572
|
-
// rename. This file is the loop's ITERATION BUDGET — a torn direct write
|
|
573
|
-
// leaves a record `parseRecord` rejects, the counter restarts at zero, and
|
|
574
|
-
// the cap stops bounding anything. A non-atomic budget write fails as an
|
|
575
|
-
// UNBOUNDED loop, which is what the budget exists to prevent.
|
|
576
|
-
return atomicWriteJson(file, state);
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
/**
|
|
580
|
-
* Clear a run's budget: the keyed file, and the legacy per-session file ONLY when
|
|
581
|
-
* this read adopted it. Both halves are load-bearing.
|
|
582
|
-
*
|
|
583
|
-
* Touching the legacy file at all: `readRunState` adopts it for a migrated run, so
|
|
584
|
-
* clearing only the keyed one made every clear a no-op there — `complete` stayed
|
|
585
|
-
* resumable and the absent-confirm clear became a repeating cycle.
|
|
586
|
-
*
|
|
587
|
-
* Gating on `adoptedLegacy` rather than on the adoption predicate: adoption and
|
|
588
|
-
* deletion want OPPOSITE defaults. A pre-round-7 file carries no `roadmap` field
|
|
589
|
-
* and is therefore adoptable by every slug — right for adopting, catastrophic for
|
|
590
|
-
* deleting, where one slug's clear would take another slug's live budget or halt
|
|
591
|
-
* stamp with it. Adoption is a fact this read already established; it is passed in
|
|
592
|
-
* rather than re-derived from a condition that cannot express it.
|
|
593
|
-
*/
|
|
594
|
-
export function clearRunState(
|
|
595
|
-
workspaceRoot: string,
|
|
596
|
-
runId: string,
|
|
597
|
-
keyedFile: string,
|
|
598
|
-
adoptedLegacy: boolean,
|
|
599
|
-
): void {
|
|
600
|
-
revokeBillingGrant(workspaceRoot, runId); // the run IS the grant's TTL
|
|
601
|
-
try {
|
|
602
|
-
fs.rmSync(keyedFile, { force: true });
|
|
603
|
-
} catch {
|
|
604
|
-
/* fail-open */
|
|
605
|
-
}
|
|
606
|
-
if (!adoptedLegacy) return;
|
|
607
|
-
try {
|
|
608
|
-
fs.rmSync(path.join(workspaceRoot, legacyStateRelPath(runId)), { force: true });
|
|
609
|
-
} catch {
|
|
610
|
-
/* fail-open */
|
|
611
|
-
}
|
|
612
|
-
}
|
|
613
|
-
|
|
614
|
-
function fileExists(p: string): boolean {
|
|
615
|
-
try {
|
|
616
|
-
return fs.statSync(p).isFile();
|
|
617
|
-
} catch {
|
|
618
|
-
return false;
|
|
619
|
-
}
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
function readState(file: string): RunState | null {
|
|
623
|
-
try {
|
|
624
|
-
const parsed: unknown = JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
625
|
-
if (parsed === null || typeof parsed !== 'object') return null;
|
|
626
|
-
const o = parsed as Record<string, unknown>;
|
|
627
|
-
if (typeof o['started_at'] !== 'string') return null;
|
|
628
|
-
if (typeof o['iterations'] !== 'number') return null;
|
|
629
|
-
if (typeof o['last_turn'] !== 'number') return null;
|
|
630
|
-
if (!Array.isArray(o['history'])) return null;
|
|
631
|
-
const rec: RunState = {
|
|
632
|
-
started_at: o['started_at'],
|
|
633
|
-
iterations: o['iterations'],
|
|
634
|
-
last_turn: o['last_turn'],
|
|
635
|
-
history: (o['history'] as unknown[]).filter(
|
|
636
|
-
(n): n is number => typeof n === 'number',
|
|
637
|
-
),
|
|
638
|
-
};
|
|
639
|
-
if (typeof o['last_engaged_at'] === 'string') {
|
|
640
|
-
rec.last_engaged_at = o['last_engaged_at'];
|
|
641
|
-
}
|
|
642
|
-
// Round-tripped, and it has to be: dropping it here would make the
|
|
643
|
-
// source look changed on EVERY fire, reset the window every time, and
|
|
644
|
-
// silently disable the stall detector the field was added to protect.
|
|
645
|
-
if (typeof o['history_source'] === 'string') {
|
|
646
|
-
rec.history_source = o['history_source'];
|
|
647
|
-
}
|
|
648
|
-
if (typeof o['roadmap'] === 'string') {
|
|
649
|
-
rec.roadmap = o['roadmap'];
|
|
650
|
-
}
|
|
651
|
-
if (typeof o['absent_fires'] === 'number' && Number.isFinite(o['absent_fires'])) {
|
|
652
|
-
rec.absent_fires = o['absent_fires'];
|
|
653
|
-
}
|
|
654
|
-
if (o['inert_reported'] === true) {
|
|
655
|
-
rec.inert_reported = true;
|
|
656
|
-
}
|
|
657
|
-
// Round-tripped for the same reason `history_source` is: without this the
|
|
658
|
-
// 8.1 hold is dead code that reads as shipped.
|
|
659
|
-
const dlv = parseDeliveryState(o['delivery']);
|
|
660
|
-
if (dlv !== undefined) rec.delivery = dlv;
|
|
661
|
-
// Round-tripped for the same reason `history_source` is: dropped, the
|
|
662
|
-
// premise would be re-recorded every fire from the newest observation, so
|
|
663
|
-
// the two sides could never differ and the rung would be dead code.
|
|
664
|
-
if (typeof o['context_fingerprint'] === 'string' && o['context_fingerprint'] !== '') {
|
|
665
|
-
rec.context_fingerprint = o['context_fingerprint'];
|
|
666
|
-
}
|
|
667
|
-
// Tolerant, not permissive — see `parseHaltStamp` for what it accepts
|
|
668
|
-
// beyond the halt set and why dropping a newer build's stamp was the
|
|
669
|
-
// wrong failure direction for a budget.
|
|
670
|
-
const halted = parseHaltStamp(o['halted']);
|
|
671
|
-
if (halted !== null) rec.halted = halted;
|
|
672
|
-
return rec;
|
|
673
|
-
} catch {
|
|
674
|
-
return null;
|
|
675
|
-
}
|
|
676
|
-
}
|
|
677
|
-
|
|
678
|
-
/**
|
|
679
|
-
* The six fields that make an event's two-tree property checkable by a third
|
|
680
|
-
* party holding nothing but the ledger line. The caller adds a seventh,
|
|
681
|
-
* `roadmap_path`, which it knows and this function does not.
|
|
682
|
-
*
|
|
683
|
-
* Keep this count in step with the file header and the call-site comment. Round 2
|
|
684
|
-
* finding 4 caught the header saying four where the function emitted five; the
|
|
685
|
-
* edit that fixed it added `session_cwd` and left THIS heading saying five, which
|
|
686
|
-
* round 3 finding 3 then caught. Two rounds, same drift, opposite direction — the
|
|
687
|
-
* count is load-bearing because it is what a later edit dropping a field would
|
|
688
|
-
* have to contradict.
|
|
689
|
-
*
|
|
690
|
-
* The defect this concern shipped with was a writer and a reader resolving
|
|
691
|
-
* DIFFERENT trees: `sessions:claim` wrote under `process.cwd()` (the operator's
|
|
692
|
-
* worktree) while this concern read under `--project-dir` (the parent
|
|
693
|
-
* checkout), so the claim was never found and no event was written. An empty
|
|
694
|
-
* ledger looked exactly like a healthy idle run, which is how it survived a
|
|
695
|
-
* release.
|
|
696
|
-
*
|
|
697
|
-
* A reader therefore has to see, from the line alone, which trees were in play
|
|
698
|
-
* and where the contract was actually read out of. A boolean such as
|
|
699
|
-
* `worktree_started: true` would be another assertion by the system under
|
|
700
|
-
* observation rather than a check on it; the falsifiable facts are concrete
|
|
701
|
-
* (AI council 2026-08-19, 2/2 convergent):
|
|
702
|
-
*
|
|
703
|
-
* `session_root !== workspace_root` → writer and reader resolved different
|
|
704
|
-
* trees. After the fix this is the
|
|
705
|
-
* NORMAL healthy two-tree arrangement,
|
|
706
|
-
* not a defect: the claim now lives in
|
|
707
|
-
* the shared root, so the line existing
|
|
708
|
-
* at all with the two roots differing is
|
|
709
|
-
* the fix working. Round 2 finding 7
|
|
710
|
-
* caught the previous wording calling it
|
|
711
|
-
* "the shipped defect condition", which
|
|
712
|
-
* made a healthy engagement line read as
|
|
713
|
-
* evidence of the bug
|
|
714
|
-
* `git_dir !== git_common_dir` → the session's own tree IS a linked
|
|
715
|
-
* worktree. Only meaningful when both
|
|
716
|
-
* are non-empty — see the degenerate
|
|
717
|
-
* reading below
|
|
718
|
-
* `claim_path` under `git_common_dir` → the contract crossed into the shared
|
|
719
|
-
* root. Also gated on a non-empty
|
|
720
|
-
* `git_common_dir`: round 2 finding 2
|
|
721
|
-
* measured that on a non-repo line both
|
|
722
|
-
* git fields are `''` and every absolute
|
|
723
|
-
* path satisfies `startsWith('')`, so a
|
|
724
|
-
* reader applying the rule unguarded
|
|
725
|
-
* concludes the contract crossed a
|
|
726
|
-
* boundary the line says nothing about
|
|
727
|
-
* `session_cwd` → the raw directory the session reported
|
|
728
|
-
* before any resolution, so a reader can
|
|
729
|
-
* tell "same tree" from "could not
|
|
730
|
-
* resolve"
|
|
731
|
-
*
|
|
732
|
-
* ## The degenerate reading, stated so it cannot be mistaken for a negative
|
|
733
|
-
*
|
|
734
|
-
* Two of the three path relations above are only interpretable on a line whose
|
|
735
|
-
* git fields are non-empty. Empty means git could not be read from the session's
|
|
736
|
-
* root at all — a plain temp directory, a broken checkout — and that is an
|
|
737
|
-
* ABSENCE of evidence rather than evidence of a same-root run. A reader must
|
|
738
|
-
* check `git_common_dir !== ''` before applying either relation.
|
|
739
|
-
*
|
|
740
|
-
* `session_cwd` exists for the same reason, and it is a fact rather than an
|
|
741
|
-
* assertion. `session_checkout` degrades to `workspace_root` when its guards
|
|
742
|
-
* fail, and the raw `cwd` is what can make a degraded line distinguishable from a
|
|
743
|
-
* genuine same-tree one. A boolean `resolved: false` would have been the system
|
|
744
|
-
* under observation asserting its own health; the raw path is checkable.
|
|
745
|
-
*
|
|
746
|
-
* **The relation is SUFFICIENT, never necessary, and this file has now written it
|
|
747
|
-
* as necessary three rounds running.** A `session_cwd` outside `session_root`
|
|
748
|
-
* proves a fallback happened. The converse does not hold: round 4 finding 3 names
|
|
749
|
-
* three reachable inputs where the resolver falls back and the raw cwd still sits
|
|
750
|
-
* under `session_root` — a cwd inside a DIFFERENT repository nested under this
|
|
751
|
-
* checkout (a vendored clone, a test fixture) failing the identity check, a cwd
|
|
752
|
-
* that does not exist, and a relative cwd resolved against the reader's root. On
|
|
753
|
-
* those lines the provenance cannot tell a reader that a fallback occurred, and
|
|
754
|
-
* saying so is the honest bound rather than a wider claim that keeps being
|
|
755
|
-
* refuted.
|
|
756
|
-
*
|
|
757
|
-
* **The degradation this field was introduced for is gone, and the field stayed.**
|
|
758
|
-
* Round 2 added it because a session started from a SUBDIRECTORY of a worktree
|
|
759
|
-
* failed the resolver's checkout-root condition and collapsed onto the reader's
|
|
760
|
-
* root. Round 3 finding 2 then showed the field was BLIND to exactly that case in
|
|
761
|
-
* the layout it mattered in: with the worktree nested under the parent, the
|
|
762
|
-
* collapsed root, both git fields AND the raw cwd all read healthy same-tree.
|
|
763
|
-
* The fix was upstream — `session_checkout` now walks up to the nearest enclosing
|
|
764
|
-
* checkout root — so a subdirectory is no longer a degradation at all.
|
|
765
|
-
*
|
|
766
|
-
* What remains, and what the field is now for: a cwd inside a DIFFERENT
|
|
767
|
-
* repository, a cwd that does not exist, a cwd under no checkout root at all.
|
|
768
|
-
* Those still fall back, and on those lines `session_cwd` is still the only
|
|
769
|
-
* thing that says so. Two cases pin both directions.
|
|
770
|
-
*
|
|
771
|
-
* ## Both git fields come from `session_root`, not from `workspace_root`
|
|
772
|
-
*
|
|
773
|
-
* The first shipped version of this function derived both of them from the
|
|
774
|
-
* READER's root, and R2 finding 1 killed it: in the arrangement documented
|
|
775
|
-
* three paragraphs up as the live one — the concern running under
|
|
776
|
-
* `--project-dir <parent checkout>` — `git_dir(parent)` and
|
|
777
|
-
* `git_common_dir(parent)` are the SAME path, so the discriminator above read
|
|
778
|
-
* FALSE for every real worktree-started run. The enrichment existed to make
|
|
779
|
-
* the two-tree property auditable and could not express it. `claim_path` could
|
|
780
|
-
* not rescue it either: the claim lands under `git_common_dir` in a plain
|
|
781
|
-
* checkout too, so that containment holds in both arrangements.
|
|
782
|
-
*
|
|
783
|
-
* `session_root` is the session's OWN checkout, resolved through the register's
|
|
784
|
-
* `session_checkout` — the same three-condition guard (existing directory,
|
|
785
|
-
* checkout root, same repository) rather than a second, divergent reading of
|
|
786
|
-
* `payload.cwd`. It degrades to `workspace_root` when any condition fails,
|
|
787
|
-
* which makes `session_root === workspace_root` mean "same tree, or unresolvable"
|
|
788
|
-
* and never a false two-tree claim.
|
|
789
|
-
*
|
|
790
|
-
* `process.cwd()` is deliberately NOT among the fields. The dispatcher chdirs
|
|
791
|
-
* into `--project-dir` before the chain runs, so at concern time cwd equals
|
|
792
|
-
* `workspace_root` on every shipped path — a field that can never disagree with
|
|
793
|
-
* another cannot falsify anything, and shipping it as provenance would be the
|
|
794
|
-
* decorative-evidence shape this whole change exists to remove. Measured while
|
|
795
|
-
* writing the test that asserted the opposite.
|
|
796
|
-
*
|
|
797
|
-
* Absolute AND realpath-normalised, deliberately: a relative form is
|
|
798
|
-
* interpreted against whichever root the reader happens to hold, and a
|
|
799
|
-
* symlinked form defeats the containment test above. R2 finding 3 measured the
|
|
800
|
-
* second half — the git fields come back realpath-resolved from
|
|
801
|
-
* `_lib/git_common_dir.ts` while the first version passed the envelope string
|
|
802
|
-
* verbatim, so on macOS a healthy run wrote `workspace_root: /var/...` against
|
|
803
|
-
* `git_common_dir: /private/var/...` and the documented prefix test failed on
|
|
804
|
-
* it. Normalising here is the only place a ledger-only reader can inherit it
|
|
805
|
-
* from. These are local filesystem paths in gitignored runtime state, never
|
|
806
|
-
* published — the same posture the session register already takes.
|
|
807
|
-
*/
|
|
808
|
-
function normalizeDir(p: string): string {
|
|
809
|
-
const abs = path.resolve(p);
|
|
810
|
-
try {
|
|
811
|
-
return fs.realpathSync(abs);
|
|
812
|
-
} catch {
|
|
813
|
-
return abs;
|
|
814
|
-
}
|
|
815
|
-
}
|
|
816
|
-
|
|
817
|
-
/**
|
|
818
|
-
* Realpath a file path without requiring the file to exist: the directory is
|
|
819
|
-
* normalised and the basename rejoined. The per-tree claim fallback names a
|
|
820
|
-
* path that may not have been written, and a missing file must not downgrade
|
|
821
|
-
* the whole line to un-normalised paths.
|
|
822
|
-
*/
|
|
823
|
-
function normalizeFile(p: string): string {
|
|
824
|
-
const abs = path.resolve(p);
|
|
825
|
-
return path.join(normalizeDir(path.dirname(abs)), path.basename(abs));
|
|
826
|
-
}
|
|
827
|
-
|
|
828
|
-
export function provenance(
|
|
829
|
-
workspaceRoot: string,
|
|
830
|
-
claimPath: string,
|
|
831
|
-
sessionRoot: string,
|
|
832
|
-
sessionCwd: string,
|
|
833
|
-
): JsonObject {
|
|
834
|
-
const reader = normalizeDir(workspaceRoot);
|
|
835
|
-
const writer = normalizeDir(sessionRoot);
|
|
836
|
-
return {
|
|
837
|
-
workspace_root: reader,
|
|
838
|
-
session_root: writer,
|
|
839
|
-
// Empty when the host sent no `cwd` at all, which is a different fact
|
|
840
|
-
// from a `cwd` that failed resolution — the first says the host is
|
|
841
|
-
// silent, the second says the session sat somewhere `session_checkout`
|
|
842
|
-
// would not trust. Both are readable; neither is guessed.
|
|
843
|
-
//
|
|
844
|
-
// Trimmed with the SAME rule `session_checkout` applies to the same
|
|
845
|
-
// string (round 3 finding 6). Without it a whitespace-padded value
|
|
846
|
-
// validated fine there and was `path.resolve`d here against the reader's
|
|
847
|
-
// cwd, fabricating a path that is neither `session_root` nor under it —
|
|
848
|
-
// precisely the shape the docblock above says no healthy resolution
|
|
849
|
-
// produces, so a healthy line read as degraded. A whitespace-only value
|
|
850
|
-
// now reads as host silence, which is what it is.
|
|
851
|
-
session_cwd: sessionCwd.trim() === '' ? '' : normalizeDir(sessionCwd.trim()),
|
|
852
|
-
git_dir: git_dir(writer) ?? '',
|
|
853
|
-
git_common_dir: git_common_dir(writer) ?? '',
|
|
854
|
-
claim_path: normalizeFile(claimPath),
|
|
855
|
-
};
|
|
856
|
-
}
|
|
857
|
-
|
|
858
|
-
/**
|
|
859
|
-
* The roadmap file this run is executing, chosen by which tree OWNS the
|
|
860
|
-
* roadmaps directory — never by whether one particular file is present.
|
|
861
|
-
*
|
|
862
|
-
* ## The per-file fallback was wrong, and round 4 finding 1 named the cost
|
|
863
|
-
*
|
|
864
|
-
* The first version resolved per FILE: session copy if it exists, else the
|
|
865
|
-
* reader's. That reads correctly in a fresh worktree and breaks a finished run.
|
|
866
|
-
* `roadmap-progress-sync` mandates archival in the SAME change that closes the
|
|
867
|
-
* last step, so a completing run `git mv`s the file into
|
|
868
|
-
* `agents/roadmaps/archive/`. On the next stop fire the session copy is gone, the
|
|
869
|
-
* per-file rule silently fell back to the parent's UN-archived copy, read its
|
|
870
|
-
* still-open steps, and blocked with "continue with this step now" against a path
|
|
871
|
-
* that no longer exists in the tree the agent is editing — re-engaging to the
|
|
872
|
-
* iteration cap instead of ever reaching `complete`.
|
|
873
|
-
*
|
|
874
|
-
* Per DIRECTORY instead: if the session's tree has `agents/roadmaps/` at all,
|
|
875
|
-
* that tree is authoritative and a missing slug file means the roadmap is gone
|
|
876
|
-
* from this run — archived, renamed, or never created — which the caller's
|
|
877
|
-
* unreadable-roadmap branch already handles correctly by allowing the turn to
|
|
878
|
-
* end. The fallback survives for the case it was actually for: a session root
|
|
879
|
-
* that is not a checkout of this project layout.
|
|
880
|
-
*
|
|
881
|
-
* ## Slug containment
|
|
882
|
-
*
|
|
883
|
-
* The slug comes from a claim file, and `_read_claim_file` accepts any non-empty
|
|
884
|
-
* trimmed string. `claim_is_stale` in the same module treats containment as
|
|
885
|
-
* necessary before any read; round 4 finding 7 observed that this function did
|
|
886
|
-
* not, and that it now builds paths in TWO trees rather than one. A slug that
|
|
887
|
-
* escapes `agents/roadmaps/` returns `null` and the caller allows — refusing to
|
|
888
|
-
* name a file is the safe direction for a concern whose only power is refusing to
|
|
889
|
-
* end a turn.
|
|
890
|
-
*/
|
|
891
|
-
function resolveRoadmap(
|
|
892
|
-
sessionRoot: string,
|
|
893
|
-
workspaceRoot: string,
|
|
894
|
-
slug: string,
|
|
895
|
-
): string | null {
|
|
896
|
-
const dirRel = path.join('agents', 'roadmaps');
|
|
897
|
-
// The SAME normalisation `claim_is_stale` applies to the same claim string
|
|
898
|
-
// (round 5 finding 7). Without it a claim whose slug already carries the
|
|
899
|
-
// suffix rendered as live work in the register while this concern resolved
|
|
900
|
-
// `<slug>.md.md`, failed the read, and allowed every stop — two functions in
|
|
901
|
-
// one flow disagreeing about one string.
|
|
902
|
-
const stem = slug.trim().replace(/\.md$/, '');
|
|
903
|
-
const rel = path.join(dirRel, `${stem}.md`);
|
|
904
|
-
const norm = path.normalize(rel);
|
|
905
|
-
// Containment on the STRUCTURE, not on the characters: `path.join` has already
|
|
906
|
-
// collapsed traversal, so what matters is whether the result is still inside
|
|
907
|
-
// the roadmaps directory and names a file directly in it. Round 5 finding 10:
|
|
908
|
-
// a substring test for `..` also rejected a legitimate slug like
|
|
909
|
-
// `road-to-a..b`, which then silently allowed every stop.
|
|
910
|
-
if (path.dirname(norm) !== dirRel) return null;
|
|
911
|
-
if (sessionRoot !== workspaceRoot && isDirectory(path.join(sessionRoot, dirRel))) {
|
|
912
|
-
return path.join(sessionRoot, norm);
|
|
913
|
-
}
|
|
914
|
-
// Canonical, like every emitted path field (round 5 finding 9). The fallback
|
|
915
|
-
// branch joined the RAW reader root while `workspace_root` on the same line is
|
|
916
|
-
// normalised, so under a symlinked ancestor a reader's containment test failed
|
|
917
|
-
// on a perfectly healthy line — the regression round 2 finding 3 fixed for the
|
|
918
|
-
// other six fields, reintroduced on the seventh.
|
|
919
|
-
return path.join(normalizeDir(workspaceRoot), norm);
|
|
920
|
-
}
|
|
921
|
-
|
|
922
|
-
function isDirectory(p: string): boolean {
|
|
923
|
-
try {
|
|
924
|
-
return fs.statSync(p).isDirectory();
|
|
925
|
-
} catch {
|
|
926
|
-
return false;
|
|
927
|
-
}
|
|
928
|
-
}
|
|
929
|
-
|
|
930
|
-
/**
|
|
931
|
-
* True when a line with this event name, run id and roadmap is already in the
|
|
932
|
-
* ledger — the durable once-guard for the two rungs that cannot keep one in the
|
|
933
|
-
* state file: `halt-roadmap-absent` fires precisely when the state is absent or
|
|
934
|
-
* unparseable, and `blocked` CLEARS the state.
|
|
935
|
-
*/
|
|
936
|
-
function eventAlreadyLogged(
|
|
937
|
-
workspaceRoot: string,
|
|
938
|
-
runId: string,
|
|
939
|
-
slug: string,
|
|
940
|
-
event: string,
|
|
941
|
-
): boolean {
|
|
942
|
-
try {
|
|
943
|
-
const file = path.join(workspaceRoot, EVENTS_RELPATH);
|
|
944
|
-
const size = fs.statSync(file).size;
|
|
945
|
-
const start = Math.max(0, size - LEDGER_TAIL_MAX_BYTES);
|
|
946
|
-
const fd = fs.openSync(file, 'r');
|
|
947
|
-
let text: string;
|
|
948
|
-
try {
|
|
949
|
-
const buf = Buffer.alloc(size - start);
|
|
950
|
-
// The byte count is honoured: a short read, or a truncation between the
|
|
951
|
-
// `statSync` and here, would otherwise decode NUL padding into lines that
|
|
952
|
-
// fail `JSON.parse` and become a false negative.
|
|
953
|
-
const read = fs.readSync(fd, buf, 0, buf.length, start);
|
|
954
|
-
text = buf.subarray(0, read).toString('utf8');
|
|
955
|
-
} finally {
|
|
956
|
-
fs.closeSync(fd);
|
|
957
|
-
}
|
|
958
|
-
for (const line of text.split('\n')) {
|
|
959
|
-
if (line === '') continue;
|
|
960
|
-
let rec: unknown;
|
|
961
|
-
try {
|
|
962
|
-
rec = JSON.parse(line);
|
|
963
|
-
} catch {
|
|
964
|
-
// A partial first line from the tail cut, or a torn append.
|
|
965
|
-
continue;
|
|
966
|
-
}
|
|
967
|
-
if (rec === null || typeof rec !== 'object') continue;
|
|
968
|
-
const o = rec as Record<string, unknown>;
|
|
969
|
-
if (o['event'] === event && o['run_id'] === runId && o['roadmap'] === slug) {
|
|
970
|
-
return true;
|
|
971
|
-
}
|
|
972
|
-
}
|
|
973
|
-
return false;
|
|
974
|
-
} catch {
|
|
975
|
-
// No ledger, or unreadable: nothing proves the line was written, and
|
|
976
|
-
// emitting once more is the lesser failure than going silent on a rung this
|
|
977
|
-
// whole file exists to make visible.
|
|
978
|
-
return false;
|
|
979
|
-
}
|
|
980
|
-
}
|
|
981
|
-
|
|
982
|
-
function appendEvent(workspaceRoot: string, record: JsonObject): void {
|
|
983
|
-
try {
|
|
984
|
-
const file = path.join(workspaceRoot, EVENTS_RELPATH);
|
|
985
|
-
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
986
|
-
fs.appendFileSync(file, `${JSON.stringify(record)}\n`, 'utf8');
|
|
987
|
-
} catch {
|
|
988
|
-
// The ledger is observability, never a reason to change the verdict.
|
|
989
|
-
}
|
|
990
|
-
}
|
|
991
|
-
|
|
992
|
-
/**
|
|
993
|
-
* True when `turn-end-gate` refused exactly this turn — the defer branch.
|
|
994
|
-
* Race-free by chain order: concerns run sequentially and this concern is
|
|
995
|
-
* registered after the gate, so the gate's marker for this turn is on disk
|
|
996
|
-
* before this read happens.
|
|
997
|
-
*/
|
|
998
|
-
export function refusedThisTurn(
|
|
999
|
-
workspaceRoot: string,
|
|
1000
|
-
sessionId: string,
|
|
1001
|
-
turnOrdinal: number,
|
|
1002
|
-
): boolean {
|
|
1003
|
-
try {
|
|
1004
|
-
const file = sessionRefusalFile(workspaceRoot, deriveSessionKey(sessionId || 'unknown-session'));
|
|
1005
|
-
const rec = parseRecord(fs.readFileSync(file, 'utf-8'));
|
|
1006
|
-
return rec !== null && rec.refused_turn === turnOrdinal;
|
|
1007
|
-
} catch {
|
|
1008
|
-
return false;
|
|
1009
|
-
}
|
|
1010
|
-
}
|
|
1011
|
-
|
|
1012
|
-
function str(v: JsonValue | undefined): string {
|
|
1013
|
-
return typeof v === 'string' ? v : '';
|
|
1014
|
-
}
|
|
1015
|
-
|
|
1016
|
-
export function main(): number {
|
|
1017
|
-
if (is_replay_mode()) return EXIT_ALLOW;
|
|
1018
|
-
if (process.env['AGENT_CONFIG_NO_RUN_CONTINUATION'] === '1') return EXIT_ALLOW;
|
|
1019
|
-
|
|
1020
|
-
let envelope: JsonObject;
|
|
1021
|
-
let payload: JsonObject;
|
|
1022
|
-
try {
|
|
1023
|
-
[envelope, payload] = unwrap(readHookStdin(), 'claude');
|
|
1024
|
-
} catch {
|
|
1025
|
-
return EXIT_ALLOW;
|
|
1026
|
-
}
|
|
1027
|
-
|
|
1028
|
-
const workspaceRoot = str(envelope['workspace_root'] as JsonValue | undefined) || process.cwd();
|
|
1029
|
-
const sessionId =
|
|
1030
|
-
str(payload['session_id'] as JsonValue | undefined) ||
|
|
1031
|
-
str(envelope['session_id'] as JsonValue | undefined);
|
|
1032
|
-
|
|
1033
|
-
// ── contract gate ────────────────────────────────────────────────
|
|
1034
|
-
const claim = resolve_claim(workspaceRoot, sessionId || null);
|
|
1035
|
-
if (claim === null) return EXIT_ALLOW;
|
|
1036
|
-
const slug = claim.slug;
|
|
1037
|
-
|
|
1038
|
-
// ── which tree's roadmap is the run ──────────────────────────────
|
|
1039
|
-
//
|
|
1040
|
-
// The SESSION's own checkout, falling back to the reader's root. In a plain
|
|
1041
|
-
// checkout the two are the same path and nothing about this changes; only
|
|
1042
|
-
// the two-tree case moves.
|
|
1043
|
-
//
|
|
1044
|
-
// R2 round 3 finding 1: this read the READER's tree unconditionally, and the
|
|
1045
|
-
// count it produces feeds the stall detector. In a worktree session the agent
|
|
1046
|
-
// flips checkboxes in the worktree copy while the parent copy does not move
|
|
1047
|
-
// until a merge — so the detector watched a file nobody was editing, the
|
|
1048
|
-
// count never changed, and after three engagements it emitted `halt-stall`
|
|
1049
|
-
// and declared a working run finished. The mechanism whose job is to detect a
|
|
1050
|
-
// stall was manufacturing one, which is the failure this file's own header
|
|
1051
|
-
// warns about in the abstract.
|
|
1052
|
-
//
|
|
1053
|
-
// AI council 2026-08-19, 2/2 convergent: resolve against the session
|
|
1054
|
-
// checkout, keep the fallback. Both seats also flagged, independently, that
|
|
1055
|
-
// `execution.mode` and the open-step count need not share an authority —
|
|
1056
|
-
// progress is inherently session-local while a mode could be read as
|
|
1057
|
-
// repo-wide policy. That choice is made HERE and stated rather than left
|
|
1058
|
-
// implicit: BOTH come from the session's file, because the session is
|
|
1059
|
-
// executing the file in its own tree and the parent's copy is simply an older
|
|
1060
|
-
// revision of the same document. A genuinely repo-wide mode policy would need
|
|
1061
|
-
// its own precedence rule, and inventing one on this evidence would be
|
|
1062
|
-
// designing for a case nobody has met.
|
|
1063
|
-
const sessionRoot = session_checkout(
|
|
1064
|
-
workspaceRoot,
|
|
1065
|
-
str(payload['cwd'] as JsonValue | undefined),
|
|
1066
|
-
);
|
|
1067
|
-
const roadmapPath = resolveRoadmap(sessionRoot, workspaceRoot, slug);
|
|
1068
|
-
const runId = deriveSessionKey(sessionId || 'unknown-session');
|
|
1069
|
-
|
|
1070
|
-
// Two locals rather than one plus a re-check: `roadmapFile` is only assigned
|
|
1071
|
-
// where the read succeeded, so the guard below narrows BOTH and everything
|
|
1072
|
-
// downstream holds a plain string. The alternative — re-testing `roadmapPath`
|
|
1073
|
-
// after the guard purely for the compiler — would be a branch that cannot be
|
|
1074
|
-
// reached and cannot be tested.
|
|
1075
|
-
let roadmapFile: string | null = null;
|
|
1076
|
-
let roadmapText: string | null = null;
|
|
1077
|
-
if (roadmapPath !== null) {
|
|
1078
|
-
try {
|
|
1079
|
-
roadmapText = fs.readFileSync(roadmapPath, 'utf8');
|
|
1080
|
-
roadmapFile = roadmapPath;
|
|
1081
|
-
} catch {
|
|
1082
|
-
roadmapText = null;
|
|
1083
|
-
}
|
|
1084
|
-
}
|
|
1085
|
-
|
|
1086
|
-
if (roadmapText === null || roadmapFile === null) {
|
|
1087
|
-
// ── the roadmap is not readable from the authoritative tree ──────
|
|
1088
|
-
//
|
|
1089
|
-
// Round 5 findings 2, 5 and 10, which are one shape seen three ways: this
|
|
1090
|
-
// returned a bare `EXIT_ALLOW` and left NOTHING behind.
|
|
1091
|
-
//
|
|
1092
|
-
// Finding 2 is the sharp end. `roadmap-progress-sync` mandates archival in
|
|
1093
|
-
// the same change that closes the last step, so a completing run flips the
|
|
1094
|
-
// last box and `git mv`s the file in one reply. The next fire found it
|
|
1095
|
-
// gone, allowed, and never reached the `complete` rung — so no line said
|
|
1096
|
-
// the run finished, AND `fs.rmSync(stateFile)` never ran. The state file
|
|
1097
|
-
// survived with `iterations` and `started_at` from the finished run, so a
|
|
1098
|
-
// later claim by the same session id began with part of the 25-iteration
|
|
1099
|
-
// budget spent and the 4 h clock already running — exactly what the
|
|
1100
|
-
// comment on that rung promises will not happen.
|
|
1101
|
-
//
|
|
1102
|
-
// A prior state file is the discriminator, and it is a fact rather than a
|
|
1103
|
-
// guess: the state only exists if THIS concern engaged on this roadmap
|
|
1104
|
-
// before, which it only does on an `autonomous` one. So:
|
|
1105
|
-
//
|
|
1106
|
-
// state present → this run was driven here and its roadmap is gone. Emit
|
|
1107
|
-
// the line, clear the budget, allow.
|
|
1108
|
-
// state absent → nothing was ever driven. Stay silent, which is the
|
|
1109
|
-
// truth rather than a gap: a `phase-checkpoints` claim
|
|
1110
|
-
// and a worktree branched before the roadmap landed
|
|
1111
|
-
// (finding 5) both land here, and neither is an event.
|
|
1112
|
-
//
|
|
1113
|
-
// What this does NOT claim is to tell archival from never-created. The
|
|
1114
|
-
// filesystem cannot: both are an absent file. The docblock on
|
|
1115
|
-
// `resolveRoadmap` used to assert the archival reading, and finding 5 was
|
|
1116
|
-
// right that it conflated the two — so the reading is now carried by the
|
|
1117
|
-
// state file, which actually knows.
|
|
1118
|
-
// Read THIS roadmap's state, keyed (round 7 finding 2). The previous version
|
|
1119
|
-
// read the session-keyed file with no roadmap discriminator, so after a
|
|
1120
|
-
// re-claim it reported roadmap A's iteration count under roadmap B's slug
|
|
1121
|
-
// and deleted A's live state — falsifying its own documented premise that
|
|
1122
|
-
// "state only exists if this concern engaged on THIS roadmap before".
|
|
1123
|
-
const runState = readRunState(workspaceRoot, runId, slug);
|
|
1124
|
-
const driven = runState.state;
|
|
1125
|
-
if (driven === null && runState.from === 'none') return EXIT_ALLOW;
|
|
1126
|
-
|
|
1127
|
-
// A HALT STAMP IS NEVER ERASED HERE (round 6 finding 1, high).
|
|
1128
|
-
//
|
|
1129
|
-
// A halted run has already recorded its own end, so there is nothing to
|
|
1130
|
-
// announce and nothing to reclaim. Silence and no write is the whole
|
|
1131
|
-
// correct action.
|
|
1132
|
-
if (driven?.halted !== undefined) return EXIT_ALLOW;
|
|
1133
|
-
const absenceRoots = provenance(
|
|
1134
|
-
workspaceRoot,
|
|
1135
|
-
claim.path,
|
|
1136
|
-
sessionRoot,
|
|
1137
|
-
str(payload['cwd'] as JsonValue | undefined),
|
|
1138
|
-
);
|
|
1139
|
-
// `null` where a traversal or malformed slug refused to name a file at
|
|
1140
|
-
// all (finding 10): the line still exists, so a refusal is no longer
|
|
1141
|
-
// indistinguishable from the concern never firing.
|
|
1142
|
-
absenceRoots['roadmap_path'] = roadmapPath;
|
|
1143
|
-
|
|
1144
|
-
// ── ONE absence is not a finished run (round 7 findings 1 and 4) ──
|
|
1145
|
-
//
|
|
1146
|
-
// Round 6 stopped this branch erasing a HALTED run's stamp and left the
|
|
1147
|
-
// larger half open: a run with a LIVE budget still had its state deleted on
|
|
1148
|
-
// a single unreadable fire. The triggers are ordinary — the agent checks out
|
|
1149
|
-
// a ref without the roadmap, a tool rewrites the file unlink-then-write, an
|
|
1150
|
-
// EACCES lands on the stop fire — and the consequence is unbounded: iteration
|
|
1151
|
-
// 20 becomes iteration 1 with a fresh 4 h clock, repeatable every time.
|
|
1152
|
-
//
|
|
1153
|
-
// Archival and a momentary read failure are indistinguishable from ONE fire.
|
|
1154
|
-
// They are not indistinguishable across two: a rewrite window is
|
|
1155
|
-
// sub-second, while an archived roadmap stays archived across turns. So the
|
|
1156
|
-
// absence is counted, the ledger line is written ONCE (on the first), and
|
|
1157
|
-
// the budget is reclaimed only after the absence has persisted.
|
|
1158
|
-
//
|
|
1159
|
-
// A state file that exists but cannot be parsed is never deleted here
|
|
1160
|
-
// (round 7 finding 4): the counter has nowhere to live, and deleting what we
|
|
1161
|
-
// could not read would erase an interrupted halt stamp — the exact leak the
|
|
1162
|
-
// presence check was added to close. The next healthy write supersedes it.
|
|
1163
|
-
const absentFires = (driven?.absent_fires ?? 0) + 1;
|
|
1164
|
-
// A readable state carries the counter; without one it has nowhere to live
|
|
1165
|
-
// and would recompute to 1 every fire, so the ledger answers instead.
|
|
1166
|
-
const firstAbsence =
|
|
1167
|
-
driven === null
|
|
1168
|
-
? !eventAlreadyLogged(workspaceRoot, runId, slug, 'halt-roadmap-absent')
|
|
1169
|
-
: absentFires === 1;
|
|
1170
|
-
if (firstAbsence) {
|
|
1171
|
-
appendEvent(workspaceRoot, {
|
|
1172
|
-
event: 'halt-roadmap-absent',
|
|
1173
|
-
run_id: runId,
|
|
1174
|
-
roadmap: slug,
|
|
1175
|
-
// `null` when the state file exists but could not be parsed.
|
|
1176
|
-
// Reported as null rather than as 0, which would claim a fact the
|
|
1177
|
-
// file no longer carries.
|
|
1178
|
-
iterations: driven?.iterations ?? null,
|
|
1179
|
-
absent_fires: driven === null ? null : absentFires,
|
|
1180
|
-
at: new Date().toISOString(),
|
|
1181
|
-
...absenceRoots,
|
|
1182
|
-
});
|
|
1183
|
-
}
|
|
1184
|
-
if (driven === null) return EXIT_ALLOW;
|
|
1185
|
-
if (absentFires < ABSENT_CONFIRM_FIRES) {
|
|
1186
|
-
driven.absent_fires = absentFires;
|
|
1187
|
-
writeState(runState.keyedFile, driven);
|
|
1188
|
-
return EXIT_ALLOW;
|
|
1189
|
-
}
|
|
1190
|
-
// Confirmed — see `clearRunState` for why the legacy file is in scope and
|
|
1191
|
-
// why only an adopted one is.
|
|
1192
|
-
clearRunState(workspaceRoot, runId, runState.keyedFile, runState.from === 'legacy');
|
|
1193
|
-
return EXIT_ALLOW;
|
|
1194
|
-
}
|
|
1195
|
-
if (parseExecutionMode(roadmapText) !== 'autonomous') return EXIT_ALLOW;
|
|
1196
|
-
|
|
1197
|
-
// ── turn identity ────────────────────────────────────────────────
|
|
1198
|
-
const transcriptPath = str(
|
|
1199
|
-
(payload['transcript_path'] ?? payload['transcriptPath']) as JsonValue | undefined,
|
|
1200
|
-
);
|
|
1201
|
-
if (!transcriptPath) return EXIT_ALLOW;
|
|
1202
|
-
// Over the shared cap, `readTranscriptTail` returns `turnOrdinal: 0`
|
|
1203
|
-
// without throwing — indistinguishable from a genuinely fresh session. The
|
|
1204
|
-
// ordinal is the ONLY key the defer-to-the-gate check has, so an untrusted
|
|
1205
|
-
// one must not be used to decide a block: allow instead.
|
|
1206
|
-
//
|
|
1207
|
-
// This is the residual half of R2 round 2's finding 1. Sharing the cap
|
|
1208
|
-
// stops the two hooks disagreeing about the SAME transcript; this stops
|
|
1209
|
-
// this concern acting on an ordinal neither of them could compute. Erring
|
|
1210
|
-
// toward allow is the same fail-open posture the gate takes on every
|
|
1211
|
-
// unreadable-transcript case.
|
|
1212
|
-
try {
|
|
1213
|
-
if (fs.statSync(transcriptPath).size > TRANSCRIPT_READ_MAX_BYTES) {
|
|
1214
|
-
// Round 7 finding 5: this returned ALLOW with no event and no state
|
|
1215
|
-
// change, so in the long-run regime this concern exists for — a 4 h cap
|
|
1216
|
-
// — a session whose transcript crosses the cap went silently inert for
|
|
1217
|
-
// the rest of the run while its budget stayed live. An inert mechanism
|
|
1218
|
-
// indistinguishable in the ledger from a healthy idle run is the exact
|
|
1219
|
-
// failure this whole roadmap is about, and the header claims every rung
|
|
1220
|
-
// is a named event.
|
|
1221
|
-
//
|
|
1222
|
-
// Emitted ONCE per run, keyed on the state, so a long inert tail does
|
|
1223
|
-
// not become a long stream of identical lines. No state file means no
|
|
1224
|
-
// run to report on — the same silence the contract-absent rung takes.
|
|
1225
|
-
const inert = readRunState(workspaceRoot, runId, slug);
|
|
1226
|
-
if (inert.state !== null && inert.state.inert_reported !== true) {
|
|
1227
|
-
// The header declares the provenance mandatory for EVERY event, and
|
|
1228
|
-
// a rung that exists to be distinguishable in the ledger is the last
|
|
1229
|
-
// one that should lack the fields a reader distinguishes runs by.
|
|
1230
|
-
const inertRoots = provenance(
|
|
1231
|
-
workspaceRoot,
|
|
1232
|
-
claim.path,
|
|
1233
|
-
sessionRoot,
|
|
1234
|
-
str(payload['cwd'] as JsonValue | undefined),
|
|
1235
|
-
);
|
|
1236
|
-
inertRoots['roadmap_path'] = roadmapFile;
|
|
1237
|
-
appendEvent(workspaceRoot, {
|
|
1238
|
-
event: 'inert-transcript-over-cap',
|
|
1239
|
-
run_id: runId,
|
|
1240
|
-
roadmap: slug,
|
|
1241
|
-
iterations: inert.state.iterations,
|
|
1242
|
-
at: new Date().toISOString(),
|
|
1243
|
-
...inertRoots,
|
|
1244
|
-
});
|
|
1245
|
-
inert.state.inert_reported = true;
|
|
1246
|
-
writeState(inert.keyedFile, inert.state);
|
|
1247
|
-
}
|
|
1248
|
-
return EXIT_ALLOW;
|
|
1249
|
-
}
|
|
1250
|
-
} catch {
|
|
1251
|
-
return EXIT_ALLOW;
|
|
1252
|
-
}
|
|
1253
|
-
let turnOrdinal = 0;
|
|
1254
|
-
try {
|
|
1255
|
-
turnOrdinal = readTranscriptTail(transcriptPath, {
|
|
1256
|
-
maxBytes: TRANSCRIPT_READ_MAX_BYTES,
|
|
1257
|
-
}).turnOrdinal;
|
|
1258
|
-
} catch {
|
|
1259
|
-
return EXIT_ALLOW;
|
|
1260
|
-
}
|
|
1261
|
-
|
|
1262
|
-
// The two-tree provenance, carried on every event this run emits. See
|
|
1263
|
-
// `provenance()` for the six fields and why none of them is a boolean.
|
|
1264
|
-
//
|
|
1265
|
-
// Position, and what changed about the cost argument. Rounds 1 and 2 pushed
|
|
1266
|
-
// this call downward to stop a `phase-checkpoints` session, and then a
|
|
1267
|
-
// session with an over-cap transcript, from paying the git resolution for a
|
|
1268
|
-
// value the next line discarded.
|
|
1269
|
-
//
|
|
1270
|
-
// Round 3 finding 1 made half of that moot: the session root is now needed
|
|
1271
|
-
// ABOVE the mode gate, because it decides which tree's roadmap the mode is
|
|
1272
|
-
// read from. So the resolution happens early by necessity and this call
|
|
1273
|
-
// merely reuses it — the double resolution round 2 finding 5 accepted is
|
|
1274
|
-
// gone as a side effect, and nothing here re-derives it.
|
|
1275
|
-
//
|
|
1276
|
-
// What remains true, and round 3 finding 5 was right to catch the previous
|
|
1277
|
-
// comment claiming otherwise: two branches below still return without an
|
|
1278
|
-
// `appendEvent` — the duplicate-stop-fire guard and the failed-state-write
|
|
1279
|
-
// path — so this is not a position where every path writes a line. It is
|
|
1280
|
-
// simply the cheapest honest one now that the value is already in hand.
|
|
1281
|
-
//
|
|
1282
|
-
// The git resolution here duplicates the one `session_checkout` does to
|
|
1283
|
-
// validate the cwd, and that duplication is ACCEPTED rather than removed
|
|
1284
|
-
// (round 2 finding 5): collapsing it means widening a register API that
|
|
1285
|
-
// other callers use, to save six syscalls on a path that has already read a
|
|
1286
|
-
// roadmap file and a transcript tail. The two resolutions also answer
|
|
1287
|
-
// different questions — the guard asks whether the cwd belongs to this
|
|
1288
|
-
// repository, this asks what the session's own tree is.
|
|
1289
|
-
const roots = provenance(
|
|
1290
|
-
workspaceRoot,
|
|
1291
|
-
claim.path,
|
|
1292
|
-
sessionRoot,
|
|
1293
|
-
str(payload['cwd'] as JsonValue | undefined),
|
|
1294
|
-
);
|
|
1295
|
-
// Round 4 finding 4: the line carried six path fields and not the one path
|
|
1296
|
-
// the only tree-dependent NUMBER on it came from. On a line with
|
|
1297
|
-
// `session_root !== workspace_root` and `open: 2`, a reader could not tell
|
|
1298
|
-
// whether the count came from the session copy (the fix working) or from the
|
|
1299
|
-
// reader's after a fallback (the defect still live) — the exact ambiguity the
|
|
1300
|
-
// other six fields exist to remove.
|
|
1301
|
-
roots['roadmap_path'] = roadmapFile;
|
|
1302
|
-
|
|
1303
|
-
// ── defer to the quality gate ────────────────────────────────────
|
|
1304
|
-
if (refusedThisTurn(workspaceRoot, sessionId, turnOrdinal)) {
|
|
1305
|
-
appendEvent(workspaceRoot, {
|
|
1306
|
-
event: 'deferred-quality-gate',
|
|
1307
|
-
run_id: runId,
|
|
1308
|
-
roadmap: slug,
|
|
1309
|
-
turn: turnOrdinal,
|
|
1310
|
-
at: new Date().toISOString(),
|
|
1311
|
-
...roots,
|
|
1312
|
-
});
|
|
1313
|
-
return EXIT_ALLOW;
|
|
1314
|
-
}
|
|
1315
|
-
|
|
1316
|
-
// ── state + duplicate-fire detection ─────────────────────────────
|
|
1317
|
-
//
|
|
1318
|
-
// A state file recorded against a DIFFERENT roadmap is not this run's state —
|
|
1319
|
-
// round 6 finding 2. The file is keyed on the session id alone and one session
|
|
1320
|
-
// may re-claim, so a halt stamped on roadmap A (never cleared: only `complete`
|
|
1321
|
-
// unlinks) was inherited by a later claim of roadmap B, which then emitted a
|
|
1322
|
-
// halt line naming B without ever engaging and reported A's iteration count
|
|
1323
|
-
// under B's slug. An absent `roadmap` field is trusted rather than discarded:
|
|
1324
|
-
// it means the state predates this field, and dropping a live budget on an
|
|
1325
|
-
// upgrade would be the worse error.
|
|
1326
|
-
// Keyed on (session, roadmap), with the legacy per-session file migrated once —
|
|
1327
|
-
// see `readRunState`. The in-file `roadmap` guard round 6 added is gone as a
|
|
1328
|
-
// BRANCH: it is now an identity, so a mismatch cannot reach this code at all,
|
|
1329
|
-
// and round 7 finding 3's "a mismatch nulls prev, so the next write overwrites
|
|
1330
|
-
// the other roadmap's halt stamp" has no path left.
|
|
1331
|
-
const mainState = readRunState(workspaceRoot, runId, slug);
|
|
1332
|
-
const stateFile = mainState.keyedFile;
|
|
1333
|
-
const prev = mainState.state;
|
|
1334
|
-
const state: RunState = prev ?? {
|
|
1335
|
-
started_at: new Date().toISOString(),
|
|
1336
|
-
iterations: 0,
|
|
1337
|
-
last_turn: -1,
|
|
1338
|
-
history: [],
|
|
1339
|
-
roadmap: slug,
|
|
1340
|
-
};
|
|
1341
|
-
// Stamped on an inherited state too, so the field fills in on first contact
|
|
1342
|
-
// rather than staying absent for the life of the run.
|
|
1343
|
-
state.roadmap = slug;
|
|
1344
|
-
// The reset the field's docblock promises. Reaching this line means the
|
|
1345
|
-
// roadmap read succeeded (the absent branch returns above), and the engage and
|
|
1346
|
-
// halt paths write THIS object back — so without the delete the counter is a
|
|
1347
|
-
// lifetime total and two separated absences reclaim a live budget.
|
|
1348
|
-
delete state.absent_fires;
|
|
1349
|
-
|
|
1350
|
-
const scan = scanOpenSteps(roadmapText);
|
|
1351
|
-
|
|
1352
|
-
// A duplicate stop fire repeats the SAME verdict without consuming an
|
|
1353
|
-
// iteration. It must repeat the BLOCK: this concern just blocked this
|
|
1354
|
-
// very stop, and an allow on the re-fire would end the reply the block
|
|
1355
|
-
// exists to continue. (An earlier draft allowed here — the smoke run
|
|
1356
|
-
// caught it ending the run it had re-engaged one event earlier.)
|
|
1357
|
-
if (isDuplicateFire(prev, turnOrdinal, scan.open, Date.now(), roadmapFile)) {
|
|
1358
|
-
process.stderr.write(_continuationText(slug, scan, state.iterations));
|
|
1359
|
-
return EXIT_BLOCK;
|
|
1360
|
-
}
|
|
1361
|
-
|
|
1362
|
-
// The source-change reset runs HERE, before the ladder reads the history —
|
|
1363
|
-
// round 5 finding 1. It used to sit inside the engage branch, which is after
|
|
1364
|
-
// `ladder()` and after the non-engage branch returns, so on the ONE fire where
|
|
1365
|
-
// the source document changes the stall test still compared counts from two
|
|
1366
|
-
// different files. Three parent-copy readings at `open: 4` followed by a
|
|
1367
|
-
// session copy that also reads 4 produced `halt-stall` on the parent's numbers
|
|
1368
|
-
// and declared a working run finished — the precise failure the field's own
|
|
1369
|
-
// docblock claims to prevent, defeated by where the guard sat.
|
|
1370
|
-
if (state.history_source !== roadmapFile) {
|
|
1371
|
-
state.history = [];
|
|
1372
|
-
state.history_source = roadmapFile;
|
|
1373
|
-
}
|
|
1374
|
-
|
|
1375
|
-
// Phase 5.4 — a dependency the run cannot obtain. Read from the transcript
|
|
1376
|
-
// TAIL only: an authentication failure from an hour ago that was then fixed
|
|
1377
|
-
// must not halt the run now. A read failure is `null` (fail-open), because a
|
|
1378
|
-
// detector that cannot read must not manufacture a halt.
|
|
1379
|
-
const unavailable = readUnavailableDependency(transcriptPath);
|
|
1380
|
-
|
|
1381
|
-
// Phase 6.6 — the stall signal, WRITTEN rather than re-derived. A consumer
|
|
1382
|
-
// asking "is this run still making progress" had to reconstruct it from the
|
|
1383
|
-
// history array and the window constant, so every reader could answer
|
|
1384
|
-
// differently. One producer, one definition.
|
|
1385
|
-
state.stall = stallSignal(state.history, STALL_WINDOW).level;
|
|
1386
|
-
|
|
1387
|
-
// 2.1 — repository drift, from the newest observation `roadmap:context`
|
|
1388
|
-
// recorded. No probe here: the fingerprint costs a `gh` call and this is the
|
|
1389
|
-
// Stop path. An unknown on either side is never a halt.
|
|
1390
|
-
const observed = readContextObservation(workspaceRoot)?.fingerprint ?? null;
|
|
1391
|
-
const premiseInvalidated = premiseMoved(state.context_fingerprint, observed);
|
|
1392
|
-
|
|
1393
|
-
const delivery = parseDeliveryState(state.delivery) ?? null;
|
|
1394
|
-
const action = ladder(
|
|
1395
|
-
state, scan.open, Date.now(),
|
|
1396
|
-
scan.blocked,
|
|
1397
|
-
undefined,
|
|
1398
|
-
unavailable,
|
|
1399
|
-
premiseInvalidated,
|
|
1400
|
-
delivery,
|
|
1401
|
-
);
|
|
1402
|
-
|
|
1403
|
-
if (action !== 'engage') {
|
|
1404
|
-
// A run that is ALREADY stamped emits nothing further — round 6 finding 6.
|
|
1405
|
-
// Once `halted` is set the state file is immortal for the session (only
|
|
1406
|
-
// `complete` unlinks it), so every later stop fire re-entered this branch
|
|
1407
|
-
// and appended another line with the same `run_id` and `iterations`: an
|
|
1408
|
-
// unbounded number of duplicate halt records in the ledger the acceptance
|
|
1409
|
-
// criteria's counts are derived from. The FIRST halt is the event; the rest
|
|
1410
|
-
// are the same fact re-stated.
|
|
1411
|
-
const alreadyStamped = prev?.halted !== undefined;
|
|
1412
|
-
// `blocked` can use neither `halted` (not in `HALT_ACTIONS`, by ADR-235) nor
|
|
1413
|
-
// a state field (the state is cleared below). The ledger survives both.
|
|
1414
|
-
const alreadyBlocked =
|
|
1415
|
-
action === 'blocked' && eventAlreadyLogged(workspaceRoot, runId, slug, 'blocked');
|
|
1416
|
-
if (!alreadyStamped && !alreadyBlocked) {
|
|
1417
|
-
const line = buildLedgerEvent(
|
|
1418
|
-
{ action, runId, slug, turn: turnOrdinal, iterations: state.iterations,
|
|
1419
|
-
open: scan.open, blocked: scan.blocked, delivery },
|
|
1420
|
-
RUN_TERMINAL_VOCABULARY_VERSION,
|
|
1421
|
-
new Date(),
|
|
1422
|
-
);
|
|
1423
|
-
appendEvent(workspaceRoot, { ...line, ...roots } as JsonObject);
|
|
1424
|
-
}
|
|
1425
|
-
if (action === 'complete') {
|
|
1426
|
-
// Only a COMPLETION clears the state, so a later run on the same
|
|
1427
|
-
// roadmap (post-merge follow-up, re-claim) starts a fresh budget.
|
|
1428
|
-
// A halt must NOT clear it — see `RunState.halted`.
|
|
1429
|
-
clearRunState(workspaceRoot, runId, stateFile, mainState.from === 'legacy');
|
|
1430
|
-
return EXIT_ALLOW;
|
|
1431
|
-
}
|
|
1432
|
-
if (action === 'blocked') {
|
|
1433
|
-
// CLEARED, like `complete`, and `runId` is why: it is
|
|
1434
|
-
// `deriveSessionKey(sessionId)` — a SESSION hash — so this same session
|
|
1435
|
-
// re-claiming this same roadmap reuses this same keyed file. Keeping the
|
|
1436
|
-
// state would hand the next run a spent budget, and since the ladder
|
|
1437
|
-
// tests `blocked` BEFORE the iteration cap, an unblocked roadmap could go
|
|
1438
|
-
// straight to `halt-max-iterations` without ever engaging.
|
|
1439
|
-
//
|
|
1440
|
-
// Safe only because the once-guard is the LEDGER: the next fire builds a
|
|
1441
|
-
// fresh state, reaches `blocked`, finds the line and stays silent.
|
|
1442
|
-
clearRunState(workspaceRoot, runId, stateFile, mainState.from === 'legacy');
|
|
1443
|
-
return EXIT_ALLOW;
|
|
1444
|
-
}
|
|
1445
|
-
// A halt is recorded in place. A failed write is fail-open in the safe
|
|
1446
|
-
// direction here: the rung already decided to allow this stop, and the
|
|
1447
|
-
// worst case of a lost stamp is the pre-fix behaviour, never a block.
|
|
1448
|
-
if (!state.halted) {
|
|
1449
|
-
state.halted = action;
|
|
1450
|
-
writeState(stateFile, state);
|
|
1451
|
-
}
|
|
1452
|
-
return EXIT_ALLOW;
|
|
1453
|
-
}
|
|
1454
|
-
|
|
1455
|
-
state.iterations += 1;
|
|
1456
|
-
state.last_turn = turnOrdinal;
|
|
1457
|
-
// Recorded ONCE — the premise this run engaged under. See the field's docblock.
|
|
1458
|
-
if (state.context_fingerprint === undefined && observed !== null) {
|
|
1459
|
-
state.context_fingerprint = observed;
|
|
1460
|
-
}
|
|
1461
|
-
state.history.push(scan.open);
|
|
1462
|
-
state.last_engaged_at = new Date().toISOString();
|
|
1463
|
-
if (!writeState(stateFile, state)) {
|
|
1464
|
-
// If the counter cannot persist, the ladder cannot bound the loop —
|
|
1465
|
-
// so the loop must not run. Allowing here is the fail-open posture
|
|
1466
|
-
// applied to the ONE branch where a lost write means an unbounded
|
|
1467
|
-
// re-engagement rather than a missed one.
|
|
1468
|
-
return EXIT_ALLOW;
|
|
1469
|
-
}
|
|
1470
|
-
|
|
1471
|
-
appendEvent(workspaceRoot, {
|
|
1472
|
-
event: 'engage',
|
|
1473
|
-
run_id: runId,
|
|
1474
|
-
roadmap: slug,
|
|
1475
|
-
turn: turnOrdinal,
|
|
1476
|
-
iteration: state.iterations,
|
|
1477
|
-
open: scan.open,
|
|
1478
|
-
blocked: scan.blocked,
|
|
1479
|
-
at: new Date().toISOString(),
|
|
1480
|
-
...roots,
|
|
1481
|
-
});
|
|
1482
|
-
|
|
1483
|
-
process.stderr.write(_continuationText(slug, scan, state.iterations));
|
|
1484
|
-
return EXIT_BLOCK;
|
|
1485
|
-
}
|
|
1486
|
-
|
|
1487
|
-
function _continuationText(slug: string, scan: ScanResult, iteration: number): string {
|
|
1488
|
-
const stepLine = scan.next
|
|
1489
|
-
? `Next step: ${scan.next.text}${renderVerifyLine(scan.next.verify)}`
|
|
1490
|
-
: 'Next step: (first open checkbox in the roadmap)';
|
|
1491
|
-
return (
|
|
1492
|
-
`run-continuation: the contracted roadmap \`${slug}\` has ${scan.open} open ` +
|
|
1493
|
-
`step${scan.open === 1 ? '' : 's'}` +
|
|
1494
|
-
(scan.blocked > 0 ? ` (+${scan.blocked} blocked-by, not yours this run)` : '') +
|
|
1495
|
-
` — iteration ${iteration}/${MAX_ITERATIONS}.\n` +
|
|
1496
|
-
`${stepLine}\n` +
|
|
1497
|
-
'Continue with this step now: do the work, run its verify line, flip ' +
|
|
1498
|
-
'the box, then end the turn. Escalate instead of continuing ONLY for a ' +
|
|
1499
|
-
'locked decision class (high_impact / user_required) or a halt your ' +
|
|
1500
|
-
'contract names.\n'
|
|
1501
|
-
);
|
|
1502
|
-
}
|
|
1503
|
-
|
|
1504
|
-
// Bundle-safety: never auto-run when inlined into an esbuild bundle.
|
|
1505
|
-
declare const __AGENT_CONFIG_BUNDLE__: boolean | undefined;
|
|
1506
|
-
function _isCliEntry(): boolean {
|
|
1507
|
-
if (typeof __AGENT_CONFIG_BUNDLE__ !== 'undefined' && __AGENT_CONFIG_BUNDLE__) {
|
|
1508
|
-
return false;
|
|
1509
|
-
}
|
|
1510
|
-
if (process.argv[1] === undefined) return false;
|
|
1511
|
-
const argvUrl = pathToFileURL(path.resolve(process.argv[1])).href;
|
|
1512
|
-
if (import.meta.url === argvUrl) return true;
|
|
1513
|
-
try {
|
|
1514
|
-
const here = fs.realpathSync(fileURLToPath(import.meta.url));
|
|
1515
|
-
const argv = fs.realpathSync(path.resolve(process.argv[1]));
|
|
1516
|
-
return here === argv;
|
|
1517
|
-
} catch {
|
|
1518
|
-
return false;
|
|
1519
|
-
}
|
|
1520
|
-
}
|
|
1521
|
-
|
|
1522
|
-
if (_isCliEntry()) {
|
|
1523
|
-
process.exit(main());
|
|
1524
|
-
}
|