@event4u/agent-config 16.1.0 → 16.3.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 +98 -257
- package/README.md +14 -12
- package/dist/agent-src/commands/analyze/inbox.md +1 -1
- package/dist/agent-src/commands/analyze/roadmap-repos.md +1 -1
- package/dist/agent-src/commands/bug/fix.md +17 -2
- package/dist/agent-src/commands/feature/plan.md +1 -1
- package/dist/agent-src/commands/feature/roadmap.md +1 -1
- package/dist/agent-src/commands/fix/ci.md +1 -1
- package/dist/agent-src/commands/implement-ticket.md +1 -1
- package/dist/agent-src/commands/jira-ticket.md +1 -1
- package/dist/agent-src/commands/roadmap/create.md +1 -1
- package/dist/agent-src/commands/roadmap/materialize.md +1 -1
- package/dist/agent-src/commands/roadmap/process-full.md +5 -5
- package/dist/agent-src/commands/roadmap/resolve-blockers.md +361 -0
- package/dist/agent-src/commands/roadmap/triage-parked.md +325 -0
- package/dist/agent-src/commands/roadmap.md +18 -4
- package/dist/agent-src/commands/tests/create.md +17 -3
- package/dist/agent-src/commands/tests/execute.md +22 -5
- package/dist/agent-src/commands/work.md +4 -0
- package/dist/agent-src/contexts/authority/decision-revisit-gate-enforcement.md +43 -0
- package/dist/agent-src/contexts/communication/rules-auto/design-fidelity-enforcement.md +24 -0
- package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +6 -6
- package/dist/agent-src/contexts/execution/autonomy-mechanics.md +4 -8
- package/dist/agent-src/contexts/execution/roadmap-process-loop.md +32 -2
- package/dist/agent-src/contexts/execution/session-canary-enforcement-history.md +67 -0
- package/dist/agent-src/contexts/execution/toolchain-resolver.md +101 -7
- package/dist/agent-src/rules/active-remediation.md +1 -1
- package/dist/agent-src/rules/autonomous-execution.md +1 -0
- package/dist/agent-src/rules/broken-access-control.md +1 -0
- package/dist/agent-src/rules/command-suggestion-policy.md +1 -0
- package/dist/agent-src/rules/context-hygiene.md +1 -1
- package/dist/agent-src/rules/decision-revisit-gate.md +16 -33
- package/dist/agent-src/rules/design-fidelity.md +13 -16
- package/dist/agent-src/rules/doc-screenshot-hygiene.md +1 -0
- package/dist/agent-src/rules/domain-safety-disclaimer.md +1 -0
- package/dist/agent-src/rules/domain-safety-pii.md +1 -0
- package/dist/agent-src/rules/domain-safety-retention.md +1 -0
- package/dist/agent-src/rules/engineering-safety-floor.md +1 -0
- package/dist/agent-src/rules/evaluator-independence.md +3 -2
- package/dist/agent-src/rules/fast-path-marker-visibility.md +1 -0
- package/dist/agent-src/rules/finance-safety-floor.md +1 -0
- package/dist/agent-src/rules/git-history-discipline.md +1 -0
- package/dist/agent-src/rules/image-likeness-and-rights.md +1 -0
- package/dist/agent-src/rules/legal-safety-floor.md +3 -2
- package/dist/agent-src/rules/lethal-trifecta-guard.md +1 -0
- package/dist/agent-src/rules/low-impact-corpus-privacy-floor.md +1 -0
- package/dist/agent-src/rules/media-governance-routing.md +14 -17
- package/dist/agent-src/rules/persona-governance.md +2 -2
- package/dist/agent-src/rules/provider-lifecycle-discipline.md +1 -1
- package/dist/agent-src/rules/question-not-instruction.md +1 -0
- package/dist/agent-src/rules/roadmap-progress-sync.md +1 -1
- package/dist/agent-src/rules/runtime-safety.md +1 -0
- package/dist/agent-src/rules/secret-vcs-guard.md +1 -0
- package/dist/agent-src/rules/security-sensitive-stop.md +3 -2
- package/dist/agent-src/rules/session-canary.md +8 -62
- package/dist/agent-src/rules/settings-ask-protocol.md +1 -0
- package/dist/agent-src/rules/source-confidentiality.md +1 -0
- package/dist/agent-src/rules/strategy-safety-floor.md +1 -0
- package/dist/agent-src/rules/tool-safety.md +1 -0
- package/dist/agent-src/rules/ui-audit-gate.md +1 -2
- package/dist/agent-src/rules/untrusted-input-defense.md +1 -0
- package/dist/agent-src/rules/user-interrupt-priority.md +1 -0
- package/dist/agent-src/scripts/archive_completed_roadmaps.ts +115 -20
- package/dist/agent-src/scripts/deferral_carry.ts +339 -0
- package/dist/agent-src/scripts/update_roadmap_progress.ts +4 -1
- package/dist/agent-src/skills/accessibility-auditor/data/aria-patterns.csv +1 -1
- package/dist/agent-src/skills/accessibility-auditor/data/manifest.json +2 -2
- package/dist/agent-src/skills/api-design/data/manifest.json +2 -2
- package/dist/agent-src/skills/api-testing/SKILL.md +17 -0
- package/dist/agent-src/skills/code-intelligence/SKILL.md +14 -2
- package/dist/agent-src/skills/design-review/SKILL.md +30 -4
- package/dist/agent-src/skills/design-review/references/verification-automation.md +32 -0
- package/dist/agent-src/skills/design-system-capture/references/import-procedure.md +1 -1
- package/dist/agent-src/skills/existing-ui-audit/SKILL.md +18 -3
- package/dist/agent-src/skills/existing-ui-audit/references/component-taxonomy-detection.md +56 -0
- package/dist/agent-src/skills/fe-design/SKILL.md +1 -1
- package/dist/agent-src/skills/iconography/SKILL.md +1 -1
- package/dist/agent-src/skills/js-library-packaging/SKILL.md +2 -2
- package/dist/agent-src/skills/markitdown/SKILL.md +4 -0
- package/dist/agent-src/skills/monorepo-workspace/SKILL.md +1 -1
- package/dist/agent-src/skills/playwright-testing/SKILL.md +30 -6
- package/dist/agent-src/skills/quality-tools/SKILL.md +11 -1
- package/dist/agent-src/skills/quality-tools/references/go-tools.md +76 -0
- package/dist/agent-src/skills/quality-tools/references/python-tools.md +104 -0
- package/dist/agent-src/skills/review-routing/SKILL.md +2 -2
- package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +1 -1
- package/dist/agent-src/skills/storybook-workshop/SKILL.md +3 -3
- package/dist/agent-src/skills/tailwind-engineer/SKILL.md +1 -1
- package/dist/agent-src/skills/test-case-discovery/SKILL.md +7 -0
- package/dist/agent-src/skills/test-driven-development/SKILL.md +17 -0
- package/dist/agent-src/skills/test-performance/SKILL.md +19 -1
- package/dist/agent-src/skills/ui-component-architect/SKILL.md +25 -2
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/roadmaps.md +30 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/app_spec.ts +10 -4
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +302 -21
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/audit.ts +22 -3
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/scaffold.ts +6 -1
- package/dist/agent-src/templates/scripts/work_engine/stack/runner.ts +774 -109
- package/dist/agent-src/templates/scripts/work_engine/state.ts +57 -7
- package/dist/agent-src/templates/scripts/work_engine/taxonomy/detect.ts +500 -0
- package/dist/agent-src/templates/scripts/work_engine/taxonomy/place.ts +183 -0
- package/dist/cli/python/knowledge_ingest.js +1 -1
- package/dist/cli/python/workspace_drive.js +1 -1
- package/dist/cli/registry.js +1 -1
- package/dist/cli-delegate/archive_completed_roadmaps.js +92 -12
- package/dist/cli-delegate/check_update_banner.js +12 -1
- package/dist/cli-delegate/chunk-523HCFYO.js +90 -0
- package/dist/cli-delegate/{chunk-M2DPGFZ4.js → chunk-6V6TA25H.js} +22 -152
- package/dist/cli-delegate/chunk-7IQE3D5S.js +191 -0
- package/dist/cli-delegate/{chunk-6KFEC3G7.js → chunk-CQWX336L.js} +1 -1
- package/dist/cli-delegate/chunk-DEIV7XP7.js +108 -0
- package/dist/cli-delegate/chunk-EEHDXSYD.js +2040 -0
- package/dist/cli-delegate/{chunk-P6ZHP5W2.js → chunk-GKE7ZVFA.js} +4 -4
- package/dist/cli-delegate/chunk-JQOM7TTM.js +1201 -0
- package/dist/cli-delegate/{chunk-UNCRJBT3.js → chunk-JQVYKIZA.js} +41 -0
- package/dist/cli-delegate/{chunk-FC75PGJE.js → chunk-JY2I2DXV.js} +12 -1
- package/dist/cli-delegate/chunk-KB5FZ655.js +208 -0
- package/dist/cli-delegate/{chunk-YUM5KURG.js → chunk-KR6EM23A.js} +235 -1455
- package/dist/cli-delegate/{chunk-LTYVIY76.js → chunk-LIYTLH6O.js} +1 -1
- package/dist/cli-delegate/chunk-NQ7WT43P.js +2729 -0
- package/dist/cli-delegate/chunk-NXEILF2K.js +2160 -0
- package/dist/cli-delegate/{chunk-5R7HOLAF.js → chunk-NYX3L2PZ.js} +1 -1
- package/dist/cli-delegate/{chunk-4E2W63DA.js → chunk-OKJUIAPS.js} +62 -1
- package/dist/cli-delegate/{chunk-QAJS5YWY.js → chunk-PHD7OOLE.js} +2 -1
- package/dist/cli-delegate/{chunk-RGNIWTEA.js → chunk-QLDHIPWR.js} +1 -1
- package/dist/cli-delegate/{chunk-HDVVGPQW.js → chunk-RQNNW7IF.js} +1405 -567
- package/dist/cli-delegate/{chunk-S3VFXMTM.js → chunk-S4UMZNES.js} +1 -1
- package/dist/cli-delegate/{chunk-6KM6ORRY.js → chunk-S4YWNRKO.js} +24 -8
- package/dist/cli-delegate/{chunk-GJCBB2UG.js → chunk-TRI6DQZ6.js} +3054 -325
- package/dist/cli-delegate/chunk-ULQRUR23.js +208 -0
- package/dist/cli-delegate/{chunk-NUHLI2RX.js → chunk-YCU3TIXH.js} +2 -0
- package/dist/cli-delegate/chunk-ZBZV2G5R.js +210 -0
- package/dist/cli-delegate/{chunk-WGXTVKCQ.js → chunk-ZUZKZYCN.js} +5 -3
- 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 +1862 -809
- package/dist/cli-delegate/cmd_doctor.js +13 -6
- package/dist/cli-delegate/cmd_doctor_neighbours.js +23 -0
- package/dist/cli-delegate/cmd_explain.js +5 -5
- package/dist/cli-delegate/cmd_export.js +11 -8
- package/dist/cli-delegate/cmd_fleet.js +3 -3
- package/dist/cli-delegate/cmd_handoff.js +10 -7
- package/dist/cli-delegate/cmd_mcp_available.js +1 -1
- package/dist/cli-delegate/cmd_memory_get.js +3 -1
- package/dist/cli-delegate/cmd_migrate.js +2 -2
- package/dist/cli-delegate/cmd_packs_active.js +3 -3
- package/dist/cli-delegate/cmd_preflight.js +6 -6
- package/dist/cli-delegate/cmd_prune.js +11 -8
- package/dist/cli-delegate/cmd_refresh.js +2 -1
- package/dist/cli-delegate/cmd_route_audit.js +8 -6
- package/dist/cli-delegate/cmd_route_explain.js +4 -4
- package/dist/cli-delegate/cmd_session_recycle.js +4 -3
- package/dist/cli-delegate/cmd_settings_get.js +1 -1
- package/dist/cli-delegate/cmd_settings_migrate.js +11 -8
- package/dist/cli-delegate/cmd_settings_set.js +4 -4
- package/dist/cli-delegate/cmd_sync.js +11 -8
- package/dist/cli-delegate/cmd_uninstall.js +11 -8
- package/dist/cli-delegate/cmd_update.js +1 -1
- package/dist/cli-delegate/cmd_upgrade.js +3 -2
- package/dist/cli-delegate/cmd_validate.js +11 -8
- package/dist/cli-delegate/cmd_versions.js +1 -1
- package/dist/cli-delegate/deferral_carry.js +16 -0
- package/dist/cli-delegate/gate_execute.js +2 -2
- package/dist/cli-delegate/roadmap_gates.js +5 -5
- package/dist/cli-delegate/update_roadmap_progress.js +1 -1
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +132 -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 +7 -5
- package/dist/discovery/trust-report.md +2 -2
- package/dist/discovery/workspaces.json +6 -4
- package/dist/hooks/dispatch.js +7972 -5186
- package/dist/hooks/dispatch.sha256 +1 -0
- package/dist/install/claudePathsPlan.js +47 -6
- package/dist/install/claudeRuleRewrite.js +7 -0
- package/dist/install/emit_host_rules_cli.js +39 -36
- package/dist/install/globalRuleScope.js +87 -0
- package/dist/install/host_rule_ownership.js +160 -0
- package/dist/install/install.mjs +2226 -1055
- package/dist/install/installThinLayer.js +261 -0
- package/dist/install/installedRuleLinks.js +176 -0
- package/dist/install/wizard-plan.js +24 -0
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +40913 -34865
- package/dist/scripts/_lib/agent_settings.js +11 -0
- package/dist/scripts/_lib/claude_settings_hooks.js +10 -8
- package/dist/scripts/_lib/installed_layer.js +378 -0
- package/dist/scripts/_lib/lean_projection_mode.js +218 -15
- package/dist/scripts/_lib/rule_consequence_class.js +45 -0
- package/dist/scripts/_lib/rule_injection.js +67 -10
- package/dist/scripts/_lib/rule_law_section.js +122 -0
- package/dist/scripts/_lib/thin_rules.js +458 -0
- package/dist/scripts/_lib/windsurf_render.js +60 -0
- package/dist/scripts/condense.js +14 -26
- package/dist/scripts/project_thin_rules.js +14 -294
- package/dist/server/schemas/settings.js +29 -0
- package/dist/shared/skillRanking.js +74 -13
- package/dist/ui/assets/index-Cwq4d0hX.js +23 -0
- package/dist/ui/assets/index-Cyjy8bWO.css +1 -0
- package/dist/ui/index.html +2 -2
- package/docs/contracts/settings-classes.md +10 -6
- package/package.json +4 -4
- package/src/agent-src/scripts/archive_completed_roadmaps.ts +115 -20
- package/src/agent-src/scripts/deferral_carry.ts +339 -0
- package/src/agent-src/scripts/update_roadmap_progress.ts +4 -1
- package/src/agent-src/templates/scripts/work_engine/directives/ui/app_spec.ts +10 -4
- package/src/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +302 -21
- package/src/agent-src/templates/scripts/work_engine/directives/ui/audit.ts +22 -3
- package/src/agent-src/templates/scripts/work_engine/directives/ui/scaffold.ts +6 -1
- package/src/agent-src/templates/scripts/work_engine/stack/runner.ts +774 -109
- package/src/agent-src/templates/scripts/work_engine/state.ts +57 -7
- package/src/agent-src/templates/scripts/work_engine/taxonomy/detect.ts +500 -0
- package/src/agent-src/templates/scripts/work_engine/taxonomy/place.ts +183 -0
- package/src/config/agent-settings.template.yml +91 -22
- package/src/config/ci-local-parity.yml +18 -0
- package/src/config/continuity-surface.json +9 -2
- package/src/config/evaluator-budgets.json +4 -4
- package/src/config/gate-coverage.yml +327 -3
- package/src/config/gate-violation-baselines.json +21 -9
- package/src/config/hook-bundle-budget.json +25 -0
- package/src/config/hook-latency-budget.json +21 -0
- package/src/config/hook-token-budget.json +8 -3
- package/src/config/host-instruction-limits.json +33 -0
- package/src/config/metric-registry.yml +114 -0
- package/src/config/placeholder-drift-budget.json +10 -0
- package/src/config/routing-coverage-seed.json +38 -3
- package/src/config/rule-activation-census.json +7 -3
- package/src/config/rule-consequence-class.json +161 -0
- package/src/config/rule-law-ceilings.json +99 -0
- package/src/install/claudePathsPlan.ts +46 -4
- package/src/install/claudeRuleRewrite.ts +10 -1
- package/src/install/emit_host_rules_cli.ts +43 -34
- package/src/install/globalRuleScope.ts +109 -0
- package/src/install/host_rule_ownership.ts +170 -0
- package/src/install/installThinLayer.ts +312 -0
- package/src/install/installedRuleLinks.ts +220 -0
- package/src/install/wizard-plan.ts +24 -0
- package/src/scripts/_cli/cmd_doctor.ts +28 -90
- package/src/scripts/_cli/cmd_doctor_neighbours.ts +293 -0
- package/src/scripts/_cli/doctor_execution.ts +100 -17
- package/src/scripts/_cli/doctor_network_posture.ts +226 -0
- package/src/scripts/_dispatch.bash +16 -2
- package/src/scripts/_lib/agent_settings.ts +11 -0
- package/src/scripts/_lib/body_portable.ts +102 -0
- package/src/scripts/_lib/cc_transcript.ts +132 -1
- package/src/scripts/_lib/claude_settings_hooks.ts +10 -8
- package/src/scripts/_lib/concern_sla_window.ts +200 -0
- package/src/scripts/_lib/estate_offsets.ts +241 -0
- package/src/scripts/_lib/exemption_shape.ts +143 -0
- package/src/scripts/_lib/fnv.ts +23 -0
- package/src/scripts/_lib/foreign_scan.ts +106 -0
- package/src/scripts/_lib/forge_protection.ts +114 -0
- package/src/scripts/_lib/forge_reader.ts +558 -0
- package/src/scripts/_lib/gitignore_block.ts +314 -0
- package/src/scripts/_lib/global_deploy_inventory.ts +32 -0
- package/src/scripts/_lib/graph_feeder_record.ts +214 -0
- package/src/scripts/_lib/hook_settings.ts +73 -0
- package/src/scripts/_lib/host_capability.ts +40 -19
- package/src/scripts/_lib/host_env_write.ts +111 -0
- package/src/scripts/_lib/host_hook_merge.ts +165 -0
- package/src/scripts/_lib/installed_layer.ts +538 -0
- package/src/scripts/_lib/json_merge.ts +82 -0
- package/src/scripts/_lib/json_pointers.ts +93 -11
- package/src/scripts/_lib/lean_projection_mode.ts +275 -15
- package/src/scripts/_lib/llm_proposer_transport.ts +14 -4
- package/src/scripts/_lib/machine_wake.ts +16 -3
- package/src/scripts/_lib/neighbour_census.ts +760 -0
- package/src/scripts/_lib/neighbour_scan.ts +122 -0
- package/src/scripts/_lib/neighbour_tool_use.ts +189 -0
- package/src/scripts/_lib/obligations.ts +119 -8
- package/src/scripts/_lib/probe_inputs.ts +271 -0
- package/src/scripts/_lib/prompt_shape.ts +46 -0
- package/src/scripts/_lib/read_surface_scan.ts +322 -0
- package/src/scripts/_lib/release_highlights.ts +2 -1
- package/src/scripts/_lib/release_migration_gate.ts +19 -3
- package/src/scripts/_lib/reserved_name_sweep.ts +73 -0
- package/src/scripts/_lib/retrieval_sanitize.ts +77 -16
- package/src/scripts/_lib/review_coverage.ts +134 -0
- package/src/scripts/_lib/rule_consequence_class.ts +71 -0
- package/src/scripts/_lib/rule_injection.ts +130 -10
- package/src/scripts/_lib/rule_law_section.ts +147 -0
- package/src/scripts/_lib/rule_layer_overlap.ts +58 -0
- package/src/scripts/_lib/shell_write_shapes.ts +108 -0
- package/src/scripts/_lib/skill_origin.ts +254 -0
- package/src/scripts/_lib/structural_hiding.ts +622 -0
- package/src/scripts/_lib/structured_ask.ts +64 -21
- package/src/scripts/_lib/thin_rules.ts +540 -0
- package/src/scripts/_lib/touched_file_quality.ts +434 -0
- package/src/scripts/_lib/turn_end_refusals.ts +600 -4
- package/src/scripts/_lib/turn_end_transcript.ts +216 -0
- package/src/scripts/_lib/verification_command.ts +324 -0
- package/src/scripts/_lib/verification_evidence.ts +647 -0
- package/src/scripts/_lib/verify_clause.ts +280 -0
- package/src/scripts/_lib/windsurf_render.ts +63 -0
- package/src/scripts/ai_council/cli_call_budget.ts +13 -5
- package/src/scripts/ai_council/clients.ts +26 -57
- package/src/scripts/ai_council/config.ts +1 -1
- package/src/scripts/ai_council/vendor_defaults.ts +45 -0
- package/src/scripts/ai_team/team_dispatch.ts +4 -0
- package/src/scripts/audit_skill_overlap.ts +261 -0
- package/src/scripts/before_complete_hook.ts +573 -25
- package/src/scripts/bench_hook_latency.ts +412 -5
- package/src/scripts/bench_touched_file_quality.ts +238 -0
- package/src/scripts/cache_realization_report.ts +61 -1
- package/src/scripts/check_argument_hint.ts +287 -0
- package/src/scripts/check_claims.ts +125 -1
- package/src/scripts/check_enforcement_coverage.ts +38 -9
- package/src/scripts/check_enforcement_matrix.ts +621 -22
- package/src/scripts/check_estate_count.ts +130 -153
- package/src/scripts/check_finding_dispositions.ts +138 -7
- package/src/scripts/check_generator_sync.ts +71 -0
- package/src/scripts/check_hook_bundle_composition.ts +370 -0
- package/src/scripts/check_host_docs_digest.ts +786 -0
- package/src/scripts/check_host_format_column.ts +559 -0
- package/src/scripts/check_input_references.ts +228 -0
- package/src/scripts/check_inputs_parity.ts +235 -0
- package/src/scripts/check_kernel_edit_ratified.ts +89 -9
- package/src/scripts/check_kill_switch_table.ts +294 -0
- package/src/scripts/check_memory.ts +7 -1
- package/src/scripts/check_placeholder_drift.ts +221 -0
- package/src/scripts/check_read_surface_coverage.ts +515 -0
- package/src/scripts/check_release_highlights.ts +10 -0
- package/src/scripts/check_release_holds.ts +2 -1
- package/src/scripts/check_release_pr_shape.ts +38 -15
- package/src/scripts/check_routing_coverage.ts +378 -11
- package/src/scripts/check_standing_rule_delivery.ts +33 -13
- package/src/scripts/check_static_parity.ts +17 -0
- package/src/scripts/check_verify_expectation_delta.ts +521 -0
- package/src/scripts/ci_settle.ts +145 -19
- package/src/scripts/closure_scan.ts +115 -1
- package/src/scripts/code_graph/detect.ts +127 -7
- package/src/scripts/code_graph/foreign.ts +194 -0
- package/src/scripts/code_graph/query.ts +217 -4
- package/src/scripts/code_graph/types.ts +26 -2
- package/src/scripts/code_graph/validate.ts +3 -1
- package/src/scripts/code_graph/verbs.ts +103 -0
- package/src/scripts/compile_hook_manifest.ts +90 -14
- package/src/scripts/condense.ts +14 -27
- package/src/scripts/estate_exemption_shape.ts +202 -0
- package/src/scripts/external_sources_denylist.json +29 -4
- package/src/scripts/generate_host_cost_table.ts +1 -1
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +192 -14
- package/src/scripts/hooks/block_config_weakening.ts +294 -4
- package/src/scripts/hooks/block_kernel_rule_writes.ts +9 -78
- package/src/scripts/hooks/block_plumbing_writes.ts +342 -0
- package/src/scripts/hooks/bundle_integrity.ts +291 -0
- package/src/scripts/hooks/chain_nudge_hook.ts +1 -2
- package/src/scripts/hooks/code_graph_context_hook.ts +253 -25
- package/src/scripts/hooks/comment_discipline_hook.ts +1 -3
- package/src/scripts/hooks/concern_failure_policy.ts +280 -0
- package/src/scripts/hooks/concern_registry.ts +2 -0
- package/src/scripts/hooks/concern_timings.ts +94 -0
- package/src/scripts/hooks/delegation_nudge_hook.ts +1 -2
- package/src/scripts/hooks/design_pass_hook.ts +100 -9
- package/src/scripts/hooks/design_slop_hook.ts +1 -2
- package/src/scripts/hooks/dispatch_hook.ts +77 -71
- package/src/scripts/hooks/edit_shape_hook.ts +1 -2
- package/src/scripts/hooks/end_review_nudge_hook.ts +1 -1
- package/src/scripts/hooks/evidence_independence.ts +1 -2
- package/src/scripts/hooks/exit_codes.ts +129 -0
- package/src/scripts/hooks/host_lowering.json +1 -0
- package/src/scripts/hooks/host_lowering.ts +146 -3
- package/src/scripts/hooks/host_lowering.yaml +262 -46
- package/src/scripts/hooks/host_semantics.ts +30 -2
- package/src/scripts/hooks/injection_budget.ts +9 -2
- package/src/scripts/hooks/interruption_ledger_hook.ts +1 -2
- package/src/scripts/hooks/journal_record_hook.ts +1 -2
- package/src/scripts/hooks/memory_recall_hook.ts +1 -2
- package/src/scripts/hooks/obligation_settle_hook.ts +151 -5
- package/src/scripts/hooks/one_question_per_ask_hook.ts +43 -6
- package/src/scripts/hooks/orchestration_record_hook.ts +1 -2
- package/src/scripts/hooks/payload_stub.ts +10 -1
- package/src/scripts/hooks/permission_gate.ts +1 -2
- package/src/scripts/hooks/push_settle_hook.ts +1 -3
- package/src/scripts/hooks/replay_hook.ts +2 -1
- package/src/scripts/hooks/reread_guard_hook.ts +1 -2
- package/src/scripts/hooks/review_baseline_hook.ts +1 -2
- package/src/scripts/hooks/rtk_wrap_hook.ts +1 -2
- package/src/scripts/hooks/rule_inject_hook.ts +765 -68
- package/src/scripts/hooks/run_continuation_hook.ts +13 -15
- package/src/scripts/hooks/skill_route_hook.ts +1 -2
- package/src/scripts/hooks/source_first_gate_hook.ts +1 -2
- package/src/scripts/hooks/spawn_guard_shadow_hook.ts +1 -2
- package/src/scripts/hooks/subagent_ledger_hook.ts +1 -2
- package/src/scripts/hooks/suggestion_capture_hook.ts +1 -1
- package/src/scripts/hooks/table_fingerprint.ts +70 -0
- package/src/scripts/hooks/telemetry_flush_hook.ts +1 -2
- package/src/scripts/hooks/telemetry_usage_hook.ts +65 -10
- package/src/scripts/hooks/tool_result_bytes_hook.ts +93 -9
- package/src/scripts/hooks/turn_end_gate_hook.ts +421 -324
- package/src/scripts/hooks/ui_route_nudge_hook.ts +1 -2
- package/src/scripts/hooks_status.ts +112 -0
- package/src/scripts/injection_scan_hook.ts +7 -0
- package/src/scripts/install.ts +75 -189
- package/src/scripts/installed_layer_report.ts +103 -0
- package/src/scripts/language_mirror_hook.ts +15 -6
- package/src/scripts/learning_sidecar.ts +119 -8
- package/src/scripts/lint_deny_text.ts +419 -0
- package/src/scripts/lint_exit_codes.ts +262 -0
- package/src/scripts/lint_hook_manifest.ts +108 -0
- package/src/scripts/lint_major_migration_sections.ts +156 -26
- package/src/scripts/lint_pack_boundaries.ts +63 -5
- package/src/scripts/lint_roadmap_blockers.ts +78 -12
- package/src/scripts/lint_rule_law_section.ts +517 -0
- package/src/scripts/lint_skill_descriptions.ts +1 -1
- package/src/scripts/lint_skill_scripts_readonly.ts +1 -1
- package/src/scripts/lint_workflow_security.ts +161 -5
- package/src/scripts/mcp_server/consumer_tool_catalog.json +53 -0
- package/src/scripts/mcp_server/graph_tools.ts +72 -3
- package/src/scripts/mcp_server/prompts.ts +142 -1
- package/src/scripts/measure_routing_signal.ts +54 -16
- package/src/scripts/measure_skill_ranker_baseline.ts +515 -53
- package/src/scripts/measure_turn_end_gate.ts +193 -0
- package/src/scripts/memory_learn_hook.ts +91 -6
- package/src/scripts/memory_lookup.ts +1 -1
- package/src/scripts/model_rule_injection.ts +52 -5
- package/src/scripts/prepack-check.mjs +53 -0
- package/src/scripts/project_thin_rules.ts +34 -327
- package/src/scripts/release_publication.ts +13 -1
- package/src/scripts/report_evidence_temperature.ts +657 -0
- package/src/scripts/report_installed_rule_links.ts +157 -0
- package/src/scripts/report_invocation_surface.ts +383 -0
- package/src/scripts/report_label_agreement.ts +233 -0
- package/src/scripts/report_obligation_carriers.ts +699 -0
- package/src/scripts/report_obligation_mechanism.ts +230 -0
- package/src/scripts/report_obligation_writer_split.ts +236 -0
- package/src/scripts/report_single_token_triggers.ts +277 -0
- package/src/scripts/report_skill_menu_census.ts +208 -0
- package/src/scripts/report_skill_ranker_confusion.ts +442 -0
- package/src/scripts/report_standing_payload_by_host.ts +188 -15
- package/src/scripts/report_verification_record_coverage.ts +306 -0
- package/src/scripts/roadmap_verify_share.ts +213 -0
- package/src/scripts/rule_activation_census.ts +5 -2
- package/src/scripts/rule_trigger_eval.ts +9 -9
- package/src/scripts/schemas/command.schema.json +44 -0
- package/src/scripts/schemas/review-findings.schema.json +7 -2
- package/src/scripts/schemas/rule.schema.json +5 -0
- package/src/scripts/schemas/skill.schema.json +44 -0
- package/src/scripts/self_review_gate.ts +421 -17
- package/src/scripts/semantic_parity_census.ts +314 -0
- package/src/scripts/session_eol_report.ts +54 -1
- package/src/scripts/skill_tools/score_skill_relevance.ts +290 -25
- package/src/scripts/sweep_dead_scan_roots.ts +1 -1
- package/src/scripts/sweep_skill_ranker_signals.ts +129 -0
- package/src/scripts/sync_gitignore.ts +29 -235
- package/src/scripts/trigger_eval_grandfather.json +0 -7
- package/src/scripts/trigger_eval_rotation.ts +122 -27
- package/src/scripts/ui_conformance_probe.ts +156 -4
- package/src/scripts/update_prices.ts +85 -3
- package/src/scripts/write_bundle_digest.mjs +74 -0
- package/src/server/schemas/settings.ts +41 -0
- package/src/shared/skillRanking.ts +117 -11
- package/src/templates/consumer-settings/ONBOARDING.md +1 -0
- package/dist/cli-delegate/chunk-FXYUYU4N.js +0 -4416
- package/dist/cli-delegate/chunk-QJWAUMJW.js +0 -1072
- package/dist/cli-delegate/chunk-YDPILCOL.js +0 -152
- package/dist/ui/assets/index-DH1xc62v.js +0 -29
- package/dist/ui/assets/index-jSfMW8_t.css +0 -1
|
@@ -12,7 +12,9 @@
|
|
|
12
12
|
* `urp.collect()` completion criterion, and exit code 0. snake_case kept.
|
|
13
13
|
*
|
|
14
14
|
* A roadmap that has reached `count_open == 0` and `count_deferred == 0` is
|
|
15
|
-
* **complete
|
|
15
|
+
* **complete** — and so is one whose only `[~]` steps are bare, because the
|
|
16
|
+
* sweep first carries them to a follow-up (`deferral_carry.ts`; `--no-carry`
|
|
17
|
+
* turns that off). This sweep moves it to `agents/roadmaps/archive/`, rewrites code-comment-allow provenance-comment -- the sweep's own operand
|
|
16
18
|
* inbound references (`agents/roadmaps/<x>.md` → `agents/roadmaps/archive/<x>.md`) code-comment-allow provenance-comment -- the rewrite this sweep performs
|
|
17
19
|
* across tracked files so links never break, and regenerates the dashboard.
|
|
18
20
|
*
|
|
@@ -63,6 +65,7 @@ import {
|
|
|
63
65
|
collect,
|
|
64
66
|
parse_blockers,
|
|
65
67
|
} from './update_roadmap_progress.js';
|
|
68
|
+
import { BLOCK_END_RE, DEFERRED_RESOLUTION_RE, DEFERRED_STEP_RE, planCarry, type CarryPlan, type OwnerDecision } from './deferral_carry.js';
|
|
66
69
|
import { guardedBaselineProblems, parseGuardedBaselines } from './guarded_baseline.js';
|
|
67
70
|
|
|
68
71
|
import { isCliEntry } from './_cli_entry.js';
|
|
@@ -403,17 +406,6 @@ export interface DeferredItem {
|
|
|
403
406
|
destination: string | null;
|
|
404
407
|
}
|
|
405
408
|
|
|
406
|
-
/**
|
|
407
|
-
* `<!-- deferred-resolution: carried-to=<slug> -->` — the resolved-deferral
|
|
408
|
-
* annotation. `merged-into=<slug>` is the second accepted form.
|
|
409
|
-
*/
|
|
410
|
-
const DEFERRED_RESOLUTION_RE = /<!--\s*deferred-resolution:\s*(carried-to|merged-into)\s*=\s*([A-Za-z0-9._-]+)\s*-->/;
|
|
411
|
-
|
|
412
|
-
/** `- [~] …` — a deferred step, at any indent, with `-` or `*`. */
|
|
413
|
-
const DEFERRED_STEP_RE = /^[ \t]*[-*][ \t]+\[~\][ \t]*(.*)$/;
|
|
414
|
-
/** Any other checkbox, or a heading — where a step's block ends. */
|
|
415
|
-
const BLOCK_END_RE = /^[ \t]*[-*][ \t]+\[[ xX~-]\]|^#{1,6}[ \t]/;
|
|
416
|
-
|
|
417
409
|
/** Escape a string for literal use inside a `RegExp`. */
|
|
418
410
|
function _escapeRe(v: string): string {
|
|
419
411
|
return v.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
@@ -590,9 +582,10 @@ export function deferralProblems(
|
|
|
590
582
|
/** Archive every complete active roadmap: no open steps, and every `[~]` resolved. */
|
|
591
583
|
function archive_completed(
|
|
592
584
|
root: string,
|
|
593
|
-
opts: { changed_only: boolean; base: string; dry_run: boolean },
|
|
585
|
+
opts: { changed_only: boolean; base: string; dry_run: boolean; carry?: boolean; owner_decision?: OwnerDecision; only?: string | null },
|
|
594
586
|
): ArchiveRecord[] {
|
|
595
587
|
const { changed_only, base, dry_run } = opts;
|
|
588
|
+
const carry = opts.carry ?? true;
|
|
596
589
|
const roadmap_root = path.join(root, 'agents', 'roadmaps');
|
|
597
590
|
if (!_isDir(roadmap_root)) {
|
|
598
591
|
return [];
|
|
@@ -617,7 +610,12 @@ function archive_completed(
|
|
|
617
610
|
);
|
|
618
611
|
|
|
619
612
|
const archived: ArchiveRecord[] = [];
|
|
613
|
+
// `--only`: the owner's archive answer is about ONE roadmap. Without the
|
|
614
|
+
// filter, `--owner-decision later` would also park every other roadmap
|
|
615
|
+
// still waiting on its own, unasked owner question.
|
|
616
|
+
const only = opts.only ? opts.only.replace(/^.*\//, '').replace(/\.md$/, '') + '.md' : null;
|
|
620
617
|
for (const stats of collect(roadmap_root)) {
|
|
618
|
+
if (only !== null && stats.rel !== only) continue;
|
|
621
619
|
// `guarded-baseline` is INCOMPLETE by construction (council 2026-08-31,
|
|
622
620
|
// 2/2 convergent) — checked BEFORE the open-step test on purpose. A
|
|
623
621
|
// well-formed record keeps its box `[ ]` and would be skipped silently as
|
|
@@ -625,7 +623,7 @@ function archive_completed(
|
|
|
625
623
|
// and invisible in a sweep that only reports what it moved; a MALFORMED
|
|
626
624
|
// one on `[x]` would otherwise archive with an annotation claiming the
|
|
627
625
|
// opposite. Both are named here instead.
|
|
628
|
-
|
|
626
|
+
let roadmapText = fs.readFileSync(path.join(roadmap_root, stats.rel), 'utf-8');
|
|
629
627
|
const guarded = parseGuardedBaselines(roadmapText);
|
|
630
628
|
if (guarded.length > 0) {
|
|
631
629
|
process.stderr.write(
|
|
@@ -644,13 +642,54 @@ function archive_completed(
|
|
|
644
642
|
// A `[~]` no longer blocks unconditionally: it blocks unless it carries a
|
|
645
643
|
// validated resolution annotation. See `deferralProblems` for why, and
|
|
646
644
|
// for every way that check fails closed.
|
|
645
|
+
const old_rel = `agents/roadmaps/${stats.rel}`;
|
|
646
|
+
let open_blockers = stats.open_blockers.map((b) => b.id);
|
|
647
647
|
if (stats.deferred !== 0) {
|
|
648
648
|
const abs = path.join(roadmap_root, stats.rel);
|
|
649
649
|
// The source's own slug is removed: it is trivially in `sweepSet`,
|
|
650
650
|
// and self-reference is reported by its own, clearer message.
|
|
651
651
|
const others = new Set(sweepSet);
|
|
652
652
|
others.delete(stats.rel.replace(/\.md$/, ''));
|
|
653
|
-
|
|
653
|
+
// Bare `[~]` steps are carried to a follow-up first, then validated
|
|
654
|
+
// like any hand-written carry — see `deferral_carry.ts`. Only for a
|
|
655
|
+
// roadmap this sweep would actually archive, so a `--changed-only`
|
|
656
|
+
// run never writes a follow-up for someone else's roadmap.
|
|
657
|
+
const inScope = !changed_only || (touched as Set<string>).has(old_rel);
|
|
658
|
+
const bare = parseDeferredItems(roadmapText).some((d) => d.kind === null);
|
|
659
|
+
if (carry && inScope && bare) {
|
|
660
|
+
const outcome = planCarry(root, stats.rel, roadmapText, open_blockers, _today(), opts.owner_decision ?? 'ask');
|
|
661
|
+
if ('refused' in outcome) {
|
|
662
|
+
process.stderr.write(` ⚠️ ${stats.rel}: deferrals not carried — ${outcome.refused}.\n`);
|
|
663
|
+
} else if (outcome.plan.ownerBlockers.length > 0 && !outcome.plan.parked) {
|
|
664
|
+
// The steps wait on the OWNER. Nothing is written: whether
|
|
665
|
+
// to park them or work them is the owner's call, and the
|
|
666
|
+
// step-by-step offer needs the first step on screen.
|
|
667
|
+
process.stdout.write(_ownerDecisionBlock(stats.rel, outcome.plan));
|
|
668
|
+
continue;
|
|
669
|
+
} else {
|
|
670
|
+
const { plan } = outcome;
|
|
671
|
+
process.stdout.write(
|
|
672
|
+
` ↪ ${stats.rel}: carried ${plan.carried} deferred step(s)` +
|
|
673
|
+
(plan.movedBlockers.length > 0 ? ` and blocker(s) ${plan.movedBlockers.join(', ')}` : '') +
|
|
674
|
+
` → ${plan.destRel}\n`,
|
|
675
|
+
);
|
|
676
|
+
if (dry_run) {
|
|
677
|
+
// Nothing was written, so the validation below would
|
|
678
|
+
// read the old file; report the move it would make.
|
|
679
|
+
archived.push({ roadmap: old_rel, archived_to: `agents/roadmaps/archive/${stats.rel}`, refs_migrated: [] });
|
|
680
|
+
continue;
|
|
681
|
+
}
|
|
682
|
+
fs.mkdirSync(path.dirname(path.join(root, plan.destRel)), { recursive: true });
|
|
683
|
+
fs.writeFileSync(path.join(root, plan.destRel), plan.destText, 'utf-8');
|
|
684
|
+
fs.writeFileSync(abs, plan.sourceText, 'utf-8');
|
|
685
|
+
// Staged so the blocker-divergence check below compares the
|
|
686
|
+
// carry against itself, not against the pre-carry index.
|
|
687
|
+
_run(['git', 'add', '--', plan.destRel, old_rel], root);
|
|
688
|
+
roadmapText = plan.sourceText;
|
|
689
|
+
open_blockers = open_blockers.filter((id) => !plan.movedBlockers.includes(id));
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
const problems = deferralProblems(root, stats.rel, roadmapText, others);
|
|
654
693
|
if (problems.length > 0) {
|
|
655
694
|
process.stderr.write(
|
|
656
695
|
` ⚠️ ${stats.rel}: ${problems.length} unresolved deferral(s) — not archived.\n`,
|
|
@@ -666,9 +705,8 @@ function archive_completed(
|
|
|
666
705
|
// predicted shipped in the 9.36.0 changelog head. Same discipline
|
|
667
706
|
// `roadmap-progress-sync` Iron Law 3 applies to `[~]` steps: a roadmap
|
|
668
707
|
// carrying an open decision stays visible until the decision is made.
|
|
669
|
-
const open_blockers = stats.open_blockers;
|
|
670
708
|
if (open_blockers.length > 0) {
|
|
671
|
-
const ids = open_blockers.
|
|
709
|
+
const ids = open_blockers.join(', ');
|
|
672
710
|
process.stderr.write(
|
|
673
711
|
` ⚠️ ${stats.rel}: all steps closed but ${open_blockers.length} ` +
|
|
674
712
|
`blocker(s) still open (${ids}) — not archived. Resolve them, ` +
|
|
@@ -676,7 +714,6 @@ function archive_completed(
|
|
|
676
714
|
);
|
|
677
715
|
continue;
|
|
678
716
|
}
|
|
679
|
-
const old_rel = `agents/roadmaps/${stats.rel}`;
|
|
680
717
|
if (changed_only && !(touched as Set<string>).has(old_rel)) {
|
|
681
718
|
continue; // complete, but not this branch's work
|
|
682
719
|
}
|
|
@@ -722,6 +759,38 @@ function archive_completed(
|
|
|
722
759
|
return archived;
|
|
723
760
|
}
|
|
724
761
|
|
|
762
|
+
/**
|
|
763
|
+
* The owner question, rendered for a human AND forwarded verbatim by a
|
|
764
|
+
* subagent: the trailing `OWNER-DECISION` line is one JSON object, so an
|
|
765
|
+
* orchestrator can re-present the decision without re-deriving it. A subagent
|
|
766
|
+
* never answers it and never re-runs with `--owner-decision later` itself.
|
|
767
|
+
*/
|
|
768
|
+
function _ownerDecisionBlock(rel: string, plan: CarryPlan): string {
|
|
769
|
+
const ids = plan.ownerBlockers.join(', ');
|
|
770
|
+
const park = `agents/roadmaps/later/${plan.destSlug}.md`;
|
|
771
|
+
const step = plan.firstStep.split('\n').map((l) => ` ${l}`).join('\n');
|
|
772
|
+
const record = {
|
|
773
|
+
roadmap: `agents/roadmaps/${rel}`,
|
|
774
|
+
owner_blockers: plan.ownerBlockers,
|
|
775
|
+
deferred_steps: plan.carried,
|
|
776
|
+
park_to: park,
|
|
777
|
+
archive_command: `./agent-config roadmap:archive --all --owner-decision later --only ${rel}`,
|
|
778
|
+
first_step: plan.firstStep,
|
|
779
|
+
};
|
|
780
|
+
return (
|
|
781
|
+
` ❓ ${rel}: ${plan.carried} deferred step(s) wait on owner blocker(s) ${ids} — not archived; the owner decides:\n` +
|
|
782
|
+
` 1. Archive it — the steps and their blockers park in ${park}\n` +
|
|
783
|
+
` (${record.archive_command})\n` +
|
|
784
|
+
' 2. Work them step by step, starting with:\n' +
|
|
785
|
+
`${step}\n` +
|
|
786
|
+
` OWNER-DECISION ${JSON.stringify(record)}\n`
|
|
787
|
+
);
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
function _today(): string {
|
|
791
|
+
return new Date().toISOString().slice(0, 10);
|
|
792
|
+
}
|
|
793
|
+
|
|
725
794
|
function _isDir(p: string): boolean {
|
|
726
795
|
try {
|
|
727
796
|
return fs.statSync(p).isDirectory();
|
|
@@ -824,13 +893,16 @@ function _runTwin(root: string, script: string): void {
|
|
|
824
893
|
const _PROG = 'archive_completed_roadmaps.py';
|
|
825
894
|
|
|
826
895
|
function _usage(): string {
|
|
827
|
-
return `usage: ${_PROG} [-h] [--all] [--base BASE] [--dry-run] [--repo-root REPO_ROOT]\n`;
|
|
896
|
+
return `usage: ${_PROG} [-h] [--all] [--base BASE] [--dry-run] [--no-carry] [--owner-decision later] [--only ROADMAP] [--repo-root REPO_ROOT]\n`;
|
|
828
897
|
}
|
|
829
898
|
|
|
830
899
|
interface Args {
|
|
831
900
|
all: boolean;
|
|
832
901
|
base: string;
|
|
833
902
|
dry_run: boolean;
|
|
903
|
+
carry: boolean;
|
|
904
|
+
owner_decision: OwnerDecision;
|
|
905
|
+
only: string | null;
|
|
834
906
|
repo_root: string | null;
|
|
835
907
|
}
|
|
836
908
|
|
|
@@ -838,6 +910,9 @@ function _parseArgs(argv: readonly string[]): Args {
|
|
|
838
910
|
let all = false;
|
|
839
911
|
let base = 'origin/main';
|
|
840
912
|
let dry_run = false;
|
|
913
|
+
let carry = true;
|
|
914
|
+
let owner_decision: OwnerDecision = 'ask';
|
|
915
|
+
let only: string | null = null;
|
|
841
916
|
let repo_root: string | null = null;
|
|
842
917
|
const emitError = (msg: string): never => {
|
|
843
918
|
process.stderr.write(_usage());
|
|
@@ -856,6 +931,23 @@ function _parseArgs(argv: readonly string[]): Args {
|
|
|
856
931
|
} else if (tok === '--dry-run') {
|
|
857
932
|
dry_run = true;
|
|
858
933
|
i += 1;
|
|
934
|
+
} else if (tok === '--no-carry') {
|
|
935
|
+
carry = false;
|
|
936
|
+
i += 1;
|
|
937
|
+
} else if (tok === '--only' || tok.startsWith('--only=')) {
|
|
938
|
+
const val = tok.includes('=') ? tok.slice(tok.indexOf('=') + 1) : argv[i + 1];
|
|
939
|
+
if (val === undefined || val === '') {
|
|
940
|
+
emitError('argument --only: expected one argument');
|
|
941
|
+
}
|
|
942
|
+
only = val as string;
|
|
943
|
+
i += tok.includes('=') ? 1 : 2;
|
|
944
|
+
} else if (tok === '--owner-decision' || tok.startsWith('--owner-decision=')) {
|
|
945
|
+
const val = tok.includes('=') ? tok.slice(tok.indexOf('=') + 1) : argv[i + 1];
|
|
946
|
+
if (val !== 'later' && val !== 'ask') {
|
|
947
|
+
emitError("argument --owner-decision: expected 'later' or 'ask'");
|
|
948
|
+
}
|
|
949
|
+
owner_decision = val as OwnerDecision;
|
|
950
|
+
i += tok.includes('=') ? 1 : 2;
|
|
859
951
|
} else if (tok === '--base') {
|
|
860
952
|
const val = argv[i + 1];
|
|
861
953
|
if (val === undefined) {
|
|
@@ -880,7 +972,7 @@ function _parseArgs(argv: readonly string[]): Args {
|
|
|
880
972
|
emitError(`unrecognized arguments: ${tok}`);
|
|
881
973
|
}
|
|
882
974
|
}
|
|
883
|
-
return { all, base, dry_run, repo_root };
|
|
975
|
+
return { all, base, dry_run, carry, owner_decision, only, repo_root };
|
|
884
976
|
}
|
|
885
977
|
|
|
886
978
|
function main(argv?: readonly string[]): number {
|
|
@@ -894,6 +986,9 @@ function main(argv?: readonly string[]): number {
|
|
|
894
986
|
changed_only: !ns.all,
|
|
895
987
|
base: ns.base,
|
|
896
988
|
dry_run: ns.dry_run,
|
|
989
|
+
carry: ns.carry,
|
|
990
|
+
owner_decision: ns.owner_decision,
|
|
991
|
+
only: ns.only,
|
|
897
992
|
});
|
|
898
993
|
if (archived.length === 0) {
|
|
899
994
|
process.stdout.write(' ℹ️ No completed roadmaps to archive.\n');
|
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-carry for the archival sweep: a finished roadmap whose only obstacle is
|
|
3
|
+
* bare `[~]` steps hands them to a follow-up roadmap and then archives.
|
|
4
|
+
*
|
|
5
|
+
* WHY. The dashboard renders a roadmap with zero open steps as 100 %, deferred
|
|
6
|
+
* steps included, while the sweep refused every bare `[~]` and waited for a
|
|
7
|
+
* human to write the `carried-to` annotation by hand. Nobody did: measured
|
|
8
|
+
* 2026-10-02, five roadmaps sat at 100 % in the active tree with fourteen
|
|
9
|
+
* unannotated deferrals between them, and `/roadmap:process-full` — which ends
|
|
10
|
+
* non-interactively — had no step that could resolve one. "Finished" and
|
|
11
|
+
* "archived" had silently come apart.
|
|
12
|
+
*
|
|
13
|
+
* The disposition this module executes is the one `roadmap-progress-sync`
|
|
14
|
+
* Iron Law 3 already routes to the council without the owner: carry the item
|
|
15
|
+
* AND its blocker into a named follow-up created in the SAME change. It keeps
|
|
16
|
+
* every criterion alive in the active estate, so it is the preserving branch of
|
|
17
|
+
* the preservation test, never a drop. The owner decided on 2026-10-02 that the
|
|
18
|
+
* sweep performs it automatically instead of waiting for a menu.
|
|
19
|
+
*
|
|
20
|
+
* What the carry does, so the archived parent and the live child agree:
|
|
21
|
+
*
|
|
22
|
+
* - every bare `[~]` block is copied verbatim into the child as an OPEN `[ ]`
|
|
23
|
+
* step — open, not `[~]`, because a child at 100 % on arrival would be
|
|
24
|
+
* carried again by the next sweep, forever;
|
|
25
|
+
* - the parent's step gets `<!-- deferred-resolution: carried-to=<child> -->`,
|
|
26
|
+
* and the child gets `parent_roadmap: <parent>`, which is the pair
|
|
27
|
+
* `deferralProblems` and `lint_deferral_integrity` validate from both ends;
|
|
28
|
+
* - every OPEN blocker a carried step names via `blocked-by: <id>` moves with
|
|
29
|
+
* it: copied verbatim into the child's `## Blockers`, and closed in the
|
|
30
|
+
* parent with a status line naming where it went. The open-blocker count is
|
|
31
|
+
* unchanged, it only changes file.
|
|
32
|
+
*
|
|
33
|
+
* NOT automatic when a moved blocker waits on the OWNER (owner decision
|
|
34
|
+
* 2026-10-02): the sweep then writes nothing and asks — archive with the steps
|
|
35
|
+
* parked in `later/` (`--owner-decision later`), or work them step by step with
|
|
36
|
+
* the first one on screen. The procedure lives in `roadmap-process-loop` § 6a.
|
|
37
|
+
*
|
|
38
|
+
* Refused, so nothing is written, when the parent would still not archive
|
|
39
|
+
* afterwards: an open blocker no carried step names is a decision the parent
|
|
40
|
+
* itself raised, and carrying around it would strand the child with steps that
|
|
41
|
+
* have no reason to exist apart from the parent. A human-written annotation
|
|
42
|
+
* that fails validation is also left alone — fixing someone's wrong carry is
|
|
43
|
+
* not this module's call.
|
|
44
|
+
*/
|
|
45
|
+
|
|
46
|
+
import * as fs from 'node:fs';
|
|
47
|
+
import * as path from 'node:path';
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* `<!-- deferred-resolution: carried-to=<slug> -->` — the resolved-deferral
|
|
51
|
+
* annotation. `merged-into=<slug>` is the second accepted form.
|
|
52
|
+
*/
|
|
53
|
+
export const DEFERRED_RESOLUTION_RE =
|
|
54
|
+
/<!--\s*deferred-resolution:\s*(carried-to|merged-into)\s*=\s*([A-Za-z0-9._-]+)\s*-->/;
|
|
55
|
+
|
|
56
|
+
/** `- [~] …` — a deferred step, at any indent, with `-` or `*`. */
|
|
57
|
+
export const DEFERRED_STEP_RE = /^[ \t]*[-*][ \t]+\[~\][ \t]*(.*)$/;
|
|
58
|
+
|
|
59
|
+
/** Any other checkbox, or a heading — where a step's block ends. */
|
|
60
|
+
export const BLOCK_END_RE = /^[ \t]*[-*][ \t]+\[[ xX~-]\]|^#{1,6}[ \t]/;
|
|
61
|
+
|
|
62
|
+
const BLOCKED_BY_RE = /blocked-by:\s*([A-Za-z0-9._-]+)/g;
|
|
63
|
+
const BLOCKER_HEAD_RE = /^###[ \t]+blocker:[ \t]*(.+?)[ \t]*$/i;
|
|
64
|
+
const STATUS_LINE_RE = /^([ \t]*-[ \t]+\*\*Status:\*\*[ \t]*)(.*)$/;
|
|
65
|
+
const AC_HEADING_RE = /^##[ \t]+acceptance/i;
|
|
66
|
+
const OWNER_LINE_RE = /^[ \t]*-[ \t]+\*\*Owner:\*\*[ \t]*`?([A-Za-z]+)/;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Blocker owners that are NOT the human owner. Everything else — `maintainer`,
|
|
70
|
+
* `user`, `owner`, and any value this list does not name — is owner-dependent:
|
|
71
|
+
* in doubt it is the owner's decision, so an unrecognised owner fails closed.
|
|
72
|
+
*/
|
|
73
|
+
const AGENT_SIDE_OWNERS: ReadonlySet<string> = new Set(['implementer', 'council', 'agent', 'ai']);
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* What happens to deferrals whose blockers wait on the owner.
|
|
77
|
+
*
|
|
78
|
+
* `ask` (default): nothing is written; the sweep reports the decision instead —
|
|
79
|
+
* archive with the steps parked in `later/`, or work them step by step.
|
|
80
|
+
* `later`: the owner chose to archive; the carry lands in `later/`.
|
|
81
|
+
*/
|
|
82
|
+
export type OwnerDecision = 'ask' | 'later';
|
|
83
|
+
|
|
84
|
+
/** The lightweight cap `lint_roadmap_complexity` enforces, with margin. */
|
|
85
|
+
const LIGHTWEIGHT_LINE_BUDGET = 500;
|
|
86
|
+
|
|
87
|
+
const DISPOSITION_DIRS: readonly string[] = ['', 'later', 'archive', 'skipped'];
|
|
88
|
+
|
|
89
|
+
interface BareStep {
|
|
90
|
+
/** Line index of the `[~]` line in the parent. */
|
|
91
|
+
line: number;
|
|
92
|
+
/** The step line plus its continuation block, dedented to the step. */
|
|
93
|
+
block: string[];
|
|
94
|
+
isAcceptance: boolean;
|
|
95
|
+
blockerIds: string[];
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
interface BlockerSpan {
|
|
99
|
+
id: string;
|
|
100
|
+
start: number;
|
|
101
|
+
end: number;
|
|
102
|
+
open: boolean;
|
|
103
|
+
ownerDependent: boolean;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export interface CarryPlan {
|
|
107
|
+
destSlug: string;
|
|
108
|
+
destRel: string;
|
|
109
|
+
destText: string;
|
|
110
|
+
sourceText: string;
|
|
111
|
+
carried: number;
|
|
112
|
+
movedBlockers: string[];
|
|
113
|
+
/** Moved blockers only the owner can resolve. Non-empty ⇒ the owner decides. */
|
|
114
|
+
ownerBlockers: string[];
|
|
115
|
+
/** The first carried step, verbatim, for the step-by-step offer. */
|
|
116
|
+
firstStep: string;
|
|
117
|
+
/** True when the carry targets `later/` (owner chose to archive). */
|
|
118
|
+
parked: boolean;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export type CarryOutcome = { plan: CarryPlan } | { refused: string };
|
|
122
|
+
|
|
123
|
+
function _bareSteps(lines: readonly string[]): BareStep[] {
|
|
124
|
+
const out: BareStep[] = [];
|
|
125
|
+
let inAcceptance = false;
|
|
126
|
+
// No fence skipping, on purpose: `parseDeferredItems` does not skip fences
|
|
127
|
+
// either, and a step this module did not see but the sweep's validation does
|
|
128
|
+
// would be written, then refused.
|
|
129
|
+
for (let i = 0; i < lines.length; i++) {
|
|
130
|
+
const line = lines[i] as string;
|
|
131
|
+
if (/^##[ \t]/.test(line)) inAcceptance = AC_HEADING_RE.test(line);
|
|
132
|
+
const m = DEFERRED_STEP_RE.exec(line);
|
|
133
|
+
if (m === null) continue;
|
|
134
|
+
let end = i + 1;
|
|
135
|
+
while (end < lines.length && !BLOCK_END_RE.test(lines[end] as string)) end++;
|
|
136
|
+
const raw = lines.slice(i, end);
|
|
137
|
+
if (DEFERRED_RESOLUTION_RE.test(raw.join('\n'))) continue;
|
|
138
|
+
while (raw.length > 1 && (raw[raw.length - 1] as string).trim() === '') raw.pop();
|
|
139
|
+
const indent = (/^[ \t]*/.exec(line) as RegExpExecArray)[0].length;
|
|
140
|
+
const block = raw.map((l) => (l.slice(0, indent).trim() === '' ? l.slice(indent) : l));
|
|
141
|
+
const ids = new Set<string>();
|
|
142
|
+
for (const b of raw) for (const hit of b.matchAll(BLOCKED_BY_RE)) ids.add(hit[1] as string);
|
|
143
|
+
out.push({ line: i, block, isAcceptance: inAcceptance, blockerIds: [...ids] });
|
|
144
|
+
}
|
|
145
|
+
return out;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function _blockerSpans(lines: readonly string[]): BlockerSpan[] {
|
|
149
|
+
const start = lines.findIndex((l) => /^##[ \t]+Blockers[ \t]*$/i.test(l));
|
|
150
|
+
if (start === -1) return [];
|
|
151
|
+
let sectionEnd = lines.length;
|
|
152
|
+
for (let i = start + 1; i < lines.length; i++) {
|
|
153
|
+
if (/^##[ \t]+\S/.test(lines[i] as string)) {
|
|
154
|
+
sectionEnd = i;
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
const spans: BlockerSpan[] = [];
|
|
159
|
+
for (let i = start + 1; i < sectionEnd; i++) {
|
|
160
|
+
const m = BLOCKER_HEAD_RE.exec(lines[i] as string);
|
|
161
|
+
if (m === null) continue;
|
|
162
|
+
let end = i + 1;
|
|
163
|
+
while (end < sectionEnd && !/^###?[ \t]/.test(lines[end] as string)) end++;
|
|
164
|
+
const status = lines
|
|
165
|
+
.slice(i, end)
|
|
166
|
+
.map((l) => STATUS_LINE_RE.exec(l))
|
|
167
|
+
.find((s) => s !== null);
|
|
168
|
+
const value = (status?.[2] ?? 'open').trim().toLowerCase();
|
|
169
|
+
const owner = lines
|
|
170
|
+
.slice(i, end)
|
|
171
|
+
.map((l) => OWNER_LINE_RE.exec(l))
|
|
172
|
+
.find((o) => o !== null);
|
|
173
|
+
spans.push({
|
|
174
|
+
id: (m[1] as string).trim(),
|
|
175
|
+
start: i,
|
|
176
|
+
end,
|
|
177
|
+
open: !/^resolved\b/.test(value),
|
|
178
|
+
ownerDependent: !AGENT_SIDE_OWNERS.has((owner?.[1] ?? '').toLowerCase()),
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
return spans;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function _plusDays(date: string, days: number): string {
|
|
185
|
+
const d = new Date(`${date}T00:00:00Z`);
|
|
186
|
+
d.setUTCDate(d.getUTCDate() + days);
|
|
187
|
+
return d.toISOString().slice(0, 10);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/** The first `<base>-carried[-N]` slug no roadmap directory already holds. */
|
|
191
|
+
export function nextCarrySlug(root: string, sourceSlug: string): string {
|
|
192
|
+
const base = sourceSlug.replace(/-carried(-\d+)?$/, '');
|
|
193
|
+
for (let n = 1; ; n++) {
|
|
194
|
+
const slug = n === 1 ? `${base}-carried` : `${base}-carried-${n}`;
|
|
195
|
+
const taken = DISPOSITION_DIRS.some((d) =>
|
|
196
|
+
fs.existsSync(path.join(root, 'agents', 'roadmaps', d, `${slug}.md`)),
|
|
197
|
+
);
|
|
198
|
+
if (!taken) return slug;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function _title(sourceText: string, sourceSlug: string): string {
|
|
203
|
+
const h1 = /^#[ \t]+(.+?)[ \t]*$/m.exec(sourceText.replace(/^---\n[\s\S]*?\n---\n/, ''));
|
|
204
|
+
return h1 !== null ? (h1[1] as string) : sourceSlug.replace(/-/g, ' ');
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Plan the carry for one roadmap. Pure apart from reading which slugs exist, so
|
|
209
|
+
* the sweep can decide before it writes anything.
|
|
210
|
+
*
|
|
211
|
+
* @param openBlockerIds every OPEN blocker the parent carries, as `collect()`
|
|
212
|
+
* counts them — the source of truth for "would it archive afterwards".
|
|
213
|
+
*/
|
|
214
|
+
export function planCarry(
|
|
215
|
+
root: string,
|
|
216
|
+
rel: string,
|
|
217
|
+
text: string,
|
|
218
|
+
openBlockerIds: readonly string[],
|
|
219
|
+
date: string,
|
|
220
|
+
ownerDecision: OwnerDecision = 'ask',
|
|
221
|
+
): CarryOutcome {
|
|
222
|
+
const sourceSlug = rel.replace(/\.md$/, '');
|
|
223
|
+
const lines = text.split('\n');
|
|
224
|
+
const steps = _bareSteps(lines);
|
|
225
|
+
if (steps.length === 0) return { refused: 'no bare `[~]` step to carry' };
|
|
226
|
+
|
|
227
|
+
const named = new Set(steps.flatMap((s) => s.blockerIds));
|
|
228
|
+
const stranded = openBlockerIds.filter((id) => !named.has(id));
|
|
229
|
+
if (stranded.length > 0) {
|
|
230
|
+
return {
|
|
231
|
+
refused:
|
|
232
|
+
`open blocker(s) no deferred step names (${stranded.join(', ')}) — ` +
|
|
233
|
+
'carrying around them would not let this roadmap archive',
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
const moved = _blockerSpans(lines).filter((b) => b.open && named.has(b.id));
|
|
237
|
+
const ownerBlockers = moved.filter((b) => b.ownerDependent).map((b) => b.id);
|
|
238
|
+
const parked = ownerBlockers.length > 0 && ownerDecision === 'later';
|
|
239
|
+
|
|
240
|
+
const destSlug = nextCarrySlug(root, sourceSlug);
|
|
241
|
+
const annotation = `<!-- deferred-resolution: carried-to=${destSlug} -->`;
|
|
242
|
+
|
|
243
|
+
const out = [...lines];
|
|
244
|
+
for (const b of moved) {
|
|
245
|
+
for (let i = b.start; i < b.end; i++) {
|
|
246
|
+
const s = STATUS_LINE_RE.exec(out[i] as string);
|
|
247
|
+
if (s === null) continue;
|
|
248
|
+
out[i] =
|
|
249
|
+
`${s[1] as string}resolved — carried, still open, to \`${destSlug}\` ` +
|
|
250
|
+
`with the steps it blocks (was: ${(s[2] as string).trim()})`;
|
|
251
|
+
break;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
for (const s of steps) out[s.line] = `${out[s.line] as string} ${annotation}`;
|
|
255
|
+
|
|
256
|
+
const toOpen = (block: readonly string[]): string =>
|
|
257
|
+
block.map((l, i) => (i === 0 ? l.replace(/\[~\]/, '[ ]') : l)).join('\n');
|
|
258
|
+
const phaseSteps = steps.filter((s) => !s.isAcceptance).map((s) => toOpen(s.block));
|
|
259
|
+
const acSteps = steps.filter((s) => s.isAcceptance).map((s) => toOpen(s.block));
|
|
260
|
+
const phaseName = `Deferred steps carried from ${sourceSlug}`;
|
|
261
|
+
const blockerText = moved.map((b) => lines.slice(b.start, b.end).join('\n').trimEnd());
|
|
262
|
+
|
|
263
|
+
const body = [
|
|
264
|
+
`# ${_title(text, sourceSlug)} — carried`,
|
|
265
|
+
'',
|
|
266
|
+
`> **Source:** carried by the archival sweep on ${date} from`,
|
|
267
|
+
`> [\`${sourceSlug}\`](${parked ? '../' : ''}archive/${sourceSlug}.md), which closed every other step.`,
|
|
268
|
+
'> Each step below was `[~]` there and is restated verbatim as open work, so',
|
|
269
|
+
'> archiving the parent buried nothing. Blockers the steps name moved with them.',
|
|
270
|
+
'',
|
|
271
|
+
'## Goal',
|
|
272
|
+
'',
|
|
273
|
+
`Every step ${sourceSlug} deferred is either done here or explicitly disposed`,
|
|
274
|
+
'of — a step that still cannot run is re-deferred with its reason, never',
|
|
275
|
+
'left to read as finished.',
|
|
276
|
+
'',
|
|
277
|
+
`## Phase 1 — ${phaseName}`,
|
|
278
|
+
'',
|
|
279
|
+
phaseSteps.length > 0
|
|
280
|
+
? phaseSteps.join('\n')
|
|
281
|
+
: '- [ ] **1.1 Close the carried acceptance criteria below.** The parent deferred\n' +
|
|
282
|
+
' only acceptance criteria; this step is done when each is checked or disposed of.\n' +
|
|
283
|
+
' verify: every criterion under `## Acceptance Criteria` is `[x]` or `[-]`',
|
|
284
|
+
'',
|
|
285
|
+
...(blockerText.length > 0 ? ['## Blockers', '', blockerText.join('\n\n'), ''] : []),
|
|
286
|
+
'## Risk Register',
|
|
287
|
+
`<!-- risk-review: v1 | reviewed: ${date} | reviewer: archive-sweep/auto-carry -->`,
|
|
288
|
+
'',
|
|
289
|
+
'| Rank | Item | Risk type | Description | Mitigation | Anchored under |',
|
|
290
|
+
'|------|------|-----------|-------------|------------|----------------|',
|
|
291
|
+
'| 1 | Carried steps stay blocked indefinitely | implementation | A step deferred ' +
|
|
292
|
+
'once for elapsed time or a decision can sit here as long as it sat in the parent | ' +
|
|
293
|
+
'It now counts as open work in the dashboard instead of as 100 %, and its blocker ' +
|
|
294
|
+
`is listed where the estate gates count it | Phase 1 — ${phaseName} |`,
|
|
295
|
+
'',
|
|
296
|
+
'## Acceptance Criteria',
|
|
297
|
+
'',
|
|
298
|
+
acSteps.length > 0
|
|
299
|
+
? acSteps.join('\n')
|
|
300
|
+
: `- [ ] AC-1 — No step carried from \`${sourceSlug}\` is still \`[ ]\` without a recorded disposition.`,
|
|
301
|
+
'',
|
|
302
|
+
].join('\n');
|
|
303
|
+
const complexity = body.split('\n').length > LIGHTWEIGHT_LINE_BUDGET ? 'structural' : 'lightweight';
|
|
304
|
+
// Parked: `status: later` plus the three-part `entry_condition:` mapping
|
|
305
|
+
// `lint_roadmap_later_disposition` requires, and the growth claim the
|
|
306
|
+
// `later_roadmaps` count needs — a new file in `later/` is not a parking
|
|
307
|
+
// move, so no allowance covers it otherwise.
|
|
308
|
+
const ids = ownerBlockers.join(', ');
|
|
309
|
+
const parkedKeys = parked
|
|
310
|
+
? 'entry_condition:\n' +
|
|
311
|
+
` what: the owner resolves blocker(s) ${ids}\n` +
|
|
312
|
+
' when: whenever the owner takes the next step\n' +
|
|
313
|
+
' who: owner\n' +
|
|
314
|
+
// `lint_roadmap_later_disposition` rule C: a park with no review date
|
|
315
|
+
// reads exactly like an abandonment.
|
|
316
|
+
`review_by: ${_plusDays(date, 90)}\n` +
|
|
317
|
+
`estate_growth_exempt: >-\n Owner-chosen archive of ${sourceSlug}: its deferred steps wait on owner\n` +
|
|
318
|
+
` blocker(s) ${ids} and are parked here instead of left active. The parent\n` +
|
|
319
|
+
' is archived in the same change, so the active count drops by one.\n'
|
|
320
|
+
: '';
|
|
321
|
+
const destText =
|
|
322
|
+
`---\ncomplexity: ${complexity}\nstatus: ${parked ? 'later' : 'ready'}\nexecution:\n mode: phase-checkpoints\n` +
|
|
323
|
+
`parent_roadmap: ${sourceSlug}\n${parkedKeys}---\n${body}`;
|
|
324
|
+
const destRel = parked ? `agents/roadmaps/later/${destSlug}.md` : `agents/roadmaps/${destSlug}.md`;
|
|
325
|
+
|
|
326
|
+
return {
|
|
327
|
+
plan: {
|
|
328
|
+
destSlug,
|
|
329
|
+
destRel,
|
|
330
|
+
destText,
|
|
331
|
+
sourceText: out.join('\n'),
|
|
332
|
+
carried: steps.length,
|
|
333
|
+
movedBlockers: moved.map((b) => b.id),
|
|
334
|
+
ownerBlockers,
|
|
335
|
+
firstStep: (steps[0] as BareStep).block.join('\n'),
|
|
336
|
+
parked,
|
|
337
|
+
},
|
|
338
|
+
};
|
|
339
|
+
}
|
|
@@ -1351,7 +1351,10 @@ function main(argv?: readonly string[]): number {
|
|
|
1351
1351
|
// leaves behind rather than the one it found. `--check` never archives: a
|
|
1352
1352
|
// gate that mutates the tree it is checking cannot be trusted by CI.
|
|
1353
1353
|
let sweep_out = '';
|
|
1354
|
-
|
|
1354
|
+
// `pending_iron_law_3` too: a 100 % roadmap with bare `[~]` steps is what the
|
|
1355
|
+
// sweep's carry exists for, and gating on `deferred === 0` never spawned it.
|
|
1356
|
+
const before = collect(roadmap_root);
|
|
1357
|
+
if (!args.check && args.archive && unarchived_complete(before).length + pending_iron_law_3(before).length > 0) {
|
|
1355
1358
|
const swept = run_archival_sweep(repo_root);
|
|
1356
1359
|
sweep_out = swept.stdout;
|
|
1357
1360
|
if (swept.stderr) {
|
|
@@ -11,8 +11,9 @@
|
|
|
11
11
|
*
|
|
12
12
|
* The gate is **scoped to the greenfield-scaffold path only**. It acts only
|
|
13
13
|
* when `state.ui_audit` records `greenfield == True` and
|
|
14
|
-
* `greenfield_decision
|
|
15
|
-
* clean `SUCCESS` no-op, so those flows stay
|
|
14
|
+
* `greenfield_decision` ∈ `{scaffold, granularity_convention}`. Every other
|
|
15
|
+
* UI flow sees this slot as a clean `SUCCESS` no-op, so those flows stay
|
|
16
|
+
* byte-identical.
|
|
16
17
|
*/
|
|
17
18
|
import {
|
|
18
19
|
type Any,
|
|
@@ -21,6 +22,7 @@ import {
|
|
|
21
22
|
StepResult,
|
|
22
23
|
agent_directive,
|
|
23
24
|
} from '../../delivery_state.js';
|
|
25
|
+
import { GRANULARITY_CONVENTION } from '../../state.js';
|
|
24
26
|
|
|
25
27
|
/** Declared ambiguity surfaces for this step. */
|
|
26
28
|
export const AMBIGUITIES: ReadonlyArray<Record<string, string>> = [
|
|
@@ -112,14 +114,18 @@ export function run(state: DeliveryState): StepResult {
|
|
|
112
114
|
* The gate is inert for every other flow: improve-existing, the `bare` /
|
|
113
115
|
* `external_reference` greenfield picks, and the `diff` / `file` envelopes all
|
|
114
116
|
* leave `ui_audit` without the `greenfield == True` +
|
|
115
|
-
* `greenfield_decision
|
|
117
|
+
* `greenfield_decision` ∈ `{scaffold, granularity_convention}` pair.
|
|
116
118
|
*/
|
|
117
119
|
function _is_greenfield_scaffold(state: DeliveryState): boolean {
|
|
118
120
|
const audit = state.ui_audit;
|
|
119
121
|
if (!_isDict(audit)) return false;
|
|
122
|
+
// `granularity_convention` is option 4 — a scaffold that additionally
|
|
123
|
+
// organises what it creates under a named convention, so it takes the same
|
|
124
|
+
// grounding pass. Kept in step with the identical guard in `scaffold`.
|
|
120
125
|
return (
|
|
121
126
|
audit['greenfield'] === true &&
|
|
122
|
-
audit['greenfield_decision'] === 'scaffold'
|
|
127
|
+
(audit['greenfield_decision'] === 'scaffold' ||
|
|
128
|
+
audit['greenfield_decision'] === GRANULARITY_CONVENTION)
|
|
123
129
|
);
|
|
124
130
|
}
|
|
125
131
|
|