@event4u/agent-config 14.22.0 → 15.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 +1 -1
- package/CHANGELOG.md +333 -356
- package/README.md +1 -1
- package/dist/agent-src/commands/agent-handoff.md +8 -7
- package/dist/agent-src/commands/agents/init.md +1 -1
- package/dist/agent-src/commands/agents/user/accept.md +4 -4
- package/dist/agent-src/commands/agents/user/delete.md +2 -2
- package/dist/agent-src/commands/agents/user/init.md +3 -3
- package/dist/agent-src/commands/agents/user/review.md +3 -3
- package/dist/agent-src/commands/agents/user/show.md +3 -3
- package/dist/agent-src/commands/agents/user/update.md +2 -2
- package/dist/agent-src/commands/agents/user.md +6 -6
- package/dist/agent-src/commands/analytics/prune.md +1 -1
- package/dist/agent-src/commands/analytics/show.md +2 -2
- package/dist/agent-src/commands/analyze/decision.md +2 -2
- package/dist/agent-src/commands/analyze/inbox.md +5 -5
- package/dist/agent-src/commands/analyze/incident.md +3 -3
- package/dist/agent-src/commands/analyze/near-miss.md +3 -3
- package/dist/agent-src/commands/analyze/postmortem.md +4 -4
- package/dist/agent-src/commands/analyze/premortem.md +2 -2
- package/dist/agent-src/commands/analyze.md +2 -2
- package/dist/agent-src/commands/bug/fix.md +1 -1
- package/dist/agent-src/commands/bug/investigate.md +2 -2
- package/dist/agent-src/commands/cost/profile.md +3 -3
- package/dist/agent-src/commands/design.md +1 -1
- package/dist/agent-src/commands/feature/explore.md +1 -1
- package/dist/agent-src/commands/feature/plan.md +2 -2
- package/dist/agent-src/commands/feature/roadmap.md +2 -2
- package/dist/agent-src/commands/ghostwriter/fetch.md +4 -4
- package/dist/agent-src/commands/ghostwriter/list.md +1 -1
- package/dist/agent-src/commands/ghostwriter/show.md +1 -1
- package/dist/agent-src/commands/ghostwriter/write.md +9 -9
- package/dist/agent-src/commands/humanize.md +6 -6
- package/dist/agent-src/commands/jira-ticket.md +1 -1
- package/dist/agent-src/commands/judge/solo.md +1 -1
- package/dist/agent-src/commands/judge.md +1 -1
- package/dist/agent-src/commands/knowledge/cross-repo.md +1 -1
- package/dist/agent-src/commands/knowledge/forget.md +1 -1
- package/dist/agent-src/commands/knowledge/ingest.md +2 -2
- package/dist/agent-src/commands/knowledge/list.md +1 -1
- package/dist/agent-src/commands/memory/add.md +3 -3
- package/dist/agent-src/commands/memory/load.md +4 -4
- package/dist/agent-src/commands/memory/mine-session.md +1 -1
- package/dist/agent-src/commands/memory/promote.md +4 -4
- package/dist/agent-src/commands/memory/propose.md +2 -2
- package/dist/agent-src/commands/mode.md +5 -5
- package/dist/agent-src/commands/post-as/ghostwriter.md +3 -3
- package/dist/agent-src/commands/post-as/me.md +7 -7
- package/dist/agent-src/commands/pr/create.md +1 -1
- package/dist/agent-src/commands/pr/merge.md +48 -39
- package/dist/agent-src/commands/profile/activate.md +1 -1
- package/dist/agent-src/commands/profile/show.md +1 -1
- package/dist/agent-src/commands/research/deep.md +2 -2
- package/dist/agent-src/commands/research/report.md +2 -2
- package/dist/agent-src/commands/review/changes.md +1 -1
- package/dist/agent-src/commands/review/routing.md +1 -1
- package/dist/agent-src/commands/roadmap/create.md +1 -1
- package/dist/agent-src/commands/roadmap/materialize.md +2 -2
- package/dist/agent-src/commands/roadmap/next.md +9 -1
- package/dist/agent-src/commands/roadmap/process-full.md +2 -2
- package/dist/agent-src/commands/security-audit-config.md +3 -3
- package/dist/agent-src/commands/skill/preview.md +1 -1
- package/dist/agent-src/commands/skills/discover.md +1 -1
- package/dist/agent-src/commands/sync/agent-settings.md +2 -2
- package/dist/agent-src/commands/sync/gitignore/fix.md +1 -1
- package/dist/agent-src/commands/tests/create.md +1 -1
- package/dist/agent-src/commands/tests/e2e-heal.md +1 -1
- package/dist/agent-src/commands/tests/e2e-plan.md +1 -1
- package/dist/agent-src/contexts/authority/kernel-rule-edits.md +6 -6
- package/dist/agent-src/contexts/communication/rules-auto/slash-command-routing-policy-mechanics.md +1 -2
- package/dist/agent-src/contexts/communication/rules-auto/think-before-action-mechanics.md +2 -2
- package/dist/agent-src/contexts/communication/rules-auto/token-efficiency-mechanics.md +88 -1
- package/dist/agent-src/contexts/communication/rules-auto/user-interaction-mechanics.md +1 -1
- package/dist/agent-src/contexts/contracts/frugality-charter.md +1 -1
- package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +1 -1
- package/dist/agent-src/contexts/execution/auto-orchestration-activation.md +1 -1
- package/dist/agent-src/contexts/execution/autonomy-mechanics.md +13 -1
- package/dist/agent-src/contexts/execution/cheap-question-mechanics.md +1 -1
- package/dist/agent-src/contexts/execution/contract-decision-sheet.md +3 -3
- package/dist/agent-src/contexts/execution/mandated-lines.md +1 -1
- package/dist/agent-src/contexts/execution/non-interactive-contract.md +1 -1
- package/dist/agent-src/contexts/execution/orchestration-telemetry.md +1 -1
- package/dist/agent-src/contexts/execution/plan-confidence-gate.md +5 -5
- package/dist/agent-src/contexts/execution/roadmap-execution-contract.md +1 -1
- package/dist/agent-src/contexts/execution/subagent-modes-detail.md +1 -1
- package/dist/agent-src/contexts/execution/subagent-routing.md +2 -2
- package/dist/agent-src/contexts/execution/subagent-spawn-contract.md +1 -1
- package/dist/agent-src/contexts/execution/user-memory-channels.md +3 -3
- package/dist/agent-src/contexts/execution/verification-mechanics.md +1 -1
- package/dist/agent-src/contexts/judges/persona-voice-rubric.md +2 -2
- package/dist/agent-src/guidelines/abstraction-thresholds.md +88 -0
- package/dist/agent-src/guidelines/agent-infra/5w2h-analysis.md +260 -0
- package/dist/agent-src/guidelines/agent-infra/active-remediation-mechanics.md +99 -0
- package/dist/agent-src/guidelines/agent-infra/agent-interaction-and-decision-quality.md +325 -0
- package/dist/agent-src/guidelines/agent-infra/api-cost-levers.md +177 -0
- package/dist/agent-src/guidelines/agent-infra/artifact-drafting-protocol-mechanics.md +222 -0
- package/dist/agent-src/guidelines/agent-infra/ask-when-uncertain-demos.md +134 -0
- package/dist/agent-src/guidelines/agent-infra/asking-and-brevity-examples.md +198 -0
- package/dist/agent-src/guidelines/agent-infra/break-glass-usage.md +113 -0
- package/dist/agent-src/guidelines/agent-infra/carve-out-predicates.md +17 -0
- package/dist/agent-src/guidelines/agent-infra/comparison-matrix.md +179 -0
- package/dist/agent-src/guidelines/agent-infra/context-hygiene-mechanics.md +165 -0
- package/dist/agent-src/guidelines/agent-infra/corpus-grounding-authoring.md +91 -0
- package/dist/agent-src/guidelines/agent-infra/critical-thinking.md +156 -0
- package/dist/agent-src/guidelines/agent-infra/cross-source-consistency-mechanics.md +109 -0
- package/dist/agent-src/guidelines/agent-infra/developer-judgment.md +82 -0
- package/dist/agent-src/guidelines/agent-infra/direct-answers-demos.md +142 -0
- package/dist/agent-src/guidelines/agent-infra/domain-adoption-gates.md +112 -0
- package/dist/agent-src/guidelines/agent-infra/domain-eval-anti-pattern.md +53 -0
- package/dist/agent-src/guidelines/agent-infra/domain-pack-architecture.md +56 -0
- package/dist/agent-src/guidelines/agent-infra/downstream-changes-mechanics.md +91 -0
- package/dist/agent-src/guidelines/agent-infra/emphasis-budget.md +45 -0
- package/dist/agent-src/guidelines/agent-infra/engineering-memory-data-format.md +210 -0
- package/dist/agent-src/guidelines/agent-infra/evaluator-independence-mechanics.md +92 -0
- package/dist/agent-src/guidelines/agent-infra/existence-question-verdicts.md +80 -0
- package/dist/agent-src/guidelines/agent-infra/failure-signatures.md +70 -0
- package/dist/agent-src/guidelines/agent-infra/false-green.md +233 -0
- package/dist/agent-src/guidelines/agent-infra/first-principles.md +192 -0
- package/dist/agent-src/guidelines/agent-infra/framework-neutrality-patterns.md +66 -0
- package/dist/agent-src/guidelines/agent-infra/frontier-reasoning-operating-profile.md +169 -0
- package/dist/agent-src/guidelines/agent-infra/gate-authoring.md +177 -0
- package/dist/agent-src/guidelines/agent-infra/guarded-baseline.md +39 -0
- package/dist/agent-src/guidelines/agent-infra/installed-tools-manifest.md +142 -0
- package/dist/agent-src/guidelines/agent-infra/inversion-thinking.md +388 -0
- package/dist/agent-src/guidelines/agent-infra/ios-simulator-guide.md +378 -0
- package/dist/agent-src/guidelines/agent-infra/language-and-tone-examples.md +141 -0
- package/dist/agent-src/guidelines/agent-infra/layered-settings.md +317 -0
- package/dist/agent-src/guidelines/agent-infra/linked-projects-onboarding-gate.md +80 -0
- package/dist/agent-src/guidelines/agent-infra/mcp-request-signing.md +197 -0
- package/dist/agent-src/guidelines/agent-infra/memory-access.md +149 -0
- package/dist/agent-src/guidelines/agent-infra/mental-models.md +314 -0
- package/dist/agent-src/guidelines/agent-infra/minimal-safe-diff-mechanics.md +241 -0
- package/dist/agent-src/guidelines/agent-infra/missing-tool-handling.md +66 -0
- package/dist/agent-src/guidelines/agent-infra/model-recommendation.md +101 -0
- package/dist/agent-src/guidelines/agent-infra/naming.md +69 -0
- package/dist/agent-src/guidelines/agent-infra/notes-horizon-mechanics.md +90 -0
- package/dist/agent-src/guidelines/agent-infra/output-patterns.md +117 -0
- package/dist/agent-src/guidelines/agent-infra/recurring-criticism-mechanics.md +96 -0
- package/dist/agent-src/guidelines/agent-infra/reuse-verdict-mechanics.md +71 -0
- package/dist/agent-src/guidelines/agent-infra/review-routing-data-format.md +143 -0
- package/dist/agent-src/guidelines/agent-infra/roadmap-deferred-resolution-provenance.md +54 -0
- package/dist/agent-src/guidelines/agent-infra/roadmap-progress-mechanics.md +274 -0
- package/dist/agent-src/guidelines/agent-infra/role-contracts.md +209 -0
- package/dist/agent-src/guidelines/agent-infra/role-mode-router.md +89 -0
- package/dist/agent-src/guidelines/agent-infra/rule-body-migration-inventory.md +241 -0
- package/dist/agent-src/guidelines/agent-infra/rule-type-governance.md +73 -0
- package/dist/agent-src/guidelines/agent-infra/runtime-layer.md +89 -0
- package/dist/agent-src/guidelines/agent-infra/scqa-framework.md +526 -0
- package/dist/agent-src/guidelines/agent-infra/security-lint-containment.md +121 -0
- package/dist/agent-src/guidelines/agent-infra/self-improvement-pipeline.md +134 -0
- package/dist/agent-src/guidelines/agent-infra/simplicity-and-goal-demos.md +211 -0
- package/dist/agent-src/guidelines/agent-infra/six-hats.md +353 -0
- package/dist/agent-src/guidelines/agent-infra/size-and-scope.md +229 -0
- package/dist/agent-src/guidelines/agent-infra/skill-quality-checklist.md +157 -0
- package/dist/agent-src/guidelines/agent-infra/source-confidentiality-mechanics.md +109 -0
- package/dist/agent-src/guidelines/agent-infra/symptom-driven-harvest-loop.md +104 -0
- package/dist/agent-src/guidelines/agent-infra/systems-thinking.md +220 -0
- package/dist/agent-src/guidelines/agent-infra/tool-description-as-policy.md +35 -0
- package/dist/agent-src/guidelines/agent-infra/tool-integration.md +73 -0
- package/dist/agent-src/guidelines/agent-infra/traceability-field-mechanics.md +50 -0
- package/dist/agent-src/guidelines/agent-infra/untrusted-input-spotlighting.md +166 -0
- package/dist/agent-src/guidelines/agent-infra/verify-before-complete-demos.md +128 -0
- package/dist/agent-src/guidelines/augment-portability-patterns.md +70 -0
- package/dist/agent-src/guidelines/code-clarity.md +350 -0
- package/dist/agent-src/guidelines/component-oriented-and-oop-development.md +189 -0
- package/dist/agent-src/guidelines/cross-role-handoff.md +127 -0
- package/dist/agent-src/guidelines/design-antipatterns-triggers.json +18 -0
- package/dist/agent-src/guidelines/design-antipatterns.md +327 -0
- package/dist/agent-src/guidelines/design-asset-discipline.md +38 -0
- package/dist/agent-src/guidelines/design-canon.md +63 -0
- package/dist/agent-src/guidelines/design-fidelity-mechanics.md +293 -0
- package/dist/agent-src/guidelines/design-fidelity-routing.md +78 -0
- package/dist/agent-src/guidelines/design-handover-extraction.md +117 -0
- package/dist/agent-src/guidelines/design-modes.md +143 -0
- package/dist/agent-src/guidelines/design-reconciliation.md +172 -0
- package/dist/agent-src/guidelines/docs/readme-size-and-splitting.md +209 -0
- package/dist/agent-src/guidelines/e2e/playwright.md +363 -0
- package/dist/agent-src/guidelines/gtm-handoff.md +114 -0
- package/dist/agent-src/guidelines/monorepo-antipatterns.md +141 -0
- package/dist/agent-src/guidelines/php/api-design.md +115 -0
- package/dist/agent-src/guidelines/php/artisan-commands.md +81 -0
- package/dist/agent-src/guidelines/php/blade-ui.md +78 -0
- package/dist/agent-src/guidelines/php/controllers.md +90 -0
- package/dist/agent-src/guidelines/php/database.md +194 -0
- package/dist/agent-src/guidelines/php/eloquent.md +208 -0
- package/dist/agent-src/guidelines/php/flux.md +80 -0
- package/dist/agent-src/guidelines/php/general.md +207 -0
- package/dist/agent-src/guidelines/php/git.md +164 -0
- package/dist/agent-src/guidelines/php/jobs.md +111 -0
- package/dist/agent-src/guidelines/php/livewire.md +71 -0
- package/dist/agent-src/guidelines/php/logging.md +79 -0
- package/dist/agent-src/guidelines/php/naming.md +89 -0
- package/dist/agent-src/guidelines/php/patterns/dependency-injection.md +57 -0
- package/dist/agent-src/guidelines/php/patterns/dtos.md +199 -0
- package/dist/agent-src/guidelines/php/patterns/events.md +67 -0
- package/dist/agent-src/guidelines/php/patterns/factory.md +53 -0
- package/dist/agent-src/guidelines/php/patterns/pipelines.md +66 -0
- package/dist/agent-src/guidelines/php/patterns/policies.md +66 -0
- package/dist/agent-src/guidelines/php/patterns/repositories.md +122 -0
- package/dist/agent-src/guidelines/php/patterns/service-layer.md +64 -0
- package/dist/agent-src/guidelines/php/patterns/strategy.md +247 -0
- package/dist/agent-src/guidelines/php/patterns.md +28 -0
- package/dist/agent-src/guidelines/php/performance.md +92 -0
- package/dist/agent-src/guidelines/php/php-coding-patterns.md +80 -0
- package/dist/agent-src/guidelines/php/resources.md +100 -0
- package/dist/agent-src/guidelines/php/security.md +110 -0
- package/dist/agent-src/guidelines/php/sql.md +97 -0
- package/dist/agent-src/guidelines/php/validations.md +119 -0
- package/dist/agent-src/guidelines/php/websocket.md +100 -0
- package/dist/agent-src/guidelines/prompt-templates.md +189 -0
- package/dist/agent-src/guidelines/redundancy-taxonomy.md +208 -0
- package/dist/agent-src/guidelines/wing4-handoff.md +127 -0
- package/dist/agent-src/personas/README.md +1 -1
- package/dist/agent-src/personas/_template-specialist/persona.md +1 -1
- package/dist/agent-src/personas/product-owner.md +1 -1
- package/dist/agent-src/rules/active-remediation.md +1 -1
- package/dist/agent-src/rules/architecture.md +2 -2
- package/dist/agent-src/rules/artifact-drafting-protocol.md +1 -1
- package/dist/agent-src/rules/ask-when-uncertain.md +2 -2
- package/dist/agent-src/rules/brand-source-of-truth.md +9 -7
- package/dist/agent-src/rules/code-comment-discipline.md +2 -2
- package/dist/agent-src/rules/code-provenance.md +1 -1
- package/dist/agent-src/rules/content-quoting-floor.md +1 -1
- package/dist/agent-src/rules/context-hygiene.md +5 -5
- package/dist/agent-src/rules/cross-source-consistency.md +1 -1
- package/dist/agent-src/rules/design-fidelity.md +36 -46
- package/dist/agent-src/rules/direct-answers.md +2 -2
- package/dist/agent-src/rules/domain-adoption-policy.md +1 -1
- package/dist/agent-src/rules/evaluator-independence.md +1 -1
- package/dist/agent-src/rules/framework-neutrality-in-generic-skills.md +1 -1
- package/dist/agent-src/rules/icon-consistency.md +5 -1
- package/dist/agent-src/rules/improve-before-implement.md +1 -1
- package/dist/agent-src/rules/language-and-tone.md +3 -3
- package/dist/agent-src/rules/minimal-safe-diff.md +1 -1
- package/dist/agent-src/rules/notes-first-reasoning.md +36 -25
- package/dist/agent-src/rules/recurring-criticism.md +1 -1
- package/dist/agent-src/rules/roadmap-progress-sync.md +1 -1
- package/dist/agent-src/rules/role-mode-adherence.md +2 -2
- package/dist/agent-src/rules/security-sensitive-stop.md +1 -1
- package/dist/agent-src/rules/size-enforcement.md +1 -1
- package/dist/agent-src/rules/source-confidentiality.md +2 -2
- package/dist/agent-src/rules/think-before-action.md +1 -1
- package/dist/agent-src/rules/token-efficiency.md +7 -5
- package/dist/agent-src/rules/ui-audit-gate.md +3 -2
- package/dist/agent-src/rules/untrusted-input-defense.md +3 -3
- package/dist/agent-src/scripts/archive_completed_roadmaps.ts +106 -4
- package/dist/agent-src/skills/activation-design/SKILL.md +2 -2
- package/dist/agent-src/skills/adr-create/SKILL.md +5 -5
- package/dist/agent-src/skills/ai-council/SKILL.md +1 -1
- package/dist/agent-src/skills/ai-council/references/advanced-modes.md +1 -1
- package/dist/agent-src/skills/blade-ui/SKILL.md +1 -1
- package/dist/agent-src/skills/blast-radius-analyzer/SKILL.md +1 -1
- package/dist/agent-src/skills/brand-to-tokens/SKILL.md +24 -3
- package/dist/agent-src/skills/bug-analyzer/SKILL.md +1 -1
- package/dist/agent-src/skills/build-buy-partner/SKILL.md +1 -1
- package/dist/agent-src/skills/churn-prevention/SKILL.md +2 -2
- package/dist/agent-src/skills/code-intelligence/SKILL.md +57 -1
- package/dist/agent-src/skills/code-refactoring/SKILL.md +3 -3
- package/dist/agent-src/skills/code-review/SKILL.md +3 -3
- package/dist/agent-src/skills/command-writing/SKILL.md +3 -3
- package/dist/agent-src/skills/comp-banding/SKILL.md +1 -1
- package/dist/agent-src/skills/competitive-moat-analysis/SKILL.md +1 -1
- package/dist/agent-src/skills/competitive-positioning/SKILL.md +2 -2
- package/dist/agent-src/skills/complexity-first-planning/SKILL.md +1 -1
- package/dist/agent-src/skills/condense-memory/SKILL.md +1 -1
- package/dist/agent-src/skills/content-funnel-design/SKILL.md +2 -2
- package/dist/agent-src/skills/contracts-cognition/SKILL.md +1 -1
- package/dist/agent-src/skills/copilot-agents-optimization/SKILL.md +2 -2
- package/dist/agent-src/skills/corpus-grounding/SKILL.md +2 -2
- package/dist/agent-src/skills/customer-research/SKILL.md +2 -2
- package/dist/agent-src/skills/dashboard-design/SKILL.md +1 -1
- package/dist/agent-src/skills/data-handling-judgment/SKILL.md +1 -1
- package/dist/agent-src/skills/deal-qualification-meddic/SKILL.md +2 -2
- package/dist/agent-src/skills/decision-record/SKILL.md +3 -3
- package/dist/agent-src/skills/decision-review/SKILL.md +8 -8
- package/dist/agent-src/skills/deep-reading-analyst/SKILL.md +22 -22
- package/dist/agent-src/skills/design-intelligence/SKILL.md +4 -4
- package/dist/agent-src/skills/design-intelligence/references/context-and-registers.md +2 -2
- package/dist/agent-src/skills/design-review/SKILL.md +4 -4
- package/dist/agent-src/skills/design-system-capture/references/design-system-json.md +20 -1
- package/dist/agent-src/skills/design-tokens/SKILL.md +17 -2
- package/dist/agent-src/skills/design-variations/SKILL.md +2 -2
- package/dist/agent-src/skills/developer-like-execution/SKILL.md +2 -2
- package/dist/agent-src/skills/discovery-interview/SKILL.md +2 -2
- package/dist/agent-src/skills/doc-coauthoring/SKILL.md +3 -3
- package/dist/agent-src/skills/editorial-calendar/SKILL.md +2 -2
- package/dist/agent-src/skills/existing-ui-audit/SKILL.md +44 -1
- package/dist/agent-src/skills/existing-ui-audit/references/anti-slop-cross-reference.md +2 -2
- package/dist/agent-src/skills/expansion-playbook/SKILL.md +2 -2
- package/dist/agent-src/skills/experiment-loop/SKILL.md +1 -1
- package/dist/agent-src/skills/experiment-loop/references/protocol.md +1 -1
- package/dist/agent-src/skills/fe-design/SKILL.md +3 -3
- package/dist/agent-src/skills/fe-design/references/design-patterns.md +1 -1
- package/dist/agent-src/skills/fe-design/references/design-read-and-memory.md +3 -3
- package/dist/agent-src/skills/fe-design/references/source-led-port.md +1 -1
- package/dist/agent-src/skills/feature-planning/SKILL.md +1 -1
- package/dist/agent-src/skills/flux/SKILL.md +1 -1
- package/dist/agent-src/skills/forecast-accuracy/SKILL.md +2 -2
- package/dist/agent-src/skills/forecasting/SKILL.md +2 -2
- package/dist/agent-src/skills/fundraising-narrative/SKILL.md +2 -2
- package/dist/agent-src/skills/funnel-analysis/SKILL.md +2 -2
- package/dist/agent-src/skills/git-workflow/references/push-closes-its-loop.md +9 -0
- package/dist/agent-src/skills/gtm-launch/SKILL.md +2 -2
- package/dist/agent-src/skills/hiring-loop-design/SKILL.md +1 -1
- package/dist/agent-src/skills/html-deck/SKILL.md +5 -5
- package/dist/agent-src/skills/humanizer/SKILL.md +1 -1
- package/dist/agent-src/skills/humanizer/data/patterns.md +1 -1
- package/dist/agent-src/skills/iconography/SKILL.md +3 -3
- package/dist/agent-src/skills/judge-synthesis/SKILL.md +1 -1
- package/dist/agent-src/skills/laravel-api-endpoint/SKILL.md +2 -2
- package/dist/agent-src/skills/launch-readiness/SKILL.md +3 -3
- package/dist/agent-src/skills/learning-to-rule-or-skill/SKILL.md +6 -6
- package/dist/agent-src/skills/livewire/SKILL.md +1 -1
- package/dist/agent-src/skills/market-entry-analysis/SKILL.md +1 -1
- package/dist/agent-src/skills/mcp-builder/SKILL.md +1 -1
- package/dist/agent-src/skills/memory-consolidation/SKILL.md +3 -3
- package/dist/agent-src/skills/messaging-architecture/SKILL.md +2 -2
- package/dist/agent-src/skills/monorepo-workspace/SKILL.md +1 -1
- package/dist/agent-src/skills/onboarding-design/SKILL.md +2 -2
- package/dist/agent-src/skills/onboarding-program/SKILL.md +1 -1
- package/dist/agent-src/skills/one-on-one-cadence/SKILL.md +1 -1
- package/dist/agent-src/skills/org-design/SKILL.md +1 -1
- package/dist/agent-src/skills/overbuild-review-lens/SKILL.md +3 -3
- package/dist/agent-src/skills/override-management/SKILL.md +1 -1
- package/dist/agent-src/skills/perf-feedback-craft/SKILL.md +1 -1
- package/dist/agent-src/skills/persona-writing/SKILL.md +1 -1
- package/dist/agent-src/skills/php-coder/SKILL.md +1 -1
- package/dist/agent-src/skills/pipeline-strategy/SKILL.md +2 -2
- package/dist/agent-src/skills/playwright-testing/SKILL.md +3 -3
- package/dist/agent-src/skills/po-discovery/SKILL.md +1 -1
- package/dist/agent-src/skills/positioning-strategy/SKILL.md +2 -2
- package/dist/agent-src/skills/privacy-review/SKILL.md +1 -1
- package/dist/agent-src/skills/prompt-optimizer/SKILL.md +3 -3
- package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +1 -1
- package/dist/agent-src/skills/reasoning-orchestrator/SKILL.md +2 -2
- 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 -2
- package/dist/agent-src/skills/retention-loops/SKILL.md +2 -2
- package/dist/agent-src/skills/review-routing/SKILL.md +2 -2
- package/dist/agent-src/skills/roadmap-management/SKILL.md +1 -1
- package/dist/agent-src/skills/roadmap-management/references/archival.md +1 -1
- package/dist/agent-src/skills/roadmap-writing/SKILL.md +5 -5
- package/dist/agent-src/skills/rule-writing/SKILL.md +6 -6
- package/dist/agent-src/skills/runway-cognition/SKILL.md +2 -2
- package/dist/agent-src/skills/scenario-modeling/SKILL.md +2 -2
- package/dist/agent-src/skills/skill-writing/SKILL.md +2 -2
- package/dist/agent-src/skills/skill-writing/references/procedure.md +1 -1
- package/dist/agent-src/skills/skill-writing/references/section-patterns.md +3 -3
- package/dist/agent-src/skills/spreadsheet-authoring/SKILL.md +1 -1
- package/dist/agent-src/skills/stakeholder-tradeoff/SKILL.md +3 -3
- package/dist/agent-src/skills/subagent-orchestration/SKILL.md +1 -1
- package/dist/agent-src/skills/supply-chain-intake/SKILL.md +1 -1
- package/dist/agent-src/skills/systematic-debugging/SKILL.md +2 -2
- package/dist/agent-src/skills/tailwind-engineer/SKILL.md +60 -4
- package/dist/agent-src/skills/throughput-vs-morale-tradeoff/SKILL.md +1 -1
- package/dist/agent-src/skills/token-optimizer/SKILL.md +1 -1
- package/dist/agent-src/skills/typography-system/SKILL.md +2 -2
- package/dist/agent-src/skills/ui-component-architect/SKILL.md +28 -8
- package/dist/agent-src/skills/unit-economics-modeling/SKILL.md +2 -2
- package/dist/agent-src/skills/upstream-contribute/SKILL.md +1 -1
- package/dist/agent-src/skills/validate-feature-fit/SKILL.md +2 -2
- package/dist/agent-src/skills/verify-repair-loop/SKILL.md +2 -2
- package/dist/agent-src/skills/vision-articulation/SKILL.md +1 -1
- package/dist/agent-src/skills/voc-extract/SKILL.md +2 -2
- package/dist/agent-src/skills/voice-and-tone-design/SKILL.md +2 -2
- package/dist/agent-src/skills/wireframe/SKILL.md +1 -1
- package/dist/agent-src/skills/workspace-link/SKILL.md +1 -1
- package/dist/agent-src/templates/agent-settings.md +6 -6
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/contexts/knowledge-pages.md +2 -3
- package/dist/agent-src/templates/copilot-instructions.md +1 -1
- package/dist/agent-src/templates/roadmaps.md +1 -1
- package/dist/agent-src/templates/scripts/README.md +2 -2
- package/dist/agent-src/user-types/_template/user-type.md +1 -1
- package/dist/cli/registry.js +1 -1
- package/dist/cli-delegate/archive_completed_roadmaps.js +52 -4
- package/dist/cli-delegate/check_update_banner.js +12 -1
- package/dist/cli-delegate/{chunk-TGIPZBCW.js → chunk-2KKXJW25.js} +22 -8
- package/dist/cli-delegate/{chunk-NLP54U3J.js → chunk-2XY7ILBT.js} +13 -1
- package/dist/cli-delegate/{chunk-4FS4WRXP.js → chunk-3FKR64R5.js} +34 -6
- package/dist/cli-delegate/{chunk-J3RFNKG4.js → chunk-55ACLDUE.js} +2 -2
- package/dist/cli-delegate/{chunk-PKOBQADP.js → chunk-57PN4GYJ.js} +1 -1
- package/dist/cli-delegate/{chunk-BIXEDQPZ.js → chunk-AK6HODNQ.js} +4 -4
- package/dist/cli-delegate/{chunk-2FTMENJL.js → chunk-GYC3VRYN.js} +1 -1
- package/dist/cli-delegate/{chunk-LWTYTX6F.js → chunk-HZ52BRGG.js} +24 -18
- package/dist/cli-delegate/{chunk-6RJA2F5A.js → chunk-IVBPRCQO.js} +1 -1
- package/dist/cli-delegate/{chunk-I6RHFQEG.js → chunk-YUM5KURG.js} +17 -1
- package/dist/cli-delegate/cmd_analyze_session.js +1 -1
- package/dist/cli-delegate/cmd_brand_status.js +1 -1
- package/dist/cli-delegate/cmd_conformance.js +3 -3
- package/dist/cli-delegate/cmd_doctor.js +3 -3
- package/dist/cli-delegate/cmd_explain.js +2 -2
- package/dist/cli-delegate/cmd_export.js +4 -4
- package/dist/cli-delegate/cmd_handoff.js +24 -16
- package/dist/cli-delegate/cmd_mcp_available.js +1 -1
- package/dist/cli-delegate/cmd_memory_get.js +1 -1
- package/dist/cli-delegate/cmd_migrate.js +2 -2
- package/dist/cli-delegate/cmd_packs_active.js +2 -2
- package/dist/cli-delegate/cmd_prune.js +4 -4
- package/dist/cli-delegate/cmd_route_audit.js +3 -3
- package/dist/cli-delegate/cmd_route_explain.js +1 -1
- package/dist/cli-delegate/cmd_session_recycle.js +4 -14
- package/dist/cli-delegate/cmd_settings_get.js +15 -9
- package/dist/cli-delegate/cmd_settings_migrate.js +4 -4
- package/dist/cli-delegate/cmd_settings_set.js +41 -11
- package/dist/cli-delegate/cmd_sync.js +4 -4
- package/dist/cli-delegate/cmd_uninstall.js +4 -4
- package/dist/cli-delegate/cmd_update.js +1 -1
- package/dist/cli-delegate/cmd_upgrade.js +1 -1
- package/dist/cli-delegate/cmd_validate.js +4 -4
- package/dist/cli-delegate/cmd_versions.js +1 -1
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +27 -80
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +3 -3
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +5 -7
- package/dist/discovery/trust-report.md +2 -2
- package/dist/discovery/workspaces.json +4 -6
- package/dist/hooks/dispatch.js +9249 -8981
- package/dist/install/install.mjs +47 -8
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +5496 -2400
- package/dist/router.json +1 -1
- package/dist/scripts/_lib/agent_settings.js +73 -0
- package/dist/scripts/_lib/agent_src.js +20 -0
- package/dist/scripts/_lib/guidelines_lane.js +158 -0
- package/dist/scripts/_lib/lean_projection_mode.js +108 -0
- package/dist/scripts/_lib/router_match.js +243 -0
- package/dist/scripts/_lib/rule_injection.js +216 -0
- package/dist/scripts/condense.js +22 -25
- package/dist/scripts/project_thin_rules.js +139 -19
- package/dist/server/io/yamlIO.js +125 -17
- package/dist/server/schemas/settings.js +32 -5
- package/dist/shared/settingsSurface.js +6 -1
- package/docs/MIGRATION.md +56 -0
- package/docs/contracts/settings-classes.md +48 -7
- package/docs/guidelines/abstraction-thresholds.md +35 -0
- package/docs/guidelines/agent-infra/active-remediation-mechanics.md +3 -3
- package/docs/guidelines/agent-infra/false-green.md +2 -2
- package/docs/guidelines/agent-infra/notes-horizon-mechanics.md +90 -0
- package/docs/guidelines/agent-infra/roadmap-progress-mechanics.md +1 -1
- package/docs/guidelines/agent-infra/skill-quality-checklist.md +1 -1
- package/docs/guidelines/design-fidelity-mechanics.md +4 -0
- package/docs/guidelines/design-fidelity-routing.md +78 -0
- package/docs/guidelines/design-reconciliation.md +172 -0
- package/docs/guidelines/gtm-handoff.md +2 -2
- package/docs/guidelines/wing4-handoff.md +2 -2
- package/llms.txt +1 -1
- package/package.json +7 -3
- package/src/agent-src/scripts/archive_completed_roadmaps.ts +106 -4
- package/src/config/agent-settings.template.yml +94 -1
- package/src/config/ci-local-parity.yml +34 -0
- package/src/config/continuity-surface.json +8 -29
- package/src/config/evaluator-budgets.json +4 -4
- package/src/config/gate-coverage.yml +31 -8
- package/src/config/gate-reachability-exemptions.json +1 -0
- package/src/config/gate-violation-baselines.json +3 -3
- package/src/config/hook-token-budget.json +8 -7
- package/src/config/host-injection-effect.json +2 -2
- package/src/config/pack-size-budget.json +55 -4
- package/src/config/packed-binary-manifest.json +1 -1
- package/src/config/platform-anchor.json +47 -0
- package/src/config/preamble-payload-budget.json +2 -3
- package/src/config/publish-surface.json +4 -2
- package/src/config/ratification-policy.json +7 -0
- package/src/config/routing-coverage-seed.json +9 -2
- package/src/config/rule-stub-ceilings.json +16 -9
- package/src/scripts/_cli/cmd_session_recycle.ts +2 -25
- package/src/scripts/_cli/cmd_settings_get.ts +22 -7
- package/src/scripts/_cli/handoff_sessions.ts +14 -44
- package/src/scripts/_lib/agent_settings.ts +85 -0
- package/src/scripts/_lib/agent_src.ts +21 -0
- package/src/scripts/_lib/artifact_maturity.ts +242 -0
- package/src/scripts/_lib/conformance_report.ts +403 -0
- package/src/scripts/_lib/continuity_slot.ts +295 -0
- package/src/scripts/_lib/continuity_writer.ts +312 -0
- package/src/scripts/_lib/design_system_import.ts +20 -0
- package/src/scripts/_lib/design_tolerance.ts +281 -0
- package/src/scripts/_lib/guidelines_lane.ts +164 -0
- package/src/scripts/_lib/hook_settings.ts +85 -0
- package/src/scripts/_lib/lean_projection_mode.ts +127 -0
- package/src/scripts/_lib/obligation_frequency.ts +2 -3
- package/src/scripts/_lib/packed_binary_predicate.ts +37 -0
- package/src/scripts/_lib/platform_anchor.ts +1053 -0
- package/src/scripts/_lib/ratification_artifact.ts +278 -0
- package/src/scripts/_lib/recycle_envelope_paths.ts +109 -21
- package/src/scripts/_lib/regression_neighbourhood.ts +159 -22
- package/src/scripts/_lib/security_lint.ts +23 -2
- package/src/scripts/_lib/self_repair.ts +21 -0
- package/src/scripts/_lib/session_eol.ts +44 -0
- package/src/scripts/_lib/session_index_trust.ts +387 -0
- package/src/scripts/_lib/standing_bound_ratchet.ts +220 -0
- package/src/scripts/_lib/tolerance_shadow.ts +177 -0
- package/src/scripts/_lib/vendored_grammar_upstream.ts +280 -0
- package/src/scripts/ai_council/redact_low_impact_entry.ts +8 -0
- package/src/scripts/audit_mcp_tools.ts +69 -25
- package/src/scripts/autonomy_friction_traffic.ts +379 -0
- package/src/scripts/build_mcp_catalog.ts +24 -1
- package/src/scripts/check_host_tree_parity.ts +291 -0
- package/src/scripts/check_kernel_edit_ratified.ts +462 -0
- package/src/scripts/check_loss_class_declared.ts +793 -46
- package/src/scripts/check_platform_anchor.ts +390 -0
- package/src/scripts/check_preamble_payload_budget.ts +424 -7
- package/src/scripts/check_projected_rule_routes.ts +395 -0
- package/src/scripts/check_rule_projection_integrity.ts +102 -2
- package/src/scripts/ci_settle.ts +205 -5
- package/src/scripts/code_graph/build.ts +79 -0
- package/src/scripts/code_graph/cli.ts +264 -7
- package/src/scripts/code_graph/detect.ts +38 -0
- package/src/scripts/code_graph/query.ts +25 -2
- package/src/scripts/code_graph/sqlite_store.ts +16 -1
- package/src/scripts/code_graph/types.ts +52 -3
- package/src/scripts/code_graph/validate.ts +3 -1
- package/src/scripts/code_graph/verbs.ts +590 -0
- package/src/scripts/condense.ts +22 -26
- package/src/scripts/generate_host_cost_table.ts +354 -0
- package/src/scripts/handoff_context_hook.ts +39 -1
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +59 -28
- package/src/scripts/hooks/block_speaking_inbox_dir.ts +182 -16
- package/src/scripts/hooks/category_a.ts +1 -1
- package/src/scripts/hooks/chain_nudge_hook.ts +311 -25
- package/src/scripts/hooks/code_graph_context_hook.ts +7 -18
- package/src/scripts/hooks/push_settle_hook.ts +3 -2
- package/src/scripts/hooks/rule_inject_hook.ts +107 -20
- package/src/scripts/hooks/session_eol_hook.ts +177 -145
- package/src/scripts/hooks/source_first_gate_hook.ts +12 -0
- package/src/scripts/hooks/ui_route_nudge_hook.ts +52 -15
- package/src/scripts/hot_context_hook.ts +103 -408
- package/src/scripts/lint_evidence_artifacts.ts +1 -0
- package/src/scripts/lint_knowledge_scale.ts +0 -26
- package/src/scripts/lint_roadmap_blockers.ts +164 -1
- package/src/scripts/mcp_server/consumer_tool_catalog.json +152 -2
- package/src/scripts/mcp_server/graph_tools.ts +294 -0
- package/src/scripts/mcp_server/path_util.ts +31 -0
- package/src/scripts/mcp_server/tool_catalog_source.ts +7 -1
- package/src/scripts/mcp_server/tools.ts +3 -13
- package/src/scripts/memory_lookup.ts +9 -9
- package/src/scripts/model_rule_injection.ts +61 -4
- package/src/scripts/project_thin_rules.ts +149 -16
- package/src/scripts/report_standing_payload_by_host.ts +650 -0
- package/src/scripts/schemas/agent-settings.schema.json +7 -1
- package/src/scripts/session_memory_index.ts +86 -8
- package/src/scripts/sync_agent_settings.ts +270 -10
- package/src/server/io/yamlIO.ts +127 -17
- package/src/server/schemas/settings.ts +45 -6
- package/src/shared/settingsSurface.ts +13 -2
- package/src/templates/compact-instructions.md +8 -3
- package/src/vendor/grammars/README.md +27 -2
- package/dist/agent-src/commands/chat-history/import.md +0 -170
- package/dist/agent-src/commands/chat-history.md +0 -63
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The continuity-record slot — capacity policy and state machine.
|
|
3
|
+
*
|
|
4
|
+
* `road-to-continuity-writer-activation` step 1.1. Until this module existed
|
|
5
|
+
* the slot had a producer (`session:recycle`), a consumer
|
|
6
|
+
* (`handoff_context_hook`) and no documented conflict ownership: the write was
|
|
7
|
+
* an unguarded `atomic_write_json`, so a second publish replaced whatever sat
|
|
8
|
+
* there and nobody had decided whether that was correct. With a MANUAL producer
|
|
9
|
+
* the question was theoretical — a human ran the verb once. Automatic
|
|
10
|
+
* production makes it routine, which is why the policy is settled here BEFORE
|
|
11
|
+
* any automatic writer exists.
|
|
12
|
+
*
|
|
13
|
+
* The full contract, including why the two rejected alternatives are rejected
|
|
14
|
+
* on tree evidence rather than on preference, is
|
|
15
|
+
* `docs/contracts/continuity-record-slot.md`. This module is that document in
|
|
16
|
+
* code; neither is the source of truth for the other's reasoning, and both are
|
|
17
|
+
* checked by `tests/scripts/_lib_continuity_slot.test.ts`.
|
|
18
|
+
*
|
|
19
|
+
* The policy in one line:
|
|
20
|
+
*
|
|
21
|
+
* SUPERSEDE OWN · REFUSE FOREIGN · QUARANTINE UNUSABLE · NEVER GO BACKWARDS.
|
|
22
|
+
*
|
|
23
|
+
* Why not create-if-absent.
|
|
24
|
+
*
|
|
25
|
+
* Create-if-absent is the policy the roadmap's own Risk 2 describes as a silent
|
|
26
|
+
* data loss: "the successor resumes from something plausible and older". It is
|
|
27
|
+
* rejected. Within one session the resident and the incoming record share a
|
|
28
|
+
* key, a workspace and a predecessor — the incoming one is the same lineage at
|
|
29
|
+
* a later moment, so keeping the older is a pure loss with no compensating
|
|
30
|
+
* safety.
|
|
31
|
+
*
|
|
32
|
+
* Why not a bounded multi-record queue.
|
|
33
|
+
*
|
|
34
|
+
* Because the reader forbids the resolution such a queue would need. Picking
|
|
35
|
+
* one of several records requires recency, and `recycle_envelope_paths.ts`
|
|
36
|
+
* carries a recorded decision against exactly that ("No `latest` index, by
|
|
37
|
+
* decision" — a pointer to the newest "would restore the shared write target
|
|
38
|
+
* one layer up"). `resolveContinuityRecord` implements it: several candidates
|
|
39
|
+
* and no session id START CLEAN rather than pick. A queue would either
|
|
40
|
+
* contradict that lock or be unreadable.
|
|
41
|
+
*
|
|
42
|
+
* Where `consuming` lives.
|
|
43
|
+
*
|
|
44
|
+
* Nowhere on disk, and that is the answer rather than a gap. Consumption is a
|
|
45
|
+
* single `fs.renameSync` from the authoritative name to the consumed name
|
|
46
|
+
* (`handoff_context_hook.ts:199`), and publication is a single `fs.renameSync`
|
|
47
|
+
* from a pid-suffixed temp name to the authoritative name
|
|
48
|
+
* (`state_io.ts:_publish_text_locked`). A rename within one directory is
|
|
49
|
+
* atomic on every filesystem this package supports, so an interruption lands
|
|
50
|
+
* strictly before or strictly after it: the authoritative name holds either the
|
|
51
|
+
* previous complete record or the new complete record, never a partial one.
|
|
52
|
+
* `consuming` is therefore a transition, not a state, and no reader has to
|
|
53
|
+
* tolerate a half-written record.
|
|
54
|
+
*/
|
|
55
|
+
import * as fs from 'node:fs';
|
|
56
|
+
import * as path from 'node:path';
|
|
57
|
+
|
|
58
|
+
import {
|
|
59
|
+
recycle_consumed_rel,
|
|
60
|
+
recycle_envelope_rel,
|
|
61
|
+
recycle_quarantine_rel,
|
|
62
|
+
RECYCLE_ENVELOPE_MAX_BYTES,
|
|
63
|
+
RECYCLE_MAX_AGE_HOURS,
|
|
64
|
+
} from './recycle_envelope_paths.js';
|
|
65
|
+
import { validateRecycleEnvelope } from './subagent_capsule.js';
|
|
66
|
+
import { update_json_under_lock } from '../hooks/state_io.js';
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* The slot's states.
|
|
70
|
+
*
|
|
71
|
+
* Five are observable on disk. `consuming` is declared because the roadmap step
|
|
72
|
+
* names it and a reader looking for it deserves to find the reason it is not a
|
|
73
|
+
* disk state rather than to conclude it was forgotten — see the module header.
|
|
74
|
+
*/
|
|
75
|
+
export const SLOT_STATES = [
|
|
76
|
+
'absent',
|
|
77
|
+
'published',
|
|
78
|
+
'consuming',
|
|
79
|
+
'consumed',
|
|
80
|
+
'quarantined',
|
|
81
|
+
'conflicting',
|
|
82
|
+
] as const;
|
|
83
|
+
export type SlotState = (typeof SLOT_STATES)[number];
|
|
84
|
+
|
|
85
|
+
/** What a publish attempt did, and why. The reason is always present. */
|
|
86
|
+
export interface PublishOutcome {
|
|
87
|
+
/** `published` on a write; otherwise the state that refused it. */
|
|
88
|
+
state: SlotState;
|
|
89
|
+
/** Did the authoritative record change as a result of this call? */
|
|
90
|
+
wrote: boolean;
|
|
91
|
+
/** One line, always present — emitted by callers, never dropped. */
|
|
92
|
+
reason: string;
|
|
93
|
+
/** Absolute path of the record moved aside, when one was. */
|
|
94
|
+
quarantined?: string;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** What {@link inspectSlot} found, without changing anything. */
|
|
98
|
+
export interface SlotInspection {
|
|
99
|
+
state: SlotState;
|
|
100
|
+
reason: string;
|
|
101
|
+
/** The authoritative path this session's records live at. */
|
|
102
|
+
target: string;
|
|
103
|
+
/** Parsed resident record, when one is present AND parseable. */
|
|
104
|
+
resident?: Record<string, unknown>;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** Hours a record stays usable — the reader's own bound, not a second one. */
|
|
108
|
+
const MAX_AGE_MS = RECYCLE_MAX_AGE_HOURS * 3600 * 1000;
|
|
109
|
+
|
|
110
|
+
function _parse(file: string): Record<string, unknown> | null {
|
|
111
|
+
try {
|
|
112
|
+
const decoded: unknown = JSON.parse(fs.readFileSync(file, 'utf-8'));
|
|
113
|
+
if (typeof decoded === 'object' && decoded !== null && !Array.isArray(decoded)) {
|
|
114
|
+
return decoded as Record<string, unknown>;
|
|
115
|
+
}
|
|
116
|
+
return null;
|
|
117
|
+
} catch {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/** Milliseconds since a record's `written_at`, or `null` when it has none. */
|
|
123
|
+
function _ageMs(record: Record<string, unknown>, now: Date): number | null {
|
|
124
|
+
const raw = record['written_at'];
|
|
125
|
+
if (typeof raw !== 'string') return null;
|
|
126
|
+
const at = Date.parse(raw);
|
|
127
|
+
if (Number.isNaN(at)) return null;
|
|
128
|
+
return now.getTime() - at;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Read the slot for `session_id` without touching it.
|
|
133
|
+
*
|
|
134
|
+
* `conflicting` here is a statement about the RESIDENT relative to the caller's
|
|
135
|
+
* identity, which is why the session id is required rather than optional: a
|
|
136
|
+
* record is foreign only with respect to somebody.
|
|
137
|
+
*/
|
|
138
|
+
export function inspectSlot(
|
|
139
|
+
workspace_root: string,
|
|
140
|
+
session_id: string | null | undefined,
|
|
141
|
+
now: Date = new Date(),
|
|
142
|
+
): SlotInspection {
|
|
143
|
+
const target = path.join(workspace_root, recycle_envelope_rel(session_id));
|
|
144
|
+
if (!fs.existsSync(target)) {
|
|
145
|
+
const consumed = path.join(workspace_root, recycle_consumed_rel(session_id));
|
|
146
|
+
if (fs.existsSync(consumed)) {
|
|
147
|
+
return { state: 'consumed', reason: 'the record for this session was consumed', target };
|
|
148
|
+
}
|
|
149
|
+
const quarantined = path.join(workspace_root, recycle_quarantine_rel(session_id));
|
|
150
|
+
if (fs.existsSync(quarantined)) {
|
|
151
|
+
return {
|
|
152
|
+
state: 'quarantined',
|
|
153
|
+
reason: 'the slot is free; an unusable record sits in quarantine',
|
|
154
|
+
target,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
return { state: 'absent', reason: 'no record in this slot', target };
|
|
158
|
+
}
|
|
159
|
+
const resident = _parse(target);
|
|
160
|
+
if (resident === null) {
|
|
161
|
+
return { state: 'quarantined', reason: 'the resident record does not parse as an object', target };
|
|
162
|
+
}
|
|
163
|
+
const violations = validateRecycleEnvelope(resident);
|
|
164
|
+
if (violations.length > 0) {
|
|
165
|
+
return {
|
|
166
|
+
state: 'quarantined',
|
|
167
|
+
reason: `the resident record fails validation (${violations.length} violation(s))`,
|
|
168
|
+
target,
|
|
169
|
+
resident,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
const age = _ageMs(resident, now);
|
|
173
|
+
if (age === null || age > MAX_AGE_MS) {
|
|
174
|
+
return {
|
|
175
|
+
state: 'quarantined',
|
|
176
|
+
reason:
|
|
177
|
+
age === null
|
|
178
|
+
? 'the resident record carries no parseable written_at'
|
|
179
|
+
: `the resident record is older than ${RECYCLE_MAX_AGE_HOURS} h`,
|
|
180
|
+
target,
|
|
181
|
+
resident,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
const owner = String(resident['session_id'] ?? '').trim();
|
|
185
|
+
const mine = String(session_id ?? '').trim();
|
|
186
|
+
if (owner !== '' && mine !== '' && owner !== mine) {
|
|
187
|
+
return {
|
|
188
|
+
state: 'conflicting',
|
|
189
|
+
reason: `the slot holds an unconsumed record belonging to session ${owner}`,
|
|
190
|
+
target,
|
|
191
|
+
resident,
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
return { state: 'published', reason: 'this session has an unconsumed record', target, resident };
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Publish `record` into this session's slot under the capacity policy.
|
|
199
|
+
*
|
|
200
|
+
* Never throws for a policy reason: a refusal is a return value, because this
|
|
201
|
+
* runs on the Stop path where an exception is a worse outcome than a missed
|
|
202
|
+
* record. A genuine I/O failure is reported as `wrote: false` with the reason,
|
|
203
|
+
* for the same reason.
|
|
204
|
+
*
|
|
205
|
+
* The write itself goes through {@link update_json_under_lock} rather than
|
|
206
|
+
* `atomic_write_json`, and the difference is the whole point: the locked form
|
|
207
|
+
* gives a read-modify-write, so the resident is inspected and the decision
|
|
208
|
+
* taken INSIDE the exclusion that stops a peer from publishing between the
|
|
209
|
+
* inspection and the write. `atomic_write_json` — the path
|
|
210
|
+
* `session:recycle` still uses — has no such window and cannot express a
|
|
211
|
+
* refusal.
|
|
212
|
+
*/
|
|
213
|
+
export function publishContinuityRecord(
|
|
214
|
+
workspace_root: string,
|
|
215
|
+
session_id: string | null | undefined,
|
|
216
|
+
record: Record<string, unknown>,
|
|
217
|
+
now: Date = new Date(),
|
|
218
|
+
): PublishOutcome {
|
|
219
|
+
const violations = validateRecycleEnvelope(record);
|
|
220
|
+
if (violations.length > 0) {
|
|
221
|
+
return {
|
|
222
|
+
state: 'absent',
|
|
223
|
+
wrote: false,
|
|
224
|
+
reason: `refused — the record to publish fails validation: ${violations[0] as string}`,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
const bytes = Buffer.byteLength(JSON.stringify(record, null, 2), 'utf-8');
|
|
228
|
+
if (bytes > RECYCLE_ENVELOPE_MAX_BYTES) {
|
|
229
|
+
return {
|
|
230
|
+
state: 'absent',
|
|
231
|
+
wrote: false,
|
|
232
|
+
reason: `refused — ${bytes} bytes exceeds the ${RECYCLE_ENVELOPE_MAX_BYTES} byte slot cap`,
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const target = path.join(workspace_root, recycle_envelope_rel(session_id));
|
|
237
|
+
const before = inspectSlot(workspace_root, session_id, now);
|
|
238
|
+
|
|
239
|
+
// A foreign, still-usable record is not this session's to move or replace.
|
|
240
|
+
// Refusing costs this session's resume; superseding costs another session's,
|
|
241
|
+
// and that one has no way to find out.
|
|
242
|
+
if (before.state === 'conflicting') {
|
|
243
|
+
return { state: 'conflicting', wrote: false, reason: `refused — ${before.reason}` };
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Monotonicity. A delayed or retried publisher must not roll the slot back
|
|
247
|
+
// to an earlier moment of the same session.
|
|
248
|
+
if (before.state === 'published' && before.resident !== undefined) {
|
|
249
|
+
const residentAt = Date.parse(String(before.resident['written_at'] ?? ''));
|
|
250
|
+
const incomingAt = Date.parse(String(record['written_at'] ?? ''));
|
|
251
|
+
if (!Number.isNaN(residentAt) && !Number.isNaN(incomingAt) && incomingAt < residentAt) {
|
|
252
|
+
return {
|
|
253
|
+
state: 'published',
|
|
254
|
+
wrote: false,
|
|
255
|
+
reason: 'refused — the resident record is newer than the one offered',
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
let quarantined: string | undefined;
|
|
261
|
+
if (before.state === 'quarantined' && fs.existsSync(target)) {
|
|
262
|
+
// Move aside, never delete. See `recycle_quarantine_rel`.
|
|
263
|
+
const dest = path.join(workspace_root, recycle_quarantine_rel(session_id));
|
|
264
|
+
try {
|
|
265
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
266
|
+
fs.renameSync(target, dest);
|
|
267
|
+
quarantined = dest;
|
|
268
|
+
} catch (exc) {
|
|
269
|
+
return {
|
|
270
|
+
state: 'quarantined',
|
|
271
|
+
wrote: false,
|
|
272
|
+
reason: `refused — could not quarantine the unusable resident: ${String(exc)}`,
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
const result = update_json_under_lock<Record<string, unknown>>(target, () => record);
|
|
278
|
+
if (result !== 'written') {
|
|
279
|
+
return {
|
|
280
|
+
state: before.state,
|
|
281
|
+
wrote: false,
|
|
282
|
+
reason: `refused — the slot write did not complete (${result})`,
|
|
283
|
+
...(quarantined !== undefined ? { quarantined } : {}),
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
return {
|
|
287
|
+
state: 'published',
|
|
288
|
+
wrote: true,
|
|
289
|
+
reason:
|
|
290
|
+
before.state === 'published'
|
|
291
|
+
? 'superseded this session’s earlier record'
|
|
292
|
+
: `published into a ${before.state} slot`,
|
|
293
|
+
...(quarantined !== undefined ? { quarantined } : {}),
|
|
294
|
+
};
|
|
295
|
+
}
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The deterministic continuity-record writer.
|
|
3
|
+
*
|
|
4
|
+
* `road-to-continuity-writer-activation` step 1.2. Until this module existed
|
|
5
|
+
* `agent-config session:recycle` was the ONLY writer of the continuity record
|
|
6
|
+
* in the tree, which is why `verb:session:recycle` counts on the
|
|
7
|
+
* `public_continuity_commands` axis and why an advisory had to tell a human to
|
|
8
|
+
* run it before `/clear`: continuity did not happen unless somebody
|
|
9
|
+
* remembered. Since step 3.2 (2026-09-10) this module is armed by default and
|
|
10
|
+
* that advisory is gone; the verb is retained as an explicit affordance, not
|
|
11
|
+
* as the normal path.
|
|
12
|
+
*
|
|
13
|
+
* Every field here is computed from on-disk state and nothing is asked of a
|
|
14
|
+
* model. That is not a cost optimisation, it is what makes the record a
|
|
15
|
+
* `continuity_record` rather than a `main_session` one: the judgement fields
|
|
16
|
+
* (`decisions`, `failed_approaches`, `successful_approaches`, …) are FORBIDDEN
|
|
17
|
+
* on the variant precisely so a deterministic writer cannot fill one with a
|
|
18
|
+
* guess and a reader cannot be left unable to tell a derived record from a
|
|
19
|
+
* judged one.
|
|
20
|
+
*
|
|
21
|
+
* Two gates, and both are needed:
|
|
22
|
+
*
|
|
23
|
+
* 1. `continuity.auto_record` must be `on`. It ships `on` since 2026-09-10
|
|
24
|
+
* (step 3.2, AI council under the owner's written delegation); before
|
|
25
|
+
* that it shipped `off` and this module was never reached on a default
|
|
26
|
+
* install. The switch still exists and still fails CLOSED, so an
|
|
27
|
+
* unreadable settings cascade disarms the producer rather than arming it.
|
|
28
|
+
* 2. The session must be SUBSTANTIVE by the committed floor
|
|
29
|
+
* (`is_substantive`) and must have a resolvable task. Both come from the
|
|
30
|
+
* concern's own counters and claim state, never from file presence.
|
|
31
|
+
*
|
|
32
|
+
* The task gate is the sharper of the two, and its bound is stated rather than
|
|
33
|
+
* hidden: a record needs at least one `acceptance_criteria` entry, and the only
|
|
34
|
+
* deterministic source of one in this tree is the roadmap a session has
|
|
35
|
+
* claimed. A session with no claim therefore leaves no record — and the
|
|
36
|
+
* alternative, writing a placeholder acceptance criterion, would assert a
|
|
37
|
+
* definition of "done" nobody set, which is the exact failure the variant's
|
|
38
|
+
* forbidden-key set exists to prevent.
|
|
39
|
+
*/
|
|
40
|
+
import * as fs from 'node:fs';
|
|
41
|
+
|
|
42
|
+
import { load_agent_settings, settings_layer_states } from './agent_settings.js';
|
|
43
|
+
import { resolvePredecessor } from './recycle_envelope_paths.js';
|
|
44
|
+
import { CHECKBOX_LINE, phaseLines } from './roadmap_checkboxes.js';
|
|
45
|
+
import { readHead, roadmapPath } from './run_checkpoint.js';
|
|
46
|
+
import { is_substantive, type StoredEolCounters } from './session_eol.js';
|
|
47
|
+
import { CAPSULE_SCHEMA_VERSION, MAX_ENTRIES, MAX_LINE_CHARS } from './subagent_capsule.js';
|
|
48
|
+
|
|
49
|
+
/** Settings key that arms this writer. Ships `on` since 2026-09-10 (step 3.2). */
|
|
50
|
+
export const AUTO_RECORD_KEY = 'continuity.auto_record';
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Read `continuity.auto_record` from the merged settings cascade.
|
|
54
|
+
*
|
|
55
|
+
* The cascade merges the shipped template, so a workspace with no settings file
|
|
56
|
+
* resolves the TEMPLATE's value. That is what the 2026-09-10 flip acts on:
|
|
57
|
+
* changing the template to `on` arms a default install.
|
|
58
|
+
*
|
|
59
|
+
* FAIL-CLOSED, AND IT IS NOW CARRIED BY CODE RATHER THAN BY THE DEFAULT.
|
|
60
|
+
*
|
|
61
|
+
* This function is documented — here, in `docs/contracts/continuity-rollback.md`
|
|
62
|
+
* and in step 1.4 of its roadmap — as failing closed: a settings cascade the
|
|
63
|
+
* user has broken must leave the producer disarmed. Until 2026-09-10 that
|
|
64
|
+
* property was carried by the TEMPLATE saying `off`, not by the `catch` below:
|
|
65
|
+
* measured, `load_agent_settings` does not throw on a malformed
|
|
66
|
+
* `.agent-settings.yml`; it skips the layer and returns the template's value.
|
|
67
|
+
* So the catch never ran for that case, and the flip to `on` removed the
|
|
68
|
+
* property outright — found by the fixture that was written to pin it.
|
|
69
|
+
*
|
|
70
|
+
* The repair is the property, not the wording. An AI council of 2026-09-10
|
|
71
|
+
* (2 seats, convergent, under the owner's written delegation) ruled option (A):
|
|
72
|
+
* openai — *"The defective implementation is grounds to repair the protection,
|
|
73
|
+
* not authority to repeal it."* Both seats classified the alternative (flipping
|
|
74
|
+
* the documented polarity to fail-open, matching `run_checkpoints_enabled`) as
|
|
75
|
+
* a WEAKENING of a class-C `consent` protection and therefore owner-reserved,
|
|
76
|
+
* not council-decidable, even done openly.
|
|
77
|
+
*
|
|
78
|
+
* So the malformed case is now decided by `settings_layer_states`, which
|
|
79
|
+
* reports per-layer validity instead of letting a resolved value stand in for
|
|
80
|
+
* it. The `catch` stays as the last resort for a genuine throw, and it is no
|
|
81
|
+
* longer the thing the claim rests on.
|
|
82
|
+
*
|
|
83
|
+
* The diagnostic is a required ATTEMPT with non-guaranteed delivery, which is
|
|
84
|
+
* the strongest promise this path can honestly make: the Stop slot never blocks
|
|
85
|
+
* and the dispatcher does not forward a concern's stderr on every host, so a
|
|
86
|
+
* line written here may reach nobody. Saying "warns you" would be the same
|
|
87
|
+
* class of claim this whole comment exists to correct.
|
|
88
|
+
*/
|
|
89
|
+
export function auto_record_enabled(root: string): boolean {
|
|
90
|
+
try {
|
|
91
|
+
// Fail-closed on a layer the USER can break, before the value is read.
|
|
92
|
+
// Order matters: reading first and checking second would let a valid
|
|
93
|
+
// template value decide a case in which the user's own file is broken.
|
|
94
|
+
const broken = settings_layer_states({ cwd: root }).filter((l) => l.state === 'malformed');
|
|
95
|
+
if (broken.length > 0) {
|
|
96
|
+
try {
|
|
97
|
+
process.stderr.write(
|
|
98
|
+
`continuity: ${AUTO_RECORD_KEY} disabled for this invocation — ` +
|
|
99
|
+
`unreadable or malformed settings layer(s): ` +
|
|
100
|
+
`${broken.map((l) => l.path).join(', ')}. ` +
|
|
101
|
+
`Validate the file; the shipped default cannot be trusted while a layer above it is broken.\n`,
|
|
102
|
+
);
|
|
103
|
+
} catch {
|
|
104
|
+
// a diagnostic that cannot be written must not change the verdict
|
|
105
|
+
}
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
const settings = load_agent_settings({ cwd: root });
|
|
109
|
+
const section = settings['continuity'];
|
|
110
|
+
if (section && typeof section === 'object' && !Array.isArray(section)) {
|
|
111
|
+
const v = (section as Record<string, unknown>)['auto_record'];
|
|
112
|
+
// YAML 1.1 parses a bare `on` as boolean true — accept both.
|
|
113
|
+
return v === 'on' || v === true;
|
|
114
|
+
}
|
|
115
|
+
} catch {
|
|
116
|
+
// last resort: a genuine throw leaves the writer disarmed
|
|
117
|
+
}
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/** Settings key that governs run-checkpoint production. Ships `on`. */
|
|
122
|
+
export const RUN_CHECKPOINTS_KEY = 'continuity.run_checkpoints';
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Read `continuity.run_checkpoints` from the merged settings cascade.
|
|
126
|
+
*
|
|
127
|
+
* Fails OPEN, unlike its sibling above, and the asymmetry is the point: this
|
|
128
|
+
* switch governs behaviour the tree already had, so an unreadable cascade must
|
|
129
|
+
* leave it running. Its sibling arms something new, so an unreadable cascade
|
|
130
|
+
* must leave that disarmed. A single helper with one polarity would have been
|
|
131
|
+
* wrong for one of the two.
|
|
132
|
+
*
|
|
133
|
+
* ONE HONEST QUALIFICATION, from the 2026-09-10 audit of its sibling. This
|
|
134
|
+
* function's `catch` is unreachable for a malformed settings file too — the
|
|
135
|
+
* loader skips a broken layer instead of throwing. Its fail-OPEN claim is true
|
|
136
|
+
* anyway, because the template says `on` and a malformed layer therefore
|
|
137
|
+
* resolves to `on`. So the polarity holds while the shipped default happens to
|
|
138
|
+
* agree with it, which is exactly the accident that broke the sibling when its
|
|
139
|
+
* default flipped. It is left as it is deliberately: the behaviour is correct
|
|
140
|
+
* today, and hardening a reader whose claim is currently true is a change with
|
|
141
|
+
* no observable effect. If this key's default ever moves to `off`, this comment
|
|
142
|
+
* is the notice that the claim moves with it.
|
|
143
|
+
*/
|
|
144
|
+
export function run_checkpoints_enabled(root: string): boolean {
|
|
145
|
+
try {
|
|
146
|
+
const settings = load_agent_settings({ cwd: root });
|
|
147
|
+
const section = settings['continuity'];
|
|
148
|
+
if (section && typeof section === 'object' && !Array.isArray(section)) {
|
|
149
|
+
const v = (section as Record<string, unknown>)['run_checkpoints'];
|
|
150
|
+
if (v === 'off' || v === false) return false;
|
|
151
|
+
}
|
|
152
|
+
} catch {
|
|
153
|
+
// fail-open: an unreadable cascade never silently removes a recovery aid
|
|
154
|
+
}
|
|
155
|
+
return true;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/** Why no record was built, when none was. Always a stated reason. */
|
|
159
|
+
export interface WriterDecision {
|
|
160
|
+
record: Record<string, unknown> | null;
|
|
161
|
+
reason: string;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/** How many `remaining` / `acceptance_criteria` lines a record carries. */
|
|
165
|
+
const LIST_CAP = 12;
|
|
166
|
+
|
|
167
|
+
function _clip(line: string): string {
|
|
168
|
+
const one = line.replace(/\s+/g, ' ').trim();
|
|
169
|
+
return one.length <= MAX_LINE_CHARS ? one : `${one.slice(0, MAX_LINE_CHARS - 1)}…`;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Open, closed and parked step counts plus the open step bodies.
|
|
174
|
+
*
|
|
175
|
+
* Deliberately reuses `phaseLines` + `CHECKBOX_LINE` rather than a fourth
|
|
176
|
+
* regex: a writer that disagreed with the dashboard about whether a roadmap is
|
|
177
|
+
* finished would put that disagreement into the record a successor resumes
|
|
178
|
+
* from.
|
|
179
|
+
*/
|
|
180
|
+
export function roadmapShape(text: string): { done: number; total: number; open: string[] } {
|
|
181
|
+
let done = 0;
|
|
182
|
+
let total = 0;
|
|
183
|
+
const open: string[] = [];
|
|
184
|
+
for (const raw of phaseLines(text)) {
|
|
185
|
+
const m = CHECKBOX_LINE.exec(raw);
|
|
186
|
+
if (m === null) continue;
|
|
187
|
+
total += 1;
|
|
188
|
+
const mark = m[1];
|
|
189
|
+
if (mark === 'x' || mark === 'X') {
|
|
190
|
+
done += 1;
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
if (mark === '~' || mark === '-') continue;
|
|
194
|
+
if (open.length < LIST_CAP) {
|
|
195
|
+
open.push(_clip((m[2] ?? '').replace(/\*\*/g, '')));
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
return { done, total, open };
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Checkbox bodies under an `## Acceptance Criteria` heading.
|
|
203
|
+
*
|
|
204
|
+
* `phaseLines` deliberately excludes this section — an autonomous run must not
|
|
205
|
+
* mistake an acceptance criterion for its next step — so it is read separately
|
|
206
|
+
* here, which is the one place the two readings legitimately differ.
|
|
207
|
+
*/
|
|
208
|
+
export function acceptanceCriteria(text: string): string[] {
|
|
209
|
+
const lines = text.split('\n');
|
|
210
|
+
const out: string[] = [];
|
|
211
|
+
let inside = false;
|
|
212
|
+
for (const raw of lines) {
|
|
213
|
+
const heading = /^(#{2,3})[ \t]+(.*?)[ \t]*$/.exec(raw);
|
|
214
|
+
if (heading !== null) {
|
|
215
|
+
inside = /^Acceptance[ \t]+Criteria\b/i.test(heading[2] ?? '');
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
if (!inside) continue;
|
|
219
|
+
const m = CHECKBOX_LINE.exec(raw);
|
|
220
|
+
if (m === null) continue;
|
|
221
|
+
if (out.length < LIST_CAP) {
|
|
222
|
+
out.push(_clip((m[2] ?? '').replace(/\*\*/g, '')));
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return out;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
export interface BuildInput {
|
|
229
|
+
/** Workspace root — the record's `workspace`, and the root every read is relative to. */
|
|
230
|
+
root: string;
|
|
231
|
+
/** Raw session id, as the record paths and the claim state key on it. */
|
|
232
|
+
sessionId: string;
|
|
233
|
+
/** The roadmap slug this session claimed, or `null` when it claimed none. */
|
|
234
|
+
slug: string | null;
|
|
235
|
+
/** The concern's own counters for this session. */
|
|
236
|
+
counters: StoredEolCounters | null;
|
|
237
|
+
/** Injected for determinism in tests. */
|
|
238
|
+
now?: Date;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Build the record, or say why there is none.
|
|
243
|
+
*
|
|
244
|
+
* Never throws and never shells out: this runs on the Stop path, where a
|
|
245
|
+
* subprocess is a latency cost paid on every turn's end and an exception is
|
|
246
|
+
* worse than a missing record. `head` is read from `.git` directly (worktree
|
|
247
|
+
* aware) rather than through `git`, and the richer anchor fields
|
|
248
|
+
* `session:recycle` collects with `git status` are deliberately omitted — the
|
|
249
|
+
* trade is one drift line for a Stop path that spawns nothing, and it is stated
|
|
250
|
+
* in `docs/contracts/continuity-record-slot.md` rather than left for a reader
|
|
251
|
+
* to discover by diffing two producers.
|
|
252
|
+
*/
|
|
253
|
+
export function buildContinuityRecord(input: BuildInput): WriterDecision {
|
|
254
|
+
const { root, sessionId, slug, counters } = input;
|
|
255
|
+
const now = input.now ?? new Date();
|
|
256
|
+
|
|
257
|
+
if (!is_substantive(counters)) {
|
|
258
|
+
return {
|
|
259
|
+
record: null,
|
|
260
|
+
reason: 'no record — the session is not substantive by the committed floor',
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
if (slug === null || slug.trim() === '') {
|
|
264
|
+
return {
|
|
265
|
+
record: null,
|
|
266
|
+
reason: 'no record — no claimed roadmap, so no deterministic acceptance criterion exists',
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
let text: string;
|
|
271
|
+
try {
|
|
272
|
+
text = fs.readFileSync(roadmapPath(root, slug), 'utf-8');
|
|
273
|
+
} catch {
|
|
274
|
+
return { record: null, reason: `no record — the claimed roadmap ${slug} is not readable` };
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
const shape = roadmapShape(text);
|
|
278
|
+
if (shape.total === 0) {
|
|
279
|
+
return { record: null, reason: `no record — ${slug} carries no phase checkboxes to count` };
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
const declared = acceptanceCriteria(text);
|
|
283
|
+
const criteria =
|
|
284
|
+
declared.length > 0
|
|
285
|
+
? declared
|
|
286
|
+
: // A roadmap with no declared criteria still has one definitional
|
|
287
|
+
// completion condition, and it is derived from the artefact class
|
|
288
|
+
// rather than judged: every step closed. Anything richer would be
|
|
289
|
+
// a definition of done nobody wrote.
|
|
290
|
+
[`every phase step in agents/roadmaps/${slug}.md is closed`];
|
|
291
|
+
|
|
292
|
+
const record: Record<string, unknown> = {
|
|
293
|
+
capsule_version: CAPSULE_SCHEMA_VERSION,
|
|
294
|
+
variant: 'continuity_record',
|
|
295
|
+
summary: _clip(`${slug}: ${shape.done} of ${shape.total} steps closed`),
|
|
296
|
+
task: _clip(slug),
|
|
297
|
+
workspace: root,
|
|
298
|
+
written_at: now.toISOString(),
|
|
299
|
+
acceptance_criteria: criteria.slice(0, MAX_ENTRIES),
|
|
300
|
+
remaining: shape.open.slice(0, MAX_ENTRIES),
|
|
301
|
+
predecessor: resolvePredecessor(root, sessionId),
|
|
302
|
+
artifact_paths: [`agents/roadmaps/${slug}.md`],
|
|
303
|
+
};
|
|
304
|
+
if (sessionId.trim() !== '') {
|
|
305
|
+
record['session_id'] = sessionId.trim();
|
|
306
|
+
}
|
|
307
|
+
const head = readHead(root);
|
|
308
|
+
if (head !== null) {
|
|
309
|
+
record['head'] = head;
|
|
310
|
+
}
|
|
311
|
+
return { record, reason: `record built for ${slug} (${shape.done}/${shape.total} closed)` };
|
|
312
|
+
}
|
|
@@ -77,8 +77,21 @@ export interface ComponentObservation {
|
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
/** The contract shape. Only `source` is mandatory; every other key is optional. */
|
|
80
|
+
/**
|
|
81
|
+
* The artefact-maturity block. Two-valued on the axis `design-fidelity`
|
|
82
|
+
* branches on, with the rung that decided it and the concrete signal — never a
|
|
83
|
+
* restatement of the verdict. Resolved by `_lib/artifact_maturity.ts`; OPTIONAL
|
|
84
|
+
* in the file, because absent resolves `finished` by the same rule.
|
|
85
|
+
*/
|
|
86
|
+
export interface SpecBlock {
|
|
87
|
+
maturity?: string;
|
|
88
|
+
maturity_source?: string;
|
|
89
|
+
maturity_signal?: string;
|
|
90
|
+
}
|
|
91
|
+
|
|
80
92
|
export interface DesignSystem {
|
|
81
93
|
source: SourceBlock;
|
|
94
|
+
spec?: SpecBlock;
|
|
82
95
|
colors?: { light?: Record<string, string>; dark?: Record<string, string> };
|
|
83
96
|
typography?: { families?: FontFamily[]; scale?: ScaleStep[] };
|
|
84
97
|
spacing?: { base?: string; scale?: string[] };
|
|
@@ -259,6 +272,13 @@ const NATIVE_KEY_SHAPE: Record<string, 'object' | 'array'> = {
|
|
|
259
272
|
shadow: 'object',
|
|
260
273
|
motion: 'object',
|
|
261
274
|
components: 'array',
|
|
275
|
+
// The artefact-maturity block (`road-to-design-intent-conformance` 3.1,
|
|
276
|
+
// resolved by `_lib/artifact_maturity.ts`). Added here in the same change
|
|
277
|
+
// that documented it: without a row the native lane routes it to
|
|
278
|
+
// `_meta.unmapped` with an "unknown top-level key" note, so the contract
|
|
279
|
+
// would say the field exists while the importer said it did not. Caught by
|
|
280
|
+
// a blind review, which read the two surfaces against each other.
|
|
281
|
+
spec: 'object',
|
|
262
282
|
_meta: 'object',
|
|
263
283
|
};
|
|
264
284
|
|