@event4u/agent-config 16.0.0 → 16.2.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 +289 -140
- package/CONTRIBUTING.md +9 -0
- package/README.md +2 -2
- package/dist/agent-src/commands/analyze/inbox.md +26 -0
- package/dist/agent-src/commands/analyze/roadmap-repos.md +27 -0
- package/dist/agent-src/commands/challenge-me/closure.md +178 -0
- package/dist/agent-src/commands/challenge-me.md +9 -2
- package/dist/agent-src/commands/council/default.md +25 -5
- package/dist/agent-src/commands/feature/plan.md +28 -1
- package/dist/agent-src/commands/feature/roadmap.md +28 -1
- package/dist/agent-src/commands/implement-ticket.md +27 -0
- package/dist/agent-src/commands/jira-ticket.md +27 -0
- package/dist/agent-src/commands/pr/create.md +29 -0
- package/dist/agent-src/commands/pr/merge.md +60 -9
- package/dist/agent-src/commands/roadmap/ai-council.md +7 -1
- package/dist/agent-src/commands/roadmap/create.md +74 -27
- package/dist/agent-src/commands/roadmap/materialize.md +27 -0
- package/dist/agent-src/commands/roadmap/process-full.md +123 -18
- package/dist/agent-src/commands/team.md +22 -0
- package/dist/agent-src/commands/work.md +4 -0
- package/dist/agent-src/contexts/authority/scope-growth-ownership.md +80 -0
- package/dist/agent-src/contexts/communication/rules-auto/user-interaction-mechanics.md +47 -0
- package/dist/agent-src/contexts/execution/auto-orchestration-activation.md +44 -3
- package/dist/agent-src/contexts/execution/autonomy-mechanics.md +19 -23
- package/dist/agent-src/contexts/execution/decision-closure-execution.md +93 -0
- package/dist/agent-src/contexts/execution/fix-loop-ladder.md +108 -0
- package/dist/agent-src/contexts/execution/plan-confidence-gate.md +4 -2
- package/dist/agent-src/contexts/execution/roadmap-process-loop.md +75 -6
- package/dist/agent-src/guidelines/agent-infra/active-remediation-mechanics.md +57 -0
- package/dist/agent-src/guidelines/agent-infra/evaluator-independence-mechanics.md +102 -0
- package/dist/agent-src/guidelines/design-fidelity-routing.md +29 -0
- package/dist/agent-src/rules/autonomous-execution.md +15 -8
- package/dist/agent-src/rules/delegation-policy.md +23 -45
- package/dist/agent-src/rules/design-fidelity.md +32 -37
- package/dist/agent-src/rules/evaluator-independence.md +43 -49
- package/dist/agent-src/rules/test-first.md +41 -0
- package/dist/agent-src/rules/ui-audit-gate.md +1 -2
- package/dist/agent-src/skills/accessibility-auditor/data/aria-patterns.csv +1 -1
- package/dist/agent-src/skills/accessibility-auditor/data/manifest.json +3 -3
- package/dist/agent-src/skills/ai-council/SKILL.md +11 -3
- package/dist/agent-src/skills/api-design/data/manifest.json +3 -3
- package/dist/agent-src/skills/database/data/manifest.json +4 -4
- package/dist/agent-src/skills/database/data/query-tuning.csv +3 -3
- package/dist/agent-src/skills/design-review/SKILL.md +80 -4
- package/dist/agent-src/skills/design-review/references/verification-automation.md +32 -0
- package/dist/agent-src/skills/existing-ui-audit/SKILL.md +30 -5
- package/dist/agent-src/skills/existing-ui-audit/references/component-taxonomy-detection.md +56 -0
- package/dist/agent-src/skills/experiment-loop/SKILL.md +31 -1
- package/dist/agent-src/skills/markitdown/SKILL.md +4 -0
- package/dist/agent-src/skills/playwright-testing/SKILL.md +30 -6
- package/dist/agent-src/skills/roadmap-writing/SKILL.md +1 -1
- package/dist/agent-src/skills/storybook-workshop/SKILL.md +42 -3
- package/dist/agent-src/skills/threat-modeling/SKILL.md +9 -4
- package/dist/agent-src/skills/threat-modeling/data/manifest.json +4 -4
- package/dist/agent-src/skills/ui-component-architect/SKILL.md +23 -0
- package/dist/agent-src/skills/verify-repair-loop/SKILL.md +37 -3
- package/dist/agent-src/templates/agent-settings.md +1 -1
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/roadmaps.md +218 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/backend/_self_fix.ts +62 -2
- package/dist/agent-src/templates/scripts/work_engine/directives/backend/test.ts +1 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +1 -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 +260 -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/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-delegate/check_update_banner.js +40 -2
- package/dist/cli-delegate/chunk-4E2W63DA.js +335 -0
- package/dist/cli-delegate/{chunk-S3VFXMTM.js → chunk-4XFP2Y3E.js} +1 -1
- package/dist/cli-delegate/chunk-5R7HOLAF.js +99 -0
- package/dist/cli-delegate/{chunk-IVBPRCQO.js → chunk-6KFEC3G7.js} +1 -1
- package/dist/cli-delegate/{chunk-2TAQ2K4V.js → chunk-6KM6ORRY.js} +55 -386
- package/dist/cli-delegate/{chunk-AK6HODNQ.js → chunk-7XGBX6ZH.js} +973 -555
- package/dist/cli-delegate/{chunk-2XY7ILBT.js → chunk-FC75PGJE.js} +42 -2
- package/dist/cli-delegate/{chunk-55ACLDUE.js → chunk-FP36SWJD.js} +587 -141
- package/dist/cli-delegate/{chunk-3FKR64R5.js → chunk-IGD6ERX6.js} +62 -7
- package/dist/cli-delegate/{chunk-GYC3VRYN.js → chunk-JNMVLWLR.js} +99 -14
- package/dist/cli-delegate/{chunk-H32DGUJH.js → chunk-P6ZHP5W2.js} +1 -1
- package/dist/cli-delegate/{chunk-57PN4GYJ.js → chunk-RGNIWTEA.js} +1 -1
- package/dist/cli-delegate/chunk-ROYYTEZU.js +39 -0
- package/dist/cli-delegate/{chunk-2DK2VJWG.js → chunk-WGXTVKCQ.js} +20 -6
- package/dist/cli-delegate/chunk-YDPILCOL.js +152 -0
- package/dist/cli-delegate/{chunk-QJWAUMJW.js → chunk-YJ72UIAK.js} +730 -15
- 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 +985 -831
- package/dist/cli-delegate/cmd_doctor.js +7 -5
- package/dist/cli-delegate/cmd_explain.js +2 -2
- package/dist/cli-delegate/cmd_export.js +9 -7
- package/dist/cli-delegate/cmd_fleet.js +4 -2
- package/dist/cli-delegate/cmd_handoff.js +7 -7
- 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_preflight.js +4 -2
- package/dist/cli-delegate/cmd_prune.js +10 -8
- 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 -4
- package/dist/cli-delegate/cmd_settings_get.js +28 -2
- package/dist/cli-delegate/cmd_settings_migrate.js +9 -7
- package/dist/cli-delegate/cmd_settings_set.js +1 -1
- package/dist/cli-delegate/cmd_sync.js +10 -8
- package/dist/cli-delegate/cmd_uninstall.js +16 -13
- 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 +12 -10
- package/dist/cli-delegate/cmd_versions.js +1 -1
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +90 -43
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +4 -4
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +10 -8
- package/dist/discovery/trust-report.md +3 -3
- package/dist/discovery/workspaces.json +8 -6
- package/dist/hooks/dispatch.js +7682 -2772
- package/dist/hooks/dispatch.sha256 +1 -0
- package/dist/install/claudeRuleRewrite.js +14 -3
- package/dist/install/conflict.js +60 -10
- package/dist/install/conflictTracker.js +218 -0
- package/dist/install/fsPrimitives.js +54 -0
- package/dist/install/install.mjs +2200 -1559
- package/dist/install/manifestFiles.js +259 -0
- package/dist/install/preflight.js +14 -2
- package/dist/install/preserve.js +157 -0
- package/dist/install/recordedOwnership.js +132 -0
- package/dist/install/txlog.js +11 -2
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +3066 -1470
- package/dist/router.json +1 -1
- package/dist/scripts/_lib/agent_settings.js +3 -2
- package/dist/scripts/_lib/fs_atomic.js +167 -0
- package/dist/scripts/_lib/installed_tools.js +460 -0
- package/dist/scripts/_lib/lean_projection_mode.js +3 -2
- package/dist/scripts/_lib/settings_renamed_keys.js +78 -0
- package/dist/server/routes/install.js +8 -0
- package/dist/server/routes/wizard.js +9 -3
- package/dist/server/schemas/settings.js +40 -5
- package/dist/shared/missionExecution.js +97 -0
- 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/MIGRATION.md +103 -0
- package/docs/contracts/settings-classes.md +28 -7
- package/docs/guidelines/agent-infra/active-remediation-mechanics.md +57 -0
- package/docs/guidelines/agent-infra/evaluator-independence-mechanics.md +102 -0
- package/docs/guidelines/design-fidelity-routing.md +29 -0
- package/package.json +4 -4
- package/src/agent-src/templates/scripts/work_engine/directives/backend/_self_fix.ts +62 -2
- package/src/agent-src/templates/scripts/work_engine/directives/backend/test.ts +1 -0
- package/src/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +1 -0
- 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 +260 -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/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 +168 -27
- package/src/config/auto-rule-budget.json +16 -0
- package/src/config/ci-local-parity.yml +36 -5
- package/src/config/continuity-surface.json +23 -2
- package/src/config/gate-coverage.yml +377 -13
- package/src/config/gate-violation-baselines.json +10 -6
- package/src/config/hook-latency-budget.json +21 -0
- package/src/config/hook-token-budget.json +4 -2
- package/src/config/loop-surfaces.yaml +215 -0
- package/src/config/metric-registry.yml +114 -0
- package/src/config/placeholder-drift-budget.json +10 -0
- package/src/config/platform-anchor.json +3 -2
- package/src/config/release-gate-locality.yml +11 -0
- package/src/config/routing-coverage-seed.json +33 -5
- package/src/config/rule-enforcement-baseline.json +0 -1
- package/src/install/claudeRuleRewrite.ts +16 -2
- package/src/install/conflict.ts +65 -9
- package/src/install/conflictTracker.ts +299 -0
- package/src/install/fsPrimitives.ts +54 -0
- package/src/install/manifestFiles.ts +312 -0
- package/src/install/preflight.ts +16 -2
- package/src/install/preserve.ts +205 -0
- package/src/install/recordedOwnership.ts +149 -0
- package/src/install/txlog.ts +11 -2
- package/src/install/types.ts +19 -4
- package/src/scripts/_cli/cmd_conformance.ts +88 -15
- package/src/scripts/_cli/cmd_doctor.ts +7 -20
- package/src/scripts/_cli/cmd_route_explain.ts +9 -2
- package/src/scripts/_cli/cmd_settings_get.ts +44 -0
- package/src/scripts/_cli/doctor_execution.ts +173 -0
- package/src/scripts/_cli/doctor_network_posture.ts +226 -0
- package/src/scripts/_lib/activation_payload.ts +247 -0
- package/src/scripts/_lib/agent_settings.ts +4 -2
- package/src/scripts/_lib/authority_path.ts +102 -0
- package/src/scripts/_lib/body_portable.ts +102 -0
- package/src/scripts/_lib/cascade_base.ts +94 -0
- package/src/scripts/_lib/cc_transcript.ts +132 -1
- package/src/scripts/_lib/changelog_eras.ts +7 -2
- package/src/scripts/_lib/concern_sla_window.ts +200 -0
- package/src/scripts/_lib/continuation_ladder.ts +149 -2
- package/src/scripts/_lib/council_transport.ts +129 -0
- package/src/scripts/_lib/delivery_ready.ts +112 -0
- package/src/scripts/_lib/forge_protection.ts +381 -0
- package/src/scripts/_lib/forge_reader.ts +558 -0
- package/src/scripts/_lib/hook_platform_keys.ts +27 -0
- package/src/scripts/_lib/host_env_write.ts +111 -0
- package/src/scripts/_lib/json_python_parity.ts +127 -0
- package/src/scripts/_lib/lean_projection_mode.ts +14 -3
- package/src/scripts/_lib/llm_proposer_transport.ts +14 -4
- package/src/scripts/_lib/loop_surfaces.ts +382 -0
- package/src/scripts/_lib/mission_record.ts +190 -0
- package/src/scripts/_lib/obligation_frequency.ts +217 -0
- package/src/scripts/_lib/obligations.ts +513 -0
- package/src/scripts/_lib/orchestration_record.ts +11 -20
- package/src/scripts/_lib/probe_inputs.ts +271 -0
- package/src/scripts/_lib/read_surface_scan.ts +322 -0
- package/src/scripts/_lib/release_highlights.ts +201 -11
- package/src/scripts/_lib/release_holds.ts +493 -0
- package/src/scripts/_lib/release_migration_gate.ts +184 -0
- package/src/scripts/_lib/retrieval_sanitize.ts +77 -16
- package/src/scripts/_lib/rides_along.ts +102 -0
- package/src/scripts/_lib/settings_renamed_keys.ts +82 -0
- package/src/scripts/_lib/shell_write_shapes.ts +108 -0
- package/src/scripts/_lib/structural_hiding.ts +622 -0
- package/src/scripts/_lib/test_delta.ts +166 -0
- package/src/scripts/_lib/test_provenance.ts +171 -0
- package/src/scripts/_lib/turn_end_refusals.ts +525 -4
- package/src/scripts/_lib/turn_end_transcript.ts +216 -0
- package/src/scripts/_lib/typed_op_grant.ts +246 -0
- package/src/scripts/_lib/typed_op_watch.ts +185 -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/ai_council/config.ts +8 -11
- package/src/scripts/ai_council/fallback_config.ts +5 -3
- package/src/scripts/ai_council/ownership_classes.ts +118 -0
- package/src/scripts/ai_team/team_dispatch.ts +4 -0
- package/src/scripts/ask_block_census.ts +285 -15
- package/src/scripts/before_complete_hook.ts +340 -23
- package/src/scripts/bench_hook_latency.ts +412 -5
- 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 +866 -0
- package/src/scripts/check_finding_dispositions.ts +22 -3
- package/src/scripts/check_gate_reachability.ts +173 -10
- package/src/scripts/check_generator_sync.ts +1025 -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 +47 -5
- package/src/scripts/check_kill_switch_table.ts +294 -0
- package/src/scripts/check_placeholder_drift.ts +221 -0
- package/src/scripts/check_preamble_payload_budget.ts +75 -2
- package/src/scripts/check_read_surface_coverage.ts +515 -0
- package/src/scripts/check_release_highlights.ts +33 -1
- package/src/scripts/check_release_holds.ts +568 -0
- package/src/scripts/check_routing_coverage.ts +378 -11
- package/src/scripts/check_rule_projection_integrity.ts +22 -12
- package/src/scripts/check_static_parity.ts +17 -0
- package/src/scripts/check_test_delta.ts +294 -0
- package/src/scripts/check_test_weakening.ts +299 -0
- package/src/scripts/ci_settle.ts +145 -19
- package/src/scripts/closure_scan.ts +447 -0
- package/src/scripts/compile_hook_manifest.ts +102 -18
- package/src/scripts/council_record_shape.ts +209 -0
- package/src/scripts/external_sources_denylist.json +29 -4
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +127 -11
- package/src/scripts/hooks/block_config_weakening.ts +229 -4
- package/src/scripts/hooks/block_kernel_rule_writes.ts +9 -78
- package/src/scripts/hooks/block_plumbing_writes.ts +314 -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 +1 -2
- package/src/scripts/hooks/comment_discipline_hook.ts +1 -3
- package/src/scripts/hooks/concern_registry.ts +6 -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 +221 -5
- package/src/scripts/hooks/design_slop_hook.ts +1 -2
- package/src/scripts/hooks/dispatch_hook.ts +25 -19
- 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 +97 -2
- package/src/scripts/hooks/exit_codes.ts +128 -0
- package/src/scripts/hooks/host_lowering.json +1 -0
- package/src/scripts/hooks/host_lowering.ts +128 -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 +539 -0
- package/src/scripts/hooks/obligation_settle_hook.ts +328 -0
- package/src/scripts/hooks/one_question_per_ask_hook.ts +25 -4
- package/src/scripts/hooks/orchestration_record_hook.ts +1 -2
- 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 +55 -4
- package/src/scripts/hooks/run_continuation_hook.ts +30 -35
- 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 +49 -0
- package/src/scripts/hooks/telemetry_flush_hook.ts +1 -2
- package/src/scripts/hooks/telemetry_usage_hook.ts +1 -2
- package/src/scripts/hooks/tool_result_bytes_hook.ts +93 -9
- package/src/scripts/hooks/turn_end_gate_hook.ts +337 -324
- package/src/scripts/hooks/ui_route_nudge_hook.ts +1 -2
- package/src/scripts/hooks_doctor.ts +85 -0
- package/src/scripts/hooks_status.ts +19 -0
- package/src/scripts/install.ts +109 -210
- package/src/scripts/janitor.ts +7 -0
- package/src/scripts/lint_decision_classes.ts +464 -0
- 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 +66 -0
- package/src/scripts/lint_major_migration_sections.ts +450 -0
- package/src/scripts/lint_plan_risk_register.ts +47 -3
- package/src/scripts/lint_roadmap_blockers.ts +139 -12
- package/src/scripts/lint_roadmap_producers.ts +202 -0
- package/src/scripts/lint_skill_descriptions.ts +1 -1
- package/src/scripts/lint_skill_scripts_readonly.ts +1 -1
- package/src/scripts/mcp_server/prompts.ts +142 -1
- package/src/scripts/measure_rule_budget.ts +101 -5
- package/src/scripts/measure_skill_ranker_baseline.ts +305 -51
- package/src/scripts/measure_turn_end_gate.ts +193 -0
- package/src/scripts/memory_lookup.ts +1 -1
- package/src/scripts/new_roadmap.ts +37 -0
- package/src/scripts/orchestration_record.ts +0 -5
- package/src/scripts/prepack-check.mjs +53 -0
- package/src/scripts/release.ts +14 -98
- package/src/scripts/release_drill.ts +267 -1
- package/src/scripts/release_publication.ts +64 -1
- package/src/scripts/report_enforcement_drift.ts +566 -0
- package/src/scripts/report_host_injection_effect.ts +3 -11
- package/src/scripts/report_invocation_surface.ts +383 -0
- package/src/scripts/report_obligation_carriers.ts +699 -0
- package/src/scripts/report_obligation_writer_split.ts +236 -0
- package/src/scripts/report_skill_menu_census.ts +208 -0
- package/src/scripts/report_standing_payload_by_host.ts +26 -152
- package/src/scripts/roadmap_verify_share.ts +213 -0
- package/src/scripts/schemas/agent-settings.schema.json +23 -0
- package/src/scripts/schemas/command.schema.json +48 -0
- package/src/scripts/schemas/review-findings.schema.json +4 -0
- package/src/scripts/schemas/skill.schema.json +44 -0
- package/src/scripts/scope_growth.ts +219 -0
- package/src/scripts/self_review_gate.ts +359 -10
- package/src/scripts/semantic_parity_census.ts +314 -0
- package/src/scripts/session_eol_report.ts +54 -1
- package/src/scripts/sweep_dead_scan_roots.ts +1 -1
- package/src/scripts/trigger_eval_grandfather.json +0 -3
- package/src/scripts/trigger_eval_rotation.ts +122 -27
- package/src/scripts/ui_conformance_probe.ts +774 -0
- package/src/scripts/update_prices.ts +85 -3
- package/src/scripts/write_bundle_digest.mjs +74 -0
- package/src/server/schemas/settings.ts +62 -7
- package/src/shared/missionExecution.ts +126 -0
- package/src/templates/consumer-settings/ONBOARDING.md +1 -0
- package/dist/cli-delegate/chunk-523HCFYO.js +0 -90
- package/dist/ui/assets/index-D0jaCRPM.js +0 -29
- package/dist/ui/assets/index-jSfMW8_t.css +0 -1
- /package/dist/cli-delegate/{chunk-YUM5KURG.js → chunk-7RQP4UDH.js} +0 -0
|
@@ -23,6 +23,7 @@ import * as path from 'node:path';
|
|
|
23
23
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
24
24
|
|
|
25
25
|
import { DEFAULT_PRICES, as_rows } from './ai_council/_default_prices.js';
|
|
26
|
+
import { sanitize_text } from './_lib/retrieval_sanitize.js';
|
|
26
27
|
import { PRICES_FILE, _render_markdown, is_stale, load_prices } from './ai_council/pricing.js';
|
|
27
28
|
|
|
28
29
|
const _HERE = fileURLToPath(import.meta.url);
|
|
@@ -39,6 +40,40 @@ type Json = any;
|
|
|
39
40
|
// from the LiteLLM payload. set(DEFAULT_PRICES.keys()) → "provider model" keys.
|
|
40
41
|
const ALLOW_LIST: ReadonlySet<string> = new Set(DEFAULT_PRICES.keys());
|
|
41
42
|
|
|
43
|
+
/**
|
|
44
|
+
* The only shape a remote identifier may have to be considered at all.
|
|
45
|
+
*
|
|
46
|
+
* Pure ASCII letters, digits and the punctuation real provider/model names use.
|
|
47
|
+
* Every allow-list entry is ASCII, so nothing outside this can be a member —
|
|
48
|
+
* and asserting it on the UNTOUCHED bytes is what makes the case fold below
|
|
49
|
+
* safe, because within ASCII folding is lossless. A Unicode character that
|
|
50
|
+
* folds onto an ASCII letter never reaches the comparison.
|
|
51
|
+
*/
|
|
52
|
+
const _CANONICAL_ID = /^[A-Za-z0-9._-]+$/;
|
|
53
|
+
|
|
54
|
+
/** ASCII-only case fold — never `toLowerCase`, which folds Unicode too. */
|
|
55
|
+
function _asciiLower(s: string): string {
|
|
56
|
+
return s.replace(/[A-Z]/g, (c) => String.fromCharCode(c.charCodeAt(0) + 32));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Report a rejected identifier that WOULD have matched after transformation.
|
|
61
|
+
*
|
|
62
|
+
* A raw miss whose normalised form hits the allow list is a different event
|
|
63
|
+
* from an ordinary unlisted name, and printing both as the same silence is what
|
|
64
|
+
* would hide an admission attempt. Ordinary misses stay silent — the fetched
|
|
65
|
+
* catalogue carries hundreds of models nobody here lists.
|
|
66
|
+
*/
|
|
67
|
+
function _reportCollision(rawProvider: string, rawModel: string): void {
|
|
68
|
+
const normalised = `${sanitize_text(rawProvider).toLowerCase()} ${sanitize_text(rawModel)}`;
|
|
69
|
+
if (!ALLOW_LIST.has(normalised)) return;
|
|
70
|
+
process.stderr.write(
|
|
71
|
+
'update_prices: DROPPED a remote row whose raw identifier is not allow-listed ' +
|
|
72
|
+
`but normalises onto \`${normalised}\`. A fetched name that folds or sanitizes ` +
|
|
73
|
+
'onto a listed one is an admission attempt, not a typo.\n',
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
42
77
|
/**
|
|
43
78
|
* Synchronous HTTPS GET so the CLI stays a straight-line script (Python uses
|
|
44
79
|
* a blocking urlopen). Returns parsed JSON dict, or null on any failure
|
|
@@ -99,13 +134,60 @@ export function _toRowsFromLitellm(
|
|
|
99
134
|
if (entry === null || typeof entry !== 'object' || Array.isArray(entry)) {
|
|
100
135
|
continue;
|
|
101
136
|
}
|
|
102
|
-
|
|
137
|
+
// Sanitize BEFORE the allow-list compare, not after. These two strings
|
|
138
|
+
// come off the wire and end up in a tracked markdown file that agents
|
|
139
|
+
// read, so they are the model-facing copy this floor exists for. Doing
|
|
140
|
+
// it before the compare is also the only order that works: a vector
|
|
141
|
+
// inside a model name would otherwise fail the allow-list lookup and
|
|
142
|
+
// drop the row, turning an injection attempt into a silent data loss.
|
|
143
|
+
// The fetched payload itself is never written anywhere — only this
|
|
144
|
+
// rendering is transformed.
|
|
145
|
+
const rawProvider = String((entry.litellm_provider as Json) ?? '');
|
|
103
146
|
// LiteLLM keys are sometimes "provider/model"; strip the prefix.
|
|
104
147
|
const slash = key.indexOf('/');
|
|
105
|
-
const
|
|
106
|
-
|
|
148
|
+
const rawModel = slash !== -1 ? key.slice(slash + 1) : key;
|
|
149
|
+
|
|
150
|
+
// THE ADMISSION BOUNDARY: a canonical ASCII grammar first, then a
|
|
151
|
+
// comparison on values nothing has transformed.
|
|
152
|
+
//
|
|
153
|
+
// Two earlier orders were both wrong and the second is the instructive
|
|
154
|
+
// one. The first sanitized before comparing, so a poisoned name could
|
|
155
|
+
// normalise onto a listed one and be admitted as it. The fix compared
|
|
156
|
+
// "raw" values — but `.toLowerCase()` ran before the compare, and THAT
|
|
157
|
+
// IS ITSELF A LOSSY UNICODE TRANSFORM: the Kelvin sign and the Turkish
|
|
158
|
+
// dotted capital both fold onto ASCII letters, so the provider field
|
|
159
|
+
// still carried the collision the model field no longer did. An
|
|
160
|
+
// independent review named it and was right; closing one field and
|
|
161
|
+
// calling the class closed is the failure mode, not the typo.
|
|
162
|
+
//
|
|
163
|
+
// The reachable fold is ONE character: `U+212A KELVIN SIGN -> k`.
|
|
164
|
+
// Measured, not recalled — U+212B ANGSTROM folds to `å`, which is not
|
|
165
|
+
// ASCII, and an earlier note here claimed otherwise. No provider in the
|
|
166
|
+
// current list carries a `k`, so this boundary guards nothing reachable
|
|
167
|
+
// TODAY; it guards the day one is added, which is the only time a
|
|
168
|
+
// boundary of this shape can be added without a migration.
|
|
169
|
+
//
|
|
170
|
+
// So the grammar is asserted on the UNTOUCHED bytes. Pure ASCII, with
|
|
171
|
+
// the punctuation real identifiers use. Nothing outside it can be an
|
|
172
|
+
// allow-list member, because every entry is ASCII — and within ASCII,
|
|
173
|
+
// case folding is lossless, which is what makes the fold below safe to
|
|
174
|
+
// apply after the gate rather than before it.
|
|
175
|
+
if (!_CANONICAL_ID.test(rawProvider) || !_CANONICAL_ID.test(rawModel)) {
|
|
176
|
+
_reportCollision(rawProvider, rawModel);
|
|
107
177
|
continue;
|
|
108
178
|
}
|
|
179
|
+
const provider = _asciiLower(rawProvider);
|
|
180
|
+
if (!ALLOW_LIST.has(`${provider} ${rawModel}`)) {
|
|
181
|
+
_reportCollision(rawProvider, rawModel);
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Only now, and only for the rendering: the row reaches a tracked
|
|
186
|
+
// markdown file that agents read, so the model-facing copy carries the
|
|
187
|
+
// floor. The fetched payload itself is never written anywhere. Both
|
|
188
|
+
// values are already canonical ASCII here, so this is a no-op in
|
|
189
|
+
// practice and a belt on the rendering in principle.
|
|
190
|
+
const model = sanitize_text(rawModel);
|
|
109
191
|
const inCost = entry.input_cost_per_token;
|
|
110
192
|
const outCost = entry.output_cost_per_token;
|
|
111
193
|
if (!_isNumber(inCost) || !_isNumber(outCost)) {
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* write_bundle_digest.mjs — the sidecar `dist/hooks/dispatch.sha256`.
|
|
4
|
+
*
|
|
5
|
+
* Step 3.1 of `road-to-a-kernel-that-guards-its-plumbing`. The dispatcher
|
|
6
|
+
* verifies at runtime that the bundle it is executing is the bundle the build
|
|
7
|
+
* produced, and it needs something to compare against. This writes that
|
|
8
|
+
* something, in the same `npm run build:hooks` invocation that writes the
|
|
9
|
+
* bundle, so the two cannot be produced separately and cannot disagree.
|
|
10
|
+
*
|
|
11
|
+
* Plain `.mjs` rather than a TS script under `scripts-run`: it is chained into
|
|
12
|
+
* `build:hooks`, which runs before anything is compiled and on machines where
|
|
13
|
+
* a `tsx` startup is pure cost. `prepack-check.mjs` sets the precedent.
|
|
14
|
+
*
|
|
15
|
+
* Format is one line, `<64 hex> <basename>`, i.e. what `shasum -a 256`
|
|
16
|
+
* emits — so an operator can verify the claim with a tool they already have
|
|
17
|
+
* instead of trusting this script:
|
|
18
|
+
*
|
|
19
|
+
* shasum -a 256 -c dist/hooks/dispatch.js.sha256
|
|
20
|
+
*
|
|
21
|
+
* This is NOT a signature and does not pretend to be. Anyone who can rewrite
|
|
22
|
+
* the bundle can rewrite the sidecar beside it. What it defends against is the
|
|
23
|
+
* hand edit — a bundle changed in place between builds, which until now
|
|
24
|
+
* survived until the next build, reached every dispatch meanwhile, and was
|
|
25
|
+
* invisible in a source review. `block_plumbing_writes` refuses that edit at
|
|
26
|
+
* tool-call time; this catches one that arrived by some other route.
|
|
27
|
+
*/
|
|
28
|
+
import { createHash } from 'node:crypto';
|
|
29
|
+
import { readFileSync, writeFileSync } from 'node:fs';
|
|
30
|
+
import { basename, resolve } from 'node:path';
|
|
31
|
+
import { argv, exit, stderr, stdout } from 'node:process';
|
|
32
|
+
|
|
33
|
+
const bundle = resolve(argv[2] ?? 'dist/hooks/dispatch.js');
|
|
34
|
+
// `dispatch.sha256`, not `dispatch.js.sha256` — the name the roadmap step
|
|
35
|
+
// wrote. Either works with `shasum -c`, which reads the subject filename from
|
|
36
|
+
// INSIDE the file rather than from the sidecar's own name, so the choice is
|
|
37
|
+
// free and the step's spelling wins.
|
|
38
|
+
const sidecar = bundle.replace(/\.js$/u, '') + '.sha256';
|
|
39
|
+
|
|
40
|
+
let bytes;
|
|
41
|
+
try {
|
|
42
|
+
bytes = readFileSync(bundle);
|
|
43
|
+
} catch (err) {
|
|
44
|
+
stderr.write(`write_bundle_digest: cannot read ${bundle}: ${err.message}\n`);
|
|
45
|
+
// Exit non-zero: a build that produced no bundle must not report success,
|
|
46
|
+
// and a sidecar written from a missing file would be a digest of nothing.
|
|
47
|
+
exit(1);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const digest = createHash('sha256').update(bytes).digest('hex');
|
|
51
|
+
writeFileSync(sidecar, `${digest} ${basename(bundle)}\n`, 'utf-8');
|
|
52
|
+
|
|
53
|
+
// Read back what was just written and confirm it describes the bundle beside
|
|
54
|
+
// it. An independent review called a post-build verification the
|
|
55
|
+
// highest-leverage addition here, and the reason is the runtime posture: a
|
|
56
|
+
// MISSING or unreadable sidecar is `unverifiable` at dispatch time and ALLOWS,
|
|
57
|
+
// deliberately, so that a consumer whose package predates the sidecar is not
|
|
58
|
+
// wedged. That choice means a half-written or unreadable sidecar degrades the
|
|
59
|
+
// check silently instead of failing anything.
|
|
60
|
+
//
|
|
61
|
+
// `prepack-check.mjs` catches it at packaging time, which covers the published
|
|
62
|
+
// tarball and nothing else. This covers every path that produces a bundle at
|
|
63
|
+
// all — local build, CI build, packaging — because it is part of producing one.
|
|
64
|
+
// It costs one re-read of 78 bytes.
|
|
65
|
+
const readBack = readFileSync(sidecar, 'utf-8');
|
|
66
|
+
const claimed = /^([0-9a-f]{64})\s/u.exec(readBack.trim())?.[1] ?? null;
|
|
67
|
+
if (claimed !== digest) {
|
|
68
|
+
stderr.write(
|
|
69
|
+
`write_bundle_digest: wrote ${sidecar} but read back ${claimed ?? '(unparseable)'} ` +
|
|
70
|
+
`instead of ${digest} — the sidecar does not describe the bundle it was written for.\n`,
|
|
71
|
+
);
|
|
72
|
+
exit(1);
|
|
73
|
+
}
|
|
74
|
+
stdout.write(`write_bundle_digest: ${digest} ${basename(bundle)} (${String(bytes.length)} bytes, verified)\n`);
|
|
@@ -36,6 +36,8 @@ const leanProjectionHost = z.enum(['claude-code', 'cursor', 'cline']);
|
|
|
36
36
|
const projectionMode = z.enum(['legacy-all', 'scoped']);
|
|
37
37
|
const memoryCadence = z.enum(['auto', 'always', 'never']);
|
|
38
38
|
const projectAudience = z.enum(['self', 'internal', 'client', 'public']);
|
|
39
|
+
const deliveryMerge = z.enum(['off', 'on-green']);
|
|
40
|
+
const prTopology = z.enum(['single', 'stacked']);
|
|
39
41
|
|
|
40
42
|
export const settingsSchema = z.object({
|
|
41
43
|
agent_config_version: z.string().default('').describe(
|
|
@@ -65,7 +67,7 @@ export const settingsSchema = z.object({
|
|
|
65
67
|
),
|
|
66
68
|
lean_projection: z.object({
|
|
67
69
|
mode: leanProjectionMode.default('eager-all').describe(
|
|
68
|
-
'How the per-tool projector emits the rule layer. eager-all = every rule body inlined into every projection (safe; what an ABSENT key still resolves to, per ADR-267 decision point 4). thin = kernel rules full-bodied + non-kernel rules as router-resolved pointers (~45k GPT-tok lighter per session), with no delivery mechanism. delivery = thin stubs PLUS the rule-inject hook concern, which delivers a body back on a trigger match; this is the value the SHIPPED TEMPLATE carries for Claude Code since ADR-267, and the
|
|
70
|
+
'How the per-tool projector emits the rule layer. eager-all = every rule body inlined into every projection (safe; what an ABSENT key still resolves to, per ADR-267 decision point 4). thin = kernel rules full-bodied + non-kernel rules as router-resolved pointers (~45k GPT-tok lighter per session, exact-BPE — a different unit from the chars/4 figures below, never compare the two directly), with no delivery mechanism. delivery = thin stubs PLUS the rule-inject hook concern, which delivers a body back on a trigger match; this is the value the SHIPPED TEMPLATE carries for Claude Code since ADR-267. SAVING AND CHARGE, MEASURED TOGETHER so neither is published alone (2026-09-12, `check_preamble_payload_budget`): the rule bucket falls 122,769 -> 24,537 chars/4 tok per session on a thinned host (-80.0%), and a trigger match costs p50 6,728 B / p90 14,016 B / max 16,297 B per fire over 318 gate-open fires of the frozen tests/eval/routing-matrix corpus at the concern\'s 16,384 B cap. Bytes per fire and tokens per session are different denominators and are never summed; re-read both rather than quoting this line. The ceiling for that charge is registered in src/config/hook-token-budget.json (user_prompt_submit slot sum 4,096 -> 16,384).',
|
|
69
71
|
),
|
|
70
72
|
hosts: z.array(leanProjectionHost).default(['claude-code']).describe(
|
|
71
73
|
'Which hosts a thinning mode may thin (ADR-267). Absent resolves to [claude-code]. '
|
|
@@ -161,6 +163,48 @@ export const settingsSchema = z.object({
|
|
|
161
163
|
'How the agent replies to PR review comments. create_review_comment = post a new review comment (works on every GitHub plan). replies_endpoint = thread the reply under the original comment (needs the newer REST endpoint). auto = detect at runtime, prefer threaded replies when available.',
|
|
162
164
|
),
|
|
163
165
|
}),
|
|
166
|
+
delivery: z.object({
|
|
167
|
+
merge: deliveryMerge.default('off').describe(
|
|
168
|
+
'Whether a run may merge the pull request it produced. off (default) = the run ends at mergeable-green-and-open and says so. on-green = merge is permitted, and only when an object-bound grant covering {op: prod_merge, target: <base>} exists and the final head is required-check-green, target-current and tamper-checked. This key is a precondition, never the authorisation by itself; forge auto-merge is the mechanism, so branch protection stays the gate.',
|
|
169
|
+
),
|
|
170
|
+
wait_for_ci: z.boolean().default(true).describe(
|
|
171
|
+
'Whether the run stays alive until the required checks settle. true (default) = the run drives CI and reports the settled verdict. false = the run ends once the branch is pushed and the PR is open, leaving the checks to be read later. Independent of merge: a run may wait for CI without being allowed to merge.',
|
|
172
|
+
),
|
|
173
|
+
pr_topology: prTopology.default('single').describe(
|
|
174
|
+
'How a mission\'s work is shaped into pull requests. single (default) = one branch, one pull request. stacked = a dependent series. stacked is never chosen by the agent and never asked about at roadmap creation — the owner plans it or it does not happen.',
|
|
175
|
+
),
|
|
176
|
+
}),
|
|
177
|
+
/**
|
|
178
|
+
* What this package may write into the HOST's own environment.
|
|
179
|
+
*
|
|
180
|
+
* THE GUARANTEE IS THE SHAPE, not a check. Only two keys exist here, and
|
|
181
|
+
* both are request-SIZE caps. Neither traffic variable is expressible —
|
|
182
|
+
* `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` and `DISABLE_AUTOUPDATER` both
|
|
183
|
+
* reach the host's update-disabled resolver (the blanket one as its third
|
|
184
|
+
* rung, measured on Claude Code 2.1.284), so a profile able to write either
|
|
185
|
+
* could disable a consumer's security updates. Owner-decided 2026-09-30:
|
|
186
|
+
* they are not writable through this package at all, and the strongest way
|
|
187
|
+
* to hold that is a schema that cannot say them rather than an exclusion
|
|
188
|
+
* list somebody has to maintain.
|
|
189
|
+
*
|
|
190
|
+
* `null` is the default on both, and it is the off switch: nothing is
|
|
191
|
+
* written. There is no separate enable flag, because a flag plus a value is
|
|
192
|
+
* two ways to say off and one of them would drift.
|
|
193
|
+
*/
|
|
194
|
+
host_environment: z.object({
|
|
195
|
+
request_size_caps: z.object({
|
|
196
|
+
bash_max_output_length: z.number().int().positive().max(150_000).nullable().default(null).describe(
|
|
197
|
+
'Character cap on Bash tool output the host places inline into a model request. null (default) = this package writes nothing and the host default of 30000 applies. A number is written into the host env block. Values above 150000 are capped by the host itself, so the schema refuses them here rather than writing a value the host silently changes. Bounds request SIZE, never request COUNT: lowering it suppresses no telemetry, no update check and no download.',
|
|
198
|
+
),
|
|
199
|
+
max_mcp_output_tokens: z.number().int().positive().nullable().default(null).describe(
|
|
200
|
+
'Token cap on a single MCP tool result the host places into a model request. null (default) = nothing written, host default 25000 applies. Same size-not-count caveat: it does not govern MCP connections, timeouts, or whether a tool runs.',
|
|
201
|
+
),
|
|
202
|
+
}).default({}).describe(
|
|
203
|
+
'Request-size caps this package may write into the host env block. Both null by default. No traffic or auto-updater variable is expressible here, by construction — see the block comment.',
|
|
204
|
+
),
|
|
205
|
+
}).default({}).describe(
|
|
206
|
+
'What this package may write into the host environment. ABSENT resolves to the all-null shape, which is the same thing as off — a settings file predating this section must not fail to parse, and "no section" and "both caps null" both mean write nothing.',
|
|
207
|
+
),
|
|
164
208
|
augment: z.object({
|
|
165
209
|
rules_use_symlinks: z.boolean().default(false).describe(
|
|
166
210
|
'When true, .augment/rules/*.md are symlinks into dist/agent-src/rules/ — edits flow back to source on save. When false (default), they are copies — safer on Windows and shared volumes, but rule edits in .augment/ are lost on the next `task sync`.',
|
|
@@ -202,8 +246,8 @@ export const settingsSchema = z.object({
|
|
|
202
246
|
skip_pre_run_gate: z.boolean().default(true).describe(
|
|
203
247
|
'Skip the /roadmap:process-* pre-run confirmation gate. true (default) starts processing immediately and surfaces the resolved config inline; false shows the numbered-options gate and waits. A genuine "which roadmap?" ambiguity always prompts regardless.',
|
|
204
248
|
),
|
|
205
|
-
quality_cadence: qualityCadence.default('
|
|
206
|
-
'When the agent runs the full quality / test suite during /roadmap:process-* runs.
|
|
249
|
+
quality_cadence: qualityCadence.default('per_phase').describe(
|
|
250
|
+
'When the agent runs the full quality / test suite during /roadmap:process-* runs. per_phase = after each phase boundary (default since 2026-09-13 — end_of_roadmap lets errors compound across phases, which is expensive in a multi-phase autonomous run nobody is watching). end_of_roadmap = once, after the last step (fastest). per_step = after every single step (slowest, highest confidence).',
|
|
207
251
|
),
|
|
208
252
|
dashboard_regen_cadence: regenCadence.default('every_5_steps').describe(
|
|
209
253
|
'How often the agent regenerates agents/roadmaps/dashboard.md during a roadmap run. every_5_steps = batch the regen (default). per_step = after every step (freshest dashboard, highest subprocess overhead). phase_boundary = only at phase edges. A rename, phase add, or archive always regenerates immediately regardless.',
|
|
@@ -221,8 +265,8 @@ export const settingsSchema = z.object({
|
|
|
221
265
|
}).default({ max_cost_per_run_usd: 5, max_cost_per_rolling_7d_usd: 25 }),
|
|
222
266
|
}),
|
|
223
267
|
planning: z.object({
|
|
224
|
-
|
|
225
|
-
'Gate C — plan-
|
|
268
|
+
closure_pass: z.boolean().default(true).describe(
|
|
269
|
+
'Gate C — plan-closure pass. true (default) = a plan-artifact ask (/roadmap:create, roadmap-writing, /feature:plan, /feature:roadmap, /roadmap:materialize, /implement-ticket, /jira-ticket, /analyze:inbox, /analyze:roadmap-repos) ends in a closure pass (/challenge-me closure): every foreseeable decision is closed at the lowest rung that owns it and written into the roadmap\'s "## Decisions" table, so a long run never meets a question planning could have closed. false = inert, plan asks author directly. An explicit user bypass always wins for that turn and is counted as a bypass rather than as an absent closure.',
|
|
226
270
|
),
|
|
227
271
|
risk_review: z.boolean().default(true).describe(
|
|
228
272
|
'Gate R1 — plan-risk review. true (default) = every ready (non-draft) plan must carry a schema-valid "## Risk Register" section (ranked risks, mitigation + anchor per row, freshness marker, exact honest-null grammar), enforced by lint_plan_risk_register at pre-push + CI. false = escape hatch, the validator skips.',
|
|
@@ -238,9 +282,20 @@ export const settingsSchema = z.object({
|
|
|
238
282
|
// test whose fixture predates the section. With the default, an absent
|
|
239
283
|
// section materialises as the three `true` leaves the contract promises.
|
|
240
284
|
.default({}),
|
|
285
|
+
execution: z.object({
|
|
286
|
+
fix_loop_max: z.number().int().min(1).default(10).describe(
|
|
287
|
+
'Consecutive failed fix attempts against one validation target before the escalation ladder reaches its terminal rung. Reaching the bound triggers a strategy change, never a question. Overridable globally, per project and per prompt.',
|
|
288
|
+
),
|
|
289
|
+
escalation: z.array(z.string()).default(['independent', 'council', 'team', 'owner_owned_check']).describe(
|
|
290
|
+
'The escalation rungs, in order, walked when the fix-loop bound is reached: independent (another session or a provider-diverse reviewer), council, team, then owner_owned_check — which asks whether the residue is owner-owned, not whether to ask the owner now.',
|
|
291
|
+
),
|
|
292
|
+
}).default({}),
|
|
241
293
|
quality: z.object({
|
|
242
294
|
local_auto_run: z.boolean().default(false).describe(
|
|
243
|
-
'Run quality tools (linters, type-checks, formatters) and the local test suite autonomously after edits. Off by default —
|
|
295
|
+
'Run quality tools (linters, type-checks, formatters) and the local test suite autonomously after edits, IN CHAT. Off by default — in a chat turn a human is present and remote CI is the authoritative gate, so a local full-pipeline run duplicates it at wall-clock cost. The agent only runs a quality tool on an explicit ask, a concrete CI failure, or the new-gate carve-out. A mission is governed by local_auto_run_in_mission instead.',
|
|
296
|
+
),
|
|
297
|
+
local_auto_run_in_mission: z.boolean().default(true).describe(
|
|
298
|
+
'Run quality tools autonomously inside a mission — an autonomous roadmap run with a claimed contract. On by default: nobody is waiting, the next action belongs to the agent itself, and a red found twenty steps later costs more than the run that would have caught it at step one. Inert outside a mission, and a mission never lowers local_auto_run: true.',
|
|
244
299
|
),
|
|
245
300
|
}),
|
|
246
301
|
design: z.object({
|
|
@@ -547,7 +602,7 @@ export const settingsSchema = z.object({
|
|
|
547
602
|
}).default({}),
|
|
548
603
|
rtk_wrap: z.object({
|
|
549
604
|
enabled: z.boolean().default(false).describe(
|
|
550
|
-
'PreToolUse RTK-wrap nudge (token-saving Phase 3). Default off. When on AND the binary on PATH is verified as Rust Token Killer (a live two-stage identity probe — not a self-reported flag, and never a colliding same-name binary), warns (never blocks) "re-run wrapped with rtk" before a single verbose CLI command (git/npm/cargo/docker/…) — upstream reports 60–90% output-token savings (their estimate). Skips completeness-critical / piped / compound commands and git diff. No-op when rtk is absent, unverified, or a different tool.',
|
|
605
|
+
'PreToolUse RTK-wrap nudge (token-saving Phase 3). Default off. When on AND the binary on PATH is verified as Rust Token Killer (a live two-stage identity probe — not a self-reported flag, and never a colliding same-name binary), warns (never blocks) "re-run wrapped with rtk" before a single verbose CLI command (git/npm/cargo/docker/…) — upstream reports 60–90% output-token savings (their estimate). Skips completeness-critical / piped / compound commands and git diff. No-op when rtk is absent, unverified, or a different tool. Its own activation charge is one advisory line under the 1,024 B default concern cap in src/config/hook-token-budget.json; the per-fire distribution is UNMEASURED — stated rather than estimated, because the saving above is a third-party output-token claim and not a standing-payload reduction this package measured.',
|
|
551
606
|
),
|
|
552
607
|
}).default({}),
|
|
553
608
|
design_slop: z.object({
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mission execution posture — the loop bound, its escalation ladder, and the
|
|
3
|
+
* one setting whose value differs inside a mission.
|
|
4
|
+
*
|
|
5
|
+
* `road-to-adversarial-verification-and-long-runs` Phase 0. Three facts that
|
|
6
|
+
* were previously either absent or stated only in prose get one module, because
|
|
7
|
+
* all three are read by more than one surface (`doctor --json`, `settings:get`,
|
|
8
|
+
* the recovery ladder) and a constant restated per reader is the standard way a
|
|
9
|
+
* default drifts.
|
|
10
|
+
*
|
|
11
|
+
* **Why a mission changes `quality.local_auto_run` and nothing else does.** The
|
|
12
|
+
* template's own justification for shipping `false` is that remote CI is the
|
|
13
|
+
* authoritative gate and a local full-pipeline run duplicates it at wall-clock
|
|
14
|
+
* cost. That argument is about a CHAT turn, where the human is present, the next
|
|
15
|
+
* action is theirs, and the pipeline's result arrives long after the reply. It is
|
|
16
|
+
* not an argument about an autonomous mission, where nobody is waiting, the next
|
|
17
|
+
* action is the agent's own, and a red found after twenty more steps costs more
|
|
18
|
+
* than the pipeline run that would have found it at step one. The roadmap
|
|
19
|
+
* template already says as much about the sibling cadence knob — that
|
|
20
|
+
* `end_of_roadmap` lets errors compound across phases — so the two knobs are
|
|
21
|
+
* corrected together rather than one at a time.
|
|
22
|
+
*
|
|
23
|
+
* The resolution is deliberately NOT a settings-layer precedence trick. A layer
|
|
24
|
+
* is a place a human wrote a value; a mission is a runtime condition. Folding
|
|
25
|
+
* the condition into the layer stack would make `settings:get` report a source
|
|
26
|
+
* file for a value no file contains.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/** The escalation rungs, in the order the recovery ladder walks them. */
|
|
30
|
+
export const ESCALATION_LADDER: readonly string[] = [
|
|
31
|
+
'independent',
|
|
32
|
+
'council',
|
|
33
|
+
'team',
|
|
34
|
+
'owner_owned_check',
|
|
35
|
+
] as const;
|
|
36
|
+
|
|
37
|
+
/** Default bound on consecutive failed fix attempts against one target. */
|
|
38
|
+
export const FIX_LOOP_MAX_DEFAULT = 10;
|
|
39
|
+
|
|
40
|
+
/** Default for `quality.local_auto_run_in_mission`. */
|
|
41
|
+
export const MISSION_AUTO_RUN_DEFAULT = true;
|
|
42
|
+
|
|
43
|
+
/** Where a resolved `quality.local_auto_run` value came from. */
|
|
44
|
+
export type AutoRunOrigin = 'mission' | 'settings';
|
|
45
|
+
|
|
46
|
+
export interface AutoRunResolution {
|
|
47
|
+
/** The value a reader should act on. */
|
|
48
|
+
readonly value: boolean;
|
|
49
|
+
/** `mission` when the mission condition decided, `settings` otherwise. */
|
|
50
|
+
readonly origin: AutoRunOrigin;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface AutoRunInputs {
|
|
54
|
+
/** `quality.local_auto_run` as the settings layers resolved it. */
|
|
55
|
+
readonly configured: boolean;
|
|
56
|
+
/** `quality.local_auto_run_in_mission`, or `undefined` for the default. */
|
|
57
|
+
readonly missionValue?: boolean | undefined;
|
|
58
|
+
/** True only inside an autonomous mission (a claimed roadmap run). */
|
|
59
|
+
readonly inMission: boolean;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Resolve `quality.local_auto_run` for the current run.
|
|
64
|
+
*
|
|
65
|
+
* Outside a mission the configured value wins unchanged — that is the whole
|
|
66
|
+
* point of leaving chat alone. Inside one, `local_auto_run_in_mission` decides.
|
|
67
|
+
*
|
|
68
|
+
* One asymmetry is deliberate: a mission never LOWERS the configured value. An
|
|
69
|
+
* operator who set `local_auto_run: true` asked for pipeline runs everywhere,
|
|
70
|
+
* and a mission is not a reason to give them fewer.
|
|
71
|
+
*/
|
|
72
|
+
export function resolveLocalAutoRun(inputs: AutoRunInputs): AutoRunResolution {
|
|
73
|
+
if (inputs.configured) return { value: true, origin: 'settings' };
|
|
74
|
+
if (!inputs.inMission) return { value: false, origin: 'settings' };
|
|
75
|
+
const mission = inputs.missionValue ?? MISSION_AUTO_RUN_DEFAULT;
|
|
76
|
+
return mission ? { value: true, origin: 'mission' } : { value: false, origin: 'settings' };
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Fold `execution.*` out of a settings-override stream, last layer wins.
|
|
81
|
+
*
|
|
82
|
+
* Takes the same `[dotted, value, file]` tuples `iter_setting_overrides` emits,
|
|
83
|
+
* so a caller never re-implements the cascade. Keys outside the `execution.`
|
|
84
|
+
* prefix are ignored rather than collected: this is a narrow reader, and a
|
|
85
|
+
* reader that accidentally carries the whole settings tree is how a doctor
|
|
86
|
+
* payload grows a field nobody declared.
|
|
87
|
+
*/
|
|
88
|
+
export function executionPostureFromOverrides(
|
|
89
|
+
layers: Iterable<readonly [string, unknown, string]>,
|
|
90
|
+
): ExecutionPosture {
|
|
91
|
+
const raw: Record<string, unknown> = {};
|
|
92
|
+
for (const [key, value] of layers) {
|
|
93
|
+
if (key === 'execution.fix_loop_max') raw['fix_loop_max'] = value;
|
|
94
|
+
else if (key === 'execution.escalation') raw['escalation'] = value;
|
|
95
|
+
}
|
|
96
|
+
return resolveExecutionPosture(raw);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export interface ExecutionPosture {
|
|
100
|
+
readonly fix_loop_max: number;
|
|
101
|
+
readonly escalation: readonly string[];
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* The `execution:` block as a reader should see it, defaults filled in.
|
|
106
|
+
*
|
|
107
|
+
* A non-integer, non-positive or absent `fix_loop_max` falls back to the default
|
|
108
|
+
* rather than propagating: a bound of `0` would make every first attempt
|
|
109
|
+
* terminal, which is a configuration that can only be a mistake.
|
|
110
|
+
*/
|
|
111
|
+
export function resolveExecutionPosture(raw: unknown): ExecutionPosture {
|
|
112
|
+
const block = (raw ?? {}) as Record<string, unknown>;
|
|
113
|
+
const rawMax = block['fix_loop_max'];
|
|
114
|
+
const max =
|
|
115
|
+
typeof rawMax === 'number' && Number.isInteger(rawMax) && rawMax > 0
|
|
116
|
+
? rawMax
|
|
117
|
+
: FIX_LOOP_MAX_DEFAULT;
|
|
118
|
+
const rawLadder = block['escalation'];
|
|
119
|
+
const ladder =
|
|
120
|
+
Array.isArray(rawLadder) &&
|
|
121
|
+
rawLadder.length > 0 &&
|
|
122
|
+
rawLadder.every((r) => typeof r === 'string')
|
|
123
|
+
? (rawLadder as string[])
|
|
124
|
+
: ESCALATION_LADDER;
|
|
125
|
+
return { fix_loop_max: max, escalation: ladder };
|
|
126
|
+
}
|
|
@@ -39,3 +39,4 @@ This surfaces every registration across all six tools and flags `DUPLICATE` / `D
|
|
|
39
39
|
- [`docs/contracts/install-scopes.md`](../../docs/contracts/install-scopes.md) — when to use project-local vs user-global.
|
|
40
40
|
- [`docs/customization.md` § Troubleshooting](../../docs/customization.md#troubleshooting) — the troubleshooting front door.
|
|
41
41
|
- [`agents/reference/docs/onboarding.md`](../../agents/reference/docs/onboarding.md) — the longer, package-side onboarding doc.
|
|
42
|
+
- [`docs/setup/host-traffic-environment.md`](../../docs/setup/host-traffic-environment.md) — which host environment variables suppress non-essential network traffic, and which only look as if they do; `agent-config doctor --json` reports their observed state.
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
import { createRequire as __acCreateRequire } from 'node:module'; const require = globalThis.require ?? __acCreateRequire(import.meta.url);
|
|
2
|
-
|
|
3
|
-
// src/install/plan.ts
|
|
4
|
-
import { createHash } from "node:crypto";
|
|
5
|
-
import { readFileSync, readdirSync, statSync } from "node:fs";
|
|
6
|
-
import { join, relative, resolve } from "node:path";
|
|
7
|
-
function sha256File(path) {
|
|
8
|
-
try {
|
|
9
|
-
const data = readFileSync(path);
|
|
10
|
-
return createHash("sha256").update(data).digest("hex");
|
|
11
|
-
} catch {
|
|
12
|
-
return null;
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
function fileEntry(path, kind, options) {
|
|
16
|
-
return {
|
|
17
|
-
path,
|
|
18
|
-
kind,
|
|
19
|
-
sha256: options.hashContent ? sha256File(path) : null
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
function walkSourceTree(dir) {
|
|
23
|
-
const out = [];
|
|
24
|
-
walkInto(dir, out);
|
|
25
|
-
return out;
|
|
26
|
-
}
|
|
27
|
-
function walkInto(dir, out) {
|
|
28
|
-
let entries;
|
|
29
|
-
try {
|
|
30
|
-
entries = readdirSync(dir).sort();
|
|
31
|
-
} catch {
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
for (const name of entries) {
|
|
35
|
-
const full = join(dir, name);
|
|
36
|
-
let isDir;
|
|
37
|
-
try {
|
|
38
|
-
isDir = statSync(full).isDirectory();
|
|
39
|
-
} catch {
|
|
40
|
-
continue;
|
|
41
|
-
}
|
|
42
|
-
if (isDir) {
|
|
43
|
-
walkInto(full, out);
|
|
44
|
-
} else {
|
|
45
|
-
out.push(full);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
function buildInstallPlan(inputs) {
|
|
50
|
-
const filesByTool = {};
|
|
51
|
-
for (const source of inputs.sources) {
|
|
52
|
-
const bucket = filesByTool[source.toolId] ?? [];
|
|
53
|
-
let files = walkSourceTree(source.srcDir);
|
|
54
|
-
if (source.fileFilter !== void 0) {
|
|
55
|
-
files = files.filter(source.fileFilter);
|
|
56
|
-
}
|
|
57
|
-
for (const srcFile of files) {
|
|
58
|
-
const rel = relative(source.srcDir, srcFile);
|
|
59
|
-
const destPath = resolve(source.destDir, rel);
|
|
60
|
-
bucket.push(
|
|
61
|
-
fileEntry(srcFile, source.kind, {
|
|
62
|
-
hashContent: source.kind !== "bridge"
|
|
63
|
-
})
|
|
64
|
-
);
|
|
65
|
-
bucket[bucket.length - 1] = {
|
|
66
|
-
...bucket[bucket.length - 1],
|
|
67
|
-
path: destPath
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
filesByTool[source.toolId] = bucket;
|
|
71
|
-
}
|
|
72
|
-
for (const source of inputs.sources) {
|
|
73
|
-
if (!(source.toolId in filesByTool)) {
|
|
74
|
-
filesByTool[source.toolId] = [];
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
return {
|
|
78
|
-
version: 2,
|
|
79
|
-
target: inputs.target,
|
|
80
|
-
root: inputs.root,
|
|
81
|
-
filesByTool,
|
|
82
|
-
mergedKeysByTool: {},
|
|
83
|
-
policy: inputs.policy
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export {
|
|
88
|
-
sha256File,
|
|
89
|
-
buildInstallPlan
|
|
90
|
-
};
|