@event4u/agent-config 11.0.0 → 12.1.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/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +173 -229
- package/agents/templates/.ai-council.yml.example +46 -3
- package/dist/agent-src/commands/agent-handoff.md +0 -1
- package/dist/agent-src/commands/agent-status.md +0 -1
- package/dist/agent-src/commands/agents/audit.md +0 -1
- package/dist/agent-src/commands/agents/init.md +0 -1
- package/dist/agent-src/commands/agents/optimize.md +0 -1
- package/dist/agent-src/commands/agents/user/accept.md +0 -1
- package/dist/agent-src/commands/agents/user/delete.md +0 -1
- package/dist/agent-src/commands/agents/user/init.md +0 -1
- package/dist/agent-src/commands/agents/user/review.md +0 -1
- package/dist/agent-src/commands/agents/user/show.md +0 -1
- package/dist/agent-src/commands/agents/user/update.md +0 -1
- package/dist/agent-src/commands/agents/user.md +0 -1
- package/dist/agent-src/commands/agents.md +0 -1
- package/dist/agent-src/commands/analytics/prune.md +0 -1
- package/dist/agent-src/commands/analytics/show.md +0 -1
- package/dist/agent-src/commands/analytics.md +0 -1
- package/dist/agent-src/commands/analyze/conformance.md +0 -1
- package/dist/agent-src/commands/analyze/decision.md +0 -1
- package/dist/agent-src/commands/analyze/inbox.md +0 -1
- package/dist/agent-src/commands/analyze/incident.md +0 -1
- package/dist/agent-src/commands/analyze/near-miss.md +0 -1
- package/dist/agent-src/commands/analyze/postmortem.md +0 -1
- package/dist/agent-src/commands/analyze/premortem.md +0 -1
- package/dist/agent-src/commands/analyze/reference-repo.md +0 -1
- package/dist/agent-src/commands/analyze.md +0 -1
- package/dist/agent-src/commands/brand/identity.md +0 -1
- package/dist/agent-src/commands/brand/review.md +0 -1
- package/dist/agent-src/commands/brand/strategy.md +0 -1
- package/dist/agent-src/commands/brand/tokens.md +0 -1
- package/dist/agent-src/commands/brand/voice.md +0 -1
- package/dist/agent-src/commands/brand.md +0 -1
- package/dist/agent-src/commands/bug/fix.md +0 -1
- package/dist/agent-src/commands/bug/investigate.md +0 -1
- package/dist/agent-src/commands/bug.md +0 -1
- package/dist/agent-src/commands/challenge-me/vision.md +0 -1
- package/dist/agent-src/commands/challenge-me/with-docs.md +0 -1
- package/dist/agent-src/commands/challenge-me.md +0 -1
- package/dist/agent-src/commands/chat-history/import.md +0 -1
- package/dist/agent-src/commands/chat-history.md +0 -1
- package/dist/agent-src/commands/check-current-md.md +0 -1
- package/dist/agent-src/commands/commit/in-chunks.md +0 -1
- package/dist/agent-src/commands/commit.md +0 -1
- package/dist/agent-src/commands/condense.md +0 -1
- package/dist/agent-src/commands/context/create.md +0 -1
- package/dist/agent-src/commands/context/refactor.md +0 -1
- package/dist/agent-src/commands/context.md +0 -1
- package/dist/agent-src/commands/contribution-precheck.md +0 -1
- package/dist/agent-src/commands/cost/profile.md +0 -1
- package/dist/agent-src/commands/cost/report.md +0 -1
- package/dist/agent-src/commands/cost.md +0 -1
- package/dist/agent-src/commands/council/analysis.md +0 -1
- package/dist/agent-src/commands/council/debate.md +0 -1
- package/dist/agent-src/commands/council/default.md +0 -1
- package/dist/agent-src/commands/council/design.md +0 -1
- package/dist/agent-src/commands/council/optimize.md +0 -1
- package/dist/agent-src/commands/council/pr.md +0 -1
- package/dist/agent-src/commands/council.md +0 -1
- package/dist/agent-src/commands/design-system/capture.md +0 -1
- package/dist/agent-src/commands/design-system/generate.md +0 -1
- package/dist/agent-src/commands/design-system/import.md +0 -1
- package/dist/agent-src/commands/design-system.md +0 -1
- package/dist/agent-src/commands/estimate-ticket.md +0 -1
- package/dist/agent-src/commands/explain-run.md +0 -1
- package/dist/agent-src/commands/feature/dev.md +0 -1
- package/dist/agent-src/commands/feature/explore.md +0 -1
- package/dist/agent-src/commands/feature/plan.md +0 -1
- package/dist/agent-src/commands/feature/refactor.md +0 -1
- package/dist/agent-src/commands/feature/roadmap.md +0 -1
- package/dist/agent-src/commands/feature.md +0 -1
- package/dist/agent-src/commands/fix/ci.md +0 -1
- package/dist/agent-src/commands/fix/comments.md +0 -1
- package/dist/agent-src/commands/fix/portability.md +0 -1
- package/dist/agent-src/commands/fix/pr-comments-loop.md +0 -1
- package/dist/agent-src/commands/fix/pr-comments.md +0 -1
- package/dist/agent-src/commands/fix/quality.md +0 -1
- package/dist/agent-src/commands/fix/refs.md +0 -1
- package/dist/agent-src/commands/fix/route.md +0 -1
- package/dist/agent-src/commands/fix/seeder.md +0 -1
- package/dist/agent-src/commands/fix.md +0 -1
- package/dist/agent-src/commands/ghostwriter/delete.md +0 -1
- package/dist/agent-src/commands/ghostwriter/fetch.md +0 -1
- package/dist/agent-src/commands/ghostwriter/list.md +0 -1
- package/dist/agent-src/commands/ghostwriter/show.md +0 -1
- package/dist/agent-src/commands/ghostwriter/write.md +0 -1
- package/dist/agent-src/commands/ghostwriter.md +0 -1
- package/dist/agent-src/commands/grill-me.md +0 -1
- package/dist/agent-src/commands/humanize.md +0 -1
- package/dist/agent-src/commands/image/analyse.md +0 -1
- package/dist/agent-src/commands/image/create.md +0 -1
- package/dist/agent-src/commands/image/verify.md +0 -1
- package/dist/agent-src/commands/image.md +0 -1
- package/dist/agent-src/commands/implement-ticket.md +0 -1
- package/dist/agent-src/commands/jira-ticket.md +0 -1
- package/dist/agent-src/commands/judge/on-diff.md +0 -1
- package/dist/agent-src/commands/judge/solo.md +0 -1
- package/dist/agent-src/commands/judge/steps.md +0 -1
- package/dist/agent-src/commands/judge.md +0 -1
- package/dist/agent-src/commands/knowledge/cross-repo.md +0 -1
- package/dist/agent-src/commands/knowledge/forget.md +0 -1
- package/dist/agent-src/commands/knowledge/ingest.md +0 -1
- package/dist/agent-src/commands/knowledge/list.md +0 -1
- package/dist/agent-src/commands/knowledge.md +0 -1
- package/dist/agent-src/commands/memory/add.md +0 -1
- package/dist/agent-src/commands/memory/learn-low-impact.md +0 -1
- package/dist/agent-src/commands/memory/load.md +0 -1
- package/dist/agent-src/commands/memory/mine-session.md +0 -1
- package/dist/agent-src/commands/memory/promote.md +0 -1
- package/dist/agent-src/commands/memory/propose.md +0 -1
- package/dist/agent-src/commands/memory.md +0 -1
- package/dist/agent-src/commands/mission/upgrade.md +0 -1
- package/dist/agent-src/commands/mode.md +0 -1
- package/dist/agent-src/commands/module/create.md +0 -1
- package/dist/agent-src/commands/module/explore.md +0 -1
- package/dist/agent-src/commands/module.md +0 -1
- package/dist/agent-src/commands/optimize/agents-dir.md +0 -1
- package/dist/agent-src/commands/optimize/augmentignore.md +0 -1
- package/dist/agent-src/commands/optimize/deep.md +0 -1
- package/dist/agent-src/commands/optimize/project.md +0 -1
- package/dist/agent-src/commands/optimize/prompt.md +0 -1
- package/dist/agent-src/commands/optimize/rtk.md +0 -1
- package/dist/agent-src/commands/optimize/skills.md +0 -1
- package/dist/agent-src/commands/optimize.md +0 -1
- package/dist/agent-src/commands/orchestrate.md +0 -1
- package/dist/agent-src/commands/override/create.md +0 -1
- package/dist/agent-src/commands/override/manage.md +0 -1
- package/dist/agent-src/commands/override.md +0 -1
- package/dist/agent-src/commands/package/reset.md +0 -1
- package/dist/agent-src/commands/package/test.md +0 -1
- package/dist/agent-src/commands/package.md +0 -1
- package/dist/agent-src/commands/post-as/ghostwriter.md +0 -1
- package/dist/agent-src/commands/post-as/me.md +0 -1
- package/dist/agent-src/commands/post-as.md +0 -1
- package/dist/agent-src/commands/pr/create/description-only.md +0 -1
- package/dist/agent-src/commands/pr/create.md +23 -9
- package/dist/agent-src/commands/prediction-pool.md +0 -1
- package/dist/agent-src/commands/prepare-for-review.md +0 -1
- package/dist/agent-src/commands/profile/activate.md +0 -1
- package/dist/agent-src/commands/profile/deactivate.md +0 -1
- package/dist/agent-src/commands/profile/show.md +0 -1
- package/dist/agent-src/commands/profile.md +0 -1
- package/dist/agent-src/commands/project/analyze.md +0 -1
- package/dist/agent-src/commands/project/health.md +0 -1
- package/dist/agent-src/commands/project.md +0 -1
- package/dist/agent-src/commands/refine-ticket.md +0 -1
- package/dist/agent-src/commands/research/deep.md +0 -1
- package/dist/agent-src/commands/research/report.md +0 -1
- package/dist/agent-src/commands/research.md +0 -1
- package/dist/agent-src/commands/review/changes.md +0 -1
- package/dist/agent-src/commands/review/routing.md +0 -1
- package/dist/agent-src/commands/review.md +0 -1
- package/dist/agent-src/commands/roadmap/ai-council.md +0 -1
- package/dist/agent-src/commands/roadmap/create.md +0 -1
- package/dist/agent-src/commands/roadmap/materialize.md +0 -1
- package/dist/agent-src/commands/roadmap/next.md +0 -1
- package/dist/agent-src/commands/roadmap/process-full.md +0 -1
- package/dist/agent-src/commands/roadmap/process-phase.md +0 -1
- package/dist/agent-src/commands/roadmap/process-step.md +0 -1
- package/dist/agent-src/commands/roadmap.md +0 -1
- package/dist/agent-src/commands/rule-compliance-audit.md +0 -1
- package/dist/agent-src/commands/security-audit-config.md +0 -1
- package/dist/agent-src/commands/skill/preview.md +0 -1
- package/dist/agent-src/commands/skill.md +0 -1
- package/dist/agent-src/commands/skills/discover.md +0 -1
- package/dist/agent-src/commands/skills.md +0 -1
- package/dist/agent-src/commands/sync/agent-settings.md +0 -1
- package/dist/agent-src/commands/sync/gitignore/fix.md +0 -1
- package/dist/agent-src/commands/sync/gitignore.md +0 -1
- package/dist/agent-src/commands/sync.md +0 -1
- package/dist/agent-src/commands/tdd/green.md +0 -1
- package/dist/agent-src/commands/tdd/red.md +0 -1
- package/dist/agent-src/commands/tdd/refactor.md +0 -1
- package/dist/agent-src/commands/tdd.md +0 -1
- package/dist/agent-src/commands/team/adversarial.md +0 -1
- package/dist/agent-src/commands/team/delegate.md +0 -1
- package/dist/agent-src/commands/team/review.md +0 -1
- package/dist/agent-src/commands/team/status.md +0 -1
- package/dist/agent-src/commands/team-knowledge/bootstrap.md +0 -1
- package/dist/agent-src/commands/team-knowledge/consolidate.md +0 -1
- package/dist/agent-src/commands/team-knowledge.md +0 -1
- package/dist/agent-src/commands/team.md +0 -1
- package/dist/agent-src/commands/tests/create.md +0 -1
- package/dist/agent-src/commands/tests/e2e-heal.md +0 -1
- package/dist/agent-src/commands/tests/e2e-plan.md +0 -1
- package/dist/agent-src/commands/tests/execute.md +0 -1
- package/dist/agent-src/commands/tests.md +0 -1
- package/dist/agent-src/commands/threat-model.md +0 -1
- package/dist/agent-src/commands/update-form-request-messages.md +0 -1
- package/dist/agent-src/commands/upstream-contribute.md +0 -1
- package/dist/agent-src/commands/video/from-script.md +0 -1
- package/dist/agent-src/commands/video/from-song.md +0 -1
- package/dist/agent-src/commands/video/scene.md +0 -1
- package/dist/agent-src/commands/video/stitch.md +0 -1
- package/dist/agent-src/commands/video/storyboard.md +0 -1
- package/dist/agent-src/commands/video.md +0 -1
- package/dist/agent-src/commands/work.md +0 -1
- package/dist/agent-src/commands/worktree/cleanup.md +0 -1
- package/dist/agent-src/commands/worktree/create.md +0 -1
- package/dist/agent-src/commands/worktree/status.md +0 -1
- package/dist/agent-src/commands/worktree/verify.md +0 -1
- package/dist/agent-src/commands/worktree.md +0 -1
- package/dist/agent-src/contexts/model-recommendations.md +6 -4
- package/dist/agent-src/rules/low-impact-corpus-privacy-floor.md +1 -0
- package/dist/agent-src/scripts/roadmap_gates.ts +30 -2
- package/dist/agent-src/scripts/update_roadmap_progress.ts +32 -1
- package/dist/agent-src/skills/docx-authoring/SKILL.md +1 -0
- package/dist/agent-src/skills/git-workflow/SKILL.md +9 -1
- package/dist/agent-src/skills/pdf-tools/SKILL.md +1 -0
- package/dist/agent-src/skills/roadmap-writing/SKILL.md +7 -7
- package/dist/agent-src/skills/skill-writing/SKILL.md +35 -0
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/roadmaps.md +41 -3
- package/dist/cli/commands/commands.candidates.test.js +1 -1
- package/dist/cli/commands/commands.candidates.test.js.map +1 -1
- package/dist/cli/commands/commands.js +9 -15
- package/dist/cli/commands/commands.js.map +1 -1
- package/dist/cli/commands/profiles.test.js +7 -7
- package/dist/cli/commands/profiles.test.js.map +1 -1
- package/dist/cli/discovery/loadManifest.js.map +1 -1
- package/dist/cli/main.js +2 -2
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/registry.js +1 -0
- package/dist/cli/registry.js.map +1 -1
- package/dist/cli-delegate/chunk-K34QTSD5.js +3895 -0
- package/dist/cli-delegate/{chunk-L565YFXH.js → chunk-LKZ5DOYW.js} +557 -297
- package/dist/cli-delegate/{chunk-NN4KW4HZ.js → chunk-O52B4F5S.js} +123 -2338
- package/dist/cli-delegate/cmd_conformance.js +18 -6
- package/dist/cli-delegate/cmd_doctor.js +2 -2
- package/dist/cli-delegate/cmd_export.js +1 -1
- package/dist/cli-delegate/cmd_handoff.js +1 -1
- package/dist/cli-delegate/cmd_prune.js +1 -1
- package/dist/cli-delegate/cmd_settings_migrate.js +1 -1
- package/dist/cli-delegate/cmd_sync.js +1 -1
- package/dist/cli-delegate/cmd_uninstall.js +1 -1
- package/dist/cli-delegate/cmd_validate.js +1 -1
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +213 -412
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +2 -2
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +3 -3
- package/dist/discovery/trust-report.md +1 -1
- package/dist/discovery/workspaces.json +3 -3
- package/dist/hooks/dispatch.js +2588 -1082
- package/dist/install/install.mjs +744 -482
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +159 -15
- package/dist/router.json +1 -1
- package/dist/scripts/_lib/model_tier.js +9 -0
- package/dist/scripts/_lib/model_tier.js.map +1 -1
- package/dist/scripts/condense.js +50 -0
- package/dist/scripts/condense.js.map +1 -1
- package/docs/MIGRATION.md +21 -1
- package/docs/contracts/settings-classes.md +41 -0
- package/package.json +1 -1
- package/src/agent-src/scripts/roadmap_gates.ts +30 -2
- package/src/agent-src/scripts/update_roadmap_progress.ts +32 -1
- package/src/config/agent-settings.template.yml +34 -0
- package/src/config/evaluator-budgets.json +4 -4
- package/src/config/gate-coverage.yml +39 -9
- package/src/config/gate-violation-baselines.json +9 -3
- package/src/config/hook-token-budget.json +7 -1
- package/src/config/preamble-payload-budget.json +28 -0
- package/src/scripts/_dispatch.bash +52 -5
- package/src/scripts/_lib/git_common_dir.ts +173 -0
- package/src/scripts/_lib/model_tier.ts +9 -0
- package/src/scripts/_lib/release_highlights.ts +108 -7
- package/src/scripts/_lib/skill_catalogue.ts +862 -0
- package/src/scripts/ai_council/clients.ts +182 -3
- package/src/scripts/ai_council/config.ts +16 -1
- package/src/scripts/ai_council/low_impact.ts +14 -1
- package/src/scripts/ai_council/orchestrator.ts +14 -1
- package/src/scripts/ai_council/transport_resolver.ts +32 -2
- package/src/scripts/audit_command_surface.ts +21 -15
- package/src/scripts/build_catalog_index.ts +1 -1
- package/src/scripts/build_discovery_manifest.ts +30 -34
- package/src/scripts/capture_skill_catalogue.ts +185 -328
- package/src/scripts/check_branch_freshness.ts +217 -62
- package/src/scripts/check_release_published.ts +6 -2
- package/src/scripts/check_release_trunk_sync.ts +18 -2
- package/src/scripts/condense.ts +50 -1
- package/src/scripts/dispatch_r2_reviewer.ts +15 -5
- package/src/scripts/evidence_report.ts +15 -4
- package/src/scripts/gen_discovery_baseline.ts +3 -3
- package/src/scripts/hook_manifest.yaml +67 -13
- package/src/scripts/hooks/concern_registry.ts +2 -0
- package/src/scripts/hooks/orchestration_record_hook.ts +21 -0
- package/src/scripts/hooks/subagent_ledger_hook.ts +17 -4
- package/src/scripts/hooks/tool_result_bytes_hook.ts +219 -0
- package/src/scripts/hot_context_hook.ts +13 -1
- package/src/scripts/install.ts +129 -0
- package/src/scripts/janitor.ts +77 -2
- package/src/scripts/lint_command_tiers.ts +29 -75
- package/src/scripts/lint_originality.ts +101 -14
- package/src/scripts/lint_plan_risk_register.ts +22 -9
- package/src/scripts/lint_roadmap_blockers.ts +109 -6
- package/src/scripts/lint_scheduled_deprecations.ts +738 -0
- package/src/scripts/migration_status.ts +17 -1
- package/src/scripts/probe_review_binding_drift.ts +731 -0
- package/src/scripts/release.ts +95 -1
- package/src/scripts/schemas/command.schema.json +6 -11
- package/src/scripts/schemas/skill.schema.json +12 -2
- package/src/scripts/schemas/subagent.schema.json +2 -2
- package/src/scripts/session_eol_report.ts +81 -0
- package/src/scripts/skill_linter.ts +82 -2
- package/src/scripts/workspace_doctor.ts +464 -0
- package/src/scripts/worktree_cleanup_check.ts +113 -8
- package/dist/cli-delegate/chunk-AYKQGIBG.js +0 -1594
|
@@ -347,6 +347,24 @@ interface Blocker {
|
|
|
347
347
|
blocks: string;
|
|
348
348
|
todo: string[];
|
|
349
349
|
resolvedWhen: string;
|
|
350
|
+
/**
|
|
351
|
+
* The two fields that make a blocker *decidable* rather than merely
|
|
352
|
+
* described. Empty string when the entry predates them — the ratchet in
|
|
353
|
+
* `lint_roadmap_blockers` keeps the backlog legal, so the renderer has to
|
|
354
|
+
* cope with absence rather than assume it away.
|
|
355
|
+
*/
|
|
356
|
+
recommendation: string;
|
|
357
|
+
ifNothing: string;
|
|
358
|
+
/**
|
|
359
|
+
* Optional one-line statement of what is actually being decided.
|
|
360
|
+
*
|
|
361
|
+
* Not required, but recognised: three entries in the tree already used
|
|
362
|
+
* `- **Question:**` and, because the field list did not know it, the
|
|
363
|
+
* continuation logic silently appended it to `Blocks` — the decision's
|
|
364
|
+
* subject arrived glued to the end of an unrelated sentence. Naming it
|
|
365
|
+
* costs one enum entry and turns a silent swallow into a rendered field.
|
|
366
|
+
*/
|
|
367
|
+
question: string;
|
|
350
368
|
}
|
|
351
369
|
|
|
352
370
|
// Strip fenced code blocks before blocker detection — a roadmap that shows the
|
|
@@ -362,7 +380,8 @@ function _stripFencedCode(text: string): string {
|
|
|
362
380
|
return text.replace(FENCED_CODE_RE, (m) => '\n'.repeat(_splitlines(m).length));
|
|
363
381
|
}
|
|
364
382
|
|
|
365
|
-
const BLOCKER_FIELD_RE =
|
|
383
|
+
const BLOCKER_FIELD_RE =
|
|
384
|
+
/^-[ \t]*\*\*(Status|Owner|Blocks|Resolved when|What to do|Recommendation|If you do nothing|Question):\*\*/i;
|
|
366
385
|
|
|
367
386
|
/** Strip an inline `<!-- comment -->` and trim. */
|
|
368
387
|
function _stripComment(s: string): string {
|
|
@@ -471,6 +490,9 @@ function parse_blockers(raw_text: string): Blocker[] {
|
|
|
471
490
|
blocks: _blockerField(body, 'Blocks') ?? '(unspecified)',
|
|
472
491
|
todo: _blockerTodo(body),
|
|
473
492
|
resolvedWhen: _blockerField(body, 'Resolved when') ?? '(unspecified)',
|
|
493
|
+
recommendation: _blockerField(body, 'Recommendation') ?? '',
|
|
494
|
+
ifNothing: _blockerField(body, 'If you do nothing') ?? '',
|
|
495
|
+
question: _blockerField(body, 'Question') ?? '',
|
|
474
496
|
});
|
|
475
497
|
}
|
|
476
498
|
}
|
|
@@ -502,6 +524,9 @@ function parse_blockers(raw_text: string): Blocker[] {
|
|
|
502
524
|
blocks: 'entire roadmap',
|
|
503
525
|
todo: [parts.join(' ')],
|
|
504
526
|
resolvedWhen: 'condition described above clears',
|
|
527
|
+
recommendation: '',
|
|
528
|
+
ifNothing: '',
|
|
529
|
+
question: '',
|
|
505
530
|
});
|
|
506
531
|
}
|
|
507
532
|
return blockers;
|
|
@@ -869,6 +894,12 @@ function render(roadmaps: RoadmapStats[], bundles: Bundle[] | null = null): stri
|
|
|
869
894
|
lines.push('**Blockers**\n');
|
|
870
895
|
for (const b of openBlockers) {
|
|
871
896
|
lines.push(`- **${b.id}** (owner: ${b.owner}) — blocks ${b.blocks}`);
|
|
897
|
+
if (b.recommendation) {
|
|
898
|
+
lines.push(` - **Recommendation:** ${b.recommendation}`);
|
|
899
|
+
}
|
|
900
|
+
if (b.ifNothing) {
|
|
901
|
+
lines.push(` - **If you do nothing:** ${b.ifNothing}`);
|
|
902
|
+
}
|
|
872
903
|
lines.push(' - **What to do:**');
|
|
873
904
|
for (const step of b.todo) {
|
|
874
905
|
lines.push(` ${step}`);
|
|
@@ -133,6 +133,40 @@ projection:
|
|
|
133
133
|
# (vendor-granular unknown_defaults in src/config/host-capabilities.yml).
|
|
134
134
|
discipline_profile: __DISCIPLINE_PROFILE__
|
|
135
135
|
|
|
136
|
+
# OPT-IN PRESET — the measured-lift configuration, shown but NOT shipped.
|
|
137
|
+
#
|
|
138
|
+
# The evidence above says `essential` carries the significant discipline lift
|
|
139
|
+
# (+0.458, p=0.0135) while `full`'s residual over it is not significant
|
|
140
|
+
# (p=0.37). That reads like an argument to flip the shipped default. It is not,
|
|
141
|
+
# for two independent reasons, and both are worth stating where the key lives
|
|
142
|
+
# rather than in a roadmap nobody reads at install time.
|
|
143
|
+
#
|
|
144
|
+
# 1. This key family is marked "do not set this from automation". That reads
|
|
145
|
+
# as ABSOLUTE — it forbids an automated CHOICE of default for the family,
|
|
146
|
+
# not merely a script rewriting your file. No measurement, however clean,
|
|
147
|
+
# licenses an agent to flip it on your behalf.
|
|
148
|
+
# 2. The flip was pre-registered against a fresh-install census of
|
|
149
|
+
# <= 30k tokens of always-on rule prose. Measured at audit time: ~163k as
|
|
150
|
+
# loaded, i.e. 5.4x the target. The criterion fails on its own terms
|
|
151
|
+
# regardless of point 1.
|
|
152
|
+
#
|
|
153
|
+
# So the better-evidenced value is carried here as a visible option you may
|
|
154
|
+
# uncomment, with its cost stated inline. Uncomment the line below to replace
|
|
155
|
+
# the resolved value above:
|
|
156
|
+
#
|
|
157
|
+
# discipline_profile: essential # ~3.3x kernel tokens (vs ~11.7x for full)
|
|
158
|
+
#
|
|
159
|
+
# Read the two factors as what they are: multiples of the kernel-only baseline
|
|
160
|
+
# from the cost-factor sweep, NOT the fresh-install census. They answer "what
|
|
161
|
+
# does this tier cost relative to `off`", never "does this tier reach 30k" —
|
|
162
|
+
# nothing has measured the latter for `essential`, and this comment does not
|
|
163
|
+
# claim it does.
|
|
164
|
+
#
|
|
165
|
+
# Recorded 2026-08-14 on an outside opinion (1 seat, 2 rounds; the second seat
|
|
166
|
+
# failed to start, so a single-model judgement on its checkable merit and NOT a
|
|
167
|
+
# convergence). It rejected both the flip and the do-nothing, and proposed this
|
|
168
|
+
# third route: you see the option, nothing automated chose for you.
|
|
169
|
+
|
|
136
170
|
# --- Cost profile (legacy knob — superseded by discipline_profile above) ---
|
|
137
171
|
#
|
|
138
172
|
# Master switch that controls which rule tiers load each session.
|
|
@@ -58,11 +58,11 @@
|
|
|
58
58
|
"deterministic": false
|
|
59
59
|
},
|
|
60
60
|
"cli_help_command_count": {
|
|
61
|
-
"max":
|
|
62
|
-
"last_measured":
|
|
63
|
-
"last_measured_at": "2026-08-
|
|
61
|
+
"max": 98,
|
|
62
|
+
"last_measured": 98,
|
|
63
|
+
"last_measured_at": "2026-08-15",
|
|
64
64
|
"method": "registry enumeration — count of `{ name: '...', disposition` entries in src/cli/registry.ts (NOT --help prose parsing; methods historically disagreed 74 vs 76 vs 79)",
|
|
65
|
-
"baseline_note": "80 → 81 on 2026-08-03 (release 9.15.0 gate). This RECORDS growth that already shipped through its own reviewed PR; it does not authorize new surface. The +1 is f02db54c2 (fix(cli): register routing:doctor in the CLI registry) — the command existed, only its registry entry was missing, and the registering PR did not move this budget. The gate did its job again: breach WARNS on main and BLOCKS on release, which is the conscious-decision point rather than a silently raised cap. Re-measured 2026-08-03 via the pinned method: 81. Headroom stays zero by design — the next registry addition must move this number in its own PR. 81 → 82 on 2026-08-04: the `handoff` subcommand (road-to-agent-handoff-resume Phase 4) registers in the same PR that adds the surface, per this record's own contract. Re-measured via the pinned method: 82. 82 → 84 on 2026-08-04: the `route:explain` + `route:audit` verbs (routing-correctness validation surface) register in the same PR that adds the surface. Re-measured via the pinned method: 84. 84 → 85 on 2026-08-05: the `settings:set` verb (road-to-zero-ceremony-settings Phase 2 — the one agent-reachable settings writer) registers in the same PR that adds the surface, per this record's own contract. Re-measured via the pinned method: 85. 85 → 86 on 2026-08-06: the `conformance:behavior` verb (road-to-agent-behavior-conformance Phase 5 — replays the local transcript store through the four mechanised conformance checks) registers in the same PR that adds the surface, per this record's own contract. Re-measured via the pinned method: 86. 86 → 88 on 2026-08-07: the `sessions:list` + `sessions:claim` verbs (road-to-parallel-session-coordination — the shell surface of the shared session register, needed because /roadmap:next is command markdown and can only reach the register through a shell call) register in the same PR that adds the surface, per this record's own contract. Re-measured via the pinned method: 88. 88 → 89 on 2026-08-08: the `council:status` verb registers in the same PR that adds the surface, per this record's own contract. It exists because an agent in a consumer project announced \"kein Council konfiguriert (keine .agent-settings.yml)\" and substituted a weaker path while the council was configured user-globally the whole time — there was no verb that answered availability, so the only route was an inference from a filename, and the intuitive filename is the one location ADR-104 guarantees is never consulted. Re-measured via the pinned method: 89. 89 → 91 on 2026-08-08: the `self-repair:status` + `self-repair:release` verbs (the queued-defect reader and the single Hard-Floor-gated outward step of the self-repair loop — the loop is deliberately unable to publish unless a human runs the release command) register in the same PR that adds the surface, per this record's own contract. Landed alongside the +1 council:status move in the same branch. Re-measured via the pinned method: 91. 91 → 94 on 2026-08-08: the `packs:active`, `settings:get` and `mcp:available` verbs (road-to-capability-answerability Phase 2 — the three capability probes for the gaps that had none) register in the same PR that adds the surface, per this record's own contract. Each answers a question that was previously only inferable from a filename: which packs are active and from which file, what a setting resolves to and which file set it, and what is declared in mcp.json versus what can actually launch. 94 -> 95 in the same PR: `brand:status` (Phase 2.4 — brand-layer presence, which the rule depended on and no surface could answer). Re-measured twice via the pinned method on the unchanged tree: 95/95. 95 → 96 on 2026-08-10: the `session:recycle` verb (road-to-token-economy-recycling Phase 2.2 — the deterministic producer of the main-session recycle envelope; the recycle advisory names this exact verb, so it must exist as a shell surface) registers in the same PR that adds the surface, per this record's own contract. Re-measured via the pinned method: 96. 96 -> 97 on 2026-08-10: the `gates` verb registers in the same PR that adds the surface, per this record's own contract. It exists because the blocker fields the dashboard already parses (Owner, What to do, Resolved when — CI-enforced by lint_roadmap_blockers) had no owner-filtered reader: the dashboard counts the open blockers across a 600-line file and links each to a per-roadmap anchor, so \"which of these are mine\" was a manual read of every anchor. The same inference-from-a-filename shape as the council:status entry above, one layer up. This branch and the session:recycle branch each measured 96 independently and landed on the same number for different verbs; the merge makes it 97, re-measured twice via the pinned method on the merged tree: 97/97."
|
|
65
|
+
"baseline_note": "80 → 81 on 2026-08-03 (release 9.15.0 gate). This RECORDS growth that already shipped through its own reviewed PR; it does not authorize new surface. The +1 is f02db54c2 (fix(cli): register routing:doctor in the CLI registry) — the command existed, only its registry entry was missing, and the registering PR did not move this budget. The gate did its job again: breach WARNS on main and BLOCKS on release, which is the conscious-decision point rather than a silently raised cap. Re-measured 2026-08-03 via the pinned method: 81. Headroom stays zero by design — the next registry addition must move this number in its own PR. 81 → 82 on 2026-08-04: the `handoff` subcommand (road-to-agent-handoff-resume Phase 4) registers in the same PR that adds the surface, per this record's own contract. Re-measured via the pinned method: 82. 82 → 84 on 2026-08-04: the `route:explain` + `route:audit` verbs (routing-correctness validation surface) register in the same PR that adds the surface. Re-measured via the pinned method: 84. 84 → 85 on 2026-08-05: the `settings:set` verb (road-to-zero-ceremony-settings Phase 2 — the one agent-reachable settings writer) registers in the same PR that adds the surface, per this record's own contract. Re-measured via the pinned method: 85. 85 → 86 on 2026-08-06: the `conformance:behavior` verb (road-to-agent-behavior-conformance Phase 5 — replays the local transcript store through the four mechanised conformance checks) registers in the same PR that adds the surface, per this record's own contract. Re-measured via the pinned method: 86. 86 → 88 on 2026-08-07: the `sessions:list` + `sessions:claim` verbs (road-to-parallel-session-coordination — the shell surface of the shared session register, needed because /roadmap:next is command markdown and can only reach the register through a shell call) register in the same PR that adds the surface, per this record's own contract. Re-measured via the pinned method: 88. 88 → 89 on 2026-08-08: the `council:status` verb registers in the same PR that adds the surface, per this record's own contract. It exists because an agent in a consumer project announced \"kein Council konfiguriert (keine .agent-settings.yml)\" and substituted a weaker path while the council was configured user-globally the whole time — there was no verb that answered availability, so the only route was an inference from a filename, and the intuitive filename is the one location ADR-104 guarantees is never consulted. Re-measured via the pinned method: 89. 89 → 91 on 2026-08-08: the `self-repair:status` + `self-repair:release` verbs (the queued-defect reader and the single Hard-Floor-gated outward step of the self-repair loop — the loop is deliberately unable to publish unless a human runs the release command) register in the same PR that adds the surface, per this record's own contract. Landed alongside the +1 council:status move in the same branch. Re-measured via the pinned method: 91. 91 → 94 on 2026-08-08: the `packs:active`, `settings:get` and `mcp:available` verbs (road-to-capability-answerability Phase 2 — the three capability probes for the gaps that had none) register in the same PR that adds the surface, per this record's own contract. Each answers a question that was previously only inferable from a filename: which packs are active and from which file, what a setting resolves to and which file set it, and what is declared in mcp.json versus what can actually launch. 94 -> 95 in the same PR: `brand:status` (Phase 2.4 — brand-layer presence, which the rule depended on and no surface could answer). Re-measured twice via the pinned method on the unchanged tree: 95/95. 95 → 96 on 2026-08-10: the `session:recycle` verb (road-to-token-economy-recycling Phase 2.2 — the deterministic producer of the main-session recycle envelope; the recycle advisory names this exact verb, so it must exist as a shell surface) registers in the same PR that adds the surface, per this record's own contract. Re-measured via the pinned method: 96. 96 -> 97 on 2026-08-10: the `gates` verb registers in the same PR that adds the surface, per this record's own contract. It exists because the blocker fields the dashboard already parses (Owner, What to do, Resolved when — CI-enforced by lint_roadmap_blockers) had no owner-filtered reader: the dashboard counts the open blockers across a 600-line file and links each to a per-roadmap anchor, so \"which of these are mine\" was a manual read of every anchor. The same inference-from-a-filename shape as the council:status entry above, one layer up. This branch and the session:recycle branch each measured 96 independently and landed on the same number for different verbs; the merge makes it 97, re-measured twice via the pinned method on the merged tree: 97/97. 97 -> 98 on 2026-08-15: the `workspace:doctor` verb (road-to-inbox-harvest-2026-08-c-workspace-identity Phase 3 — the read-only report over the new `workspaceIdentity()` resolver) registers in the same PR that adds the surface, per this record's own contract. It exists for the same inference-from-a-filename shape as the council:status and gates entries above, one layer down: the tree answered \"where am I\" in eight ad-hoc places across six files, and the 12.0.0 span shipped the same worktree misclassification twice, so no verb could be asked which checkout is the main one. Read-only by construction — the roadmap's Non-goals put worktree disposal out of scope and its Risk 3 names \"the pressure read becomes a disposal path by accident\" as the failure to design against, so the command carries no --fix and no --prune. Re-measured twice via the pinned method on the unchanged tree: 98/98."
|
|
66
66
|
},
|
|
67
67
|
"mcp_public_tool_count": {
|
|
68
68
|
"max": 19,
|
|
@@ -42,18 +42,19 @@
|
|
|
42
42
|
#
|
|
43
43
|
# COVERAGE — THE HONEST DENOMINATOR (re-measured 2026-08-13)
|
|
44
44
|
# ----------------------------------------------------------
|
|
45
|
-
#
|
|
45
|
+
# 259 `lint_*` / `check_*` / `audit_*` scripts live under `src/scripts/`
|
|
46
46
|
# (the count is computed, not asserted — `check_gate_coverage.count_gate_scripts`).
|
|
47
|
-
# **
|
|
48
|
-
# CI-identical argv, and all
|
|
47
|
+
# **36 of them emit the machine-readable `scanned: <N>` line under their
|
|
48
|
+
# CI-identical argv, and all 36 are listed below.** The manifest is therefore
|
|
49
49
|
# complete with respect to its own contract, and covers ~14 % of the population.
|
|
50
50
|
# (The 2026-08-05 reading said "32 … and all 31 are listed"; the 2026-08-10
|
|
51
|
-
# reading said "33 … and all 33" while 34 entries were listed
|
|
52
|
-
#
|
|
53
|
-
#
|
|
54
|
-
#
|
|
55
|
-
#
|
|
56
|
-
#
|
|
51
|
+
# reading said "33 … and all 33" while 34 entries were listed; the 2026-08-13
|
|
52
|
+
# reading said "257 … 35 of them" and both halves were correct at the time.
|
|
53
|
+
# Both halves are RECOUNTED here on 2026-08-15: 259 is what
|
|
54
|
+
# `count_gate_scripts()` returns on the tree that carries this change — the
|
|
55
|
+
# reading was 258 with `lint_scheduled_deprecations` absent — and 36 is
|
|
56
|
+
# `grep -c '^ - id:'` on this file. Neither number was derived by adding one to
|
|
57
|
+
# the previous prose, which is the move the note below forbids.)
|
|
57
58
|
#
|
|
58
59
|
# A 2026-08-13 revision of this paragraph first wrote 256, derived as "255 before
|
|
59
60
|
# this change plus the one it adds" — inside the sentence claiming to have
|
|
@@ -769,3 +770,32 @@ gates:
|
|
|
769
770
|
The canary plants a manifest whose declared CSV does not exist — the exact
|
|
770
771
|
gap `corpus-grounding/scripts/schema_validator.ts` leaves open, since it
|
|
771
772
|
computes the path and never opens the file.
|
|
773
|
+
|
|
774
|
+
- id: lint_scheduled_deprecations
|
|
775
|
+
argv: ["--quiet"]
|
|
776
|
+
min_scanned: 1
|
|
777
|
+
corpus: "rows of the `docs/MIGRATION.md` scheduled-deprecations table (3 at baseline)"
|
|
778
|
+
status: enforced
|
|
779
|
+
note: >
|
|
780
|
+
`argv` carries `--quiet` because that is what the task passes: the
|
|
781
|
+
Taskfile resolves `{{.QUIET_FLAG}}` to `--quiet` unless
|
|
782
|
+
AGENT_SCRIPT_VERBOSITY=verbose, and the consistency workflow goes through
|
|
783
|
+
the same task. It passed as a bare call only because `reportScanned` is
|
|
784
|
+
not quiet-gated while this gate's success line and ledger report are — a
|
|
785
|
+
coincidence, not the contract rule 2 states.
|
|
786
|
+
The floor is 1, not "a floor comfortably below the corpus", and the reason
|
|
787
|
+
is worth stating rather than hiding: the corpus is three rows, so no floor
|
|
788
|
+
exists that is both below it and far above a collapse. What the floor
|
|
789
|
+
actually buys here is the contract that the count is PUBLISHED; the
|
|
790
|
+
collapse case — a drifted heading or a reformatted table parsing to zero
|
|
791
|
+
rows — is caught one layer up by the gate's own `reportScanned`
|
|
792
|
+
assertion, which reds instead of printing a green line over nothing.
|
|
793
|
+
That case is the gate's own subject, so it is pinned by a test fixture
|
|
794
|
+
too (`a table that parses to zero rows reds rather than exiting green`).
|
|
795
|
+
No `canary:` recipe: this gate's only violation shape is a MODIFICATION of
|
|
796
|
+
a tracked artefact (`docs/MIGRATION.md`), and the canary contract is
|
|
797
|
+
create-only, so it reports UNPROVEN rather than green. Discrimination is
|
|
798
|
+
proven instead by paired fixtures in
|
|
799
|
+
`tests/scripts/lint_scheduled_deprecations.test.ts`, verified by mutation:
|
|
800
|
+
widening the overdue threshold fails the overdue-by-construction case, and
|
|
801
|
+
granting `allowEmpty` fails the zero-row case.
|
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
"falsifier": "./scripts-run src/scripts/check_ci_local_parity"
|
|
9
9
|
},
|
|
10
10
|
"check_no_new_legacy_path:hardcoded-scan-roots": {
|
|
11
|
-
"count":
|
|
12
|
-
"landed": "2026-08-
|
|
13
|
-
"note": "Lines under src/scripts/**/*.{ts,mts,mjs} that pass the retired `.agent-src.uncondensed` directory into `path.join(...)` — a filesystem path CONSTRUCTED against the tree ADR-051 abandoned, which is the exact shape of all 14 dead gates. Deliberately narrow so the number is signal, not noise: 236 raw mentions under src/scripts → 147 string-literal lines → 67 path-constructing lines when the pass was written, after exempting src/scripts/_lib/agent_src.ts (the shared resolver, whose job IS owning the constant — gates that route through it survived the move). Detectors holding the literal as data to match, strip, or print are not counted, and no prose, docs, tests or fixtures are read: that full-tree shape was measured at 44 files / 213 hits and rejected as the wrong lint (see the note in check_no_new_legacy_path.ts::find_offenders). Recorded at 58 rather than 67 because Phase 1's scan-root repairs were landing on this branch while the pass was being written and had already removed 9 — a baseline above the truth silently permits new violations. This count goes to ZERO as the remaining repairs land; every repair is a lowering commit. Lowered 56→51 by the road-to-renewal-foundation Phase 1 dead-root sweep (check_always_budget, check_portability, check_references, lint_framework_leakage, lint_agents_md). Lowered 51→49 by the gate-hardening adoption PR: skill_collision_clusters and skill_overlap were repointed at the live skills tree via the shared resolver — two gates that had been reading the retired container and scoring 0 of 288 skills. Lowered 49→48 by road-to-rule-delivery-integrity P2.2: score_skill_selection was repointed at the live skills tree via the shared resolver. It is the same shape as the two gates lowered before it — a scorer reading the retired container and scoring 0 of 288 skills — and here the consequence was sharper than a dead gate: the roadmap's pre-registered selection-accuracy criteria would have been compared against a baseline of silent zeros."
|
|
11
|
+
"count": 47,
|
|
12
|
+
"landed": "2026-08-13",
|
|
13
|
+
"note": "Lines under src/scripts/**/*.{ts,mts,mjs} that pass the retired `.agent-src.uncondensed` directory into `path.join(...)` — a filesystem path CONSTRUCTED against the tree ADR-051 abandoned, which is the exact shape of all 14 dead gates. Deliberately narrow so the number is signal, not noise: 236 raw mentions under src/scripts → 147 string-literal lines → 67 path-constructing lines when the pass was written, after exempting src/scripts/_lib/agent_src.ts (the shared resolver, whose job IS owning the constant — gates that route through it survived the move). Detectors holding the literal as data to match, strip, or print are not counted, and no prose, docs, tests or fixtures are read: that full-tree shape was measured at 44 files / 213 hits and rejected as the wrong lint (see the note in check_no_new_legacy_path.ts::find_offenders). Recorded at 58 rather than 67 because Phase 1's scan-root repairs were landing on this branch while the pass was being written and had already removed 9 — a baseline above the truth silently permits new violations. This count goes to ZERO as the remaining repairs land; every repair is a lowering commit. Lowered 56→51 by the road-to-renewal-foundation Phase 1 dead-root sweep (check_always_budget, check_portability, check_references, lint_framework_leakage, lint_agents_md). Lowered 51→49 by the gate-hardening adoption PR: skill_collision_clusters and skill_overlap were repointed at the live skills tree via the shared resolver — two gates that had been reading the retired container and scoring 0 of 288 skills. Lowered 49→48 by road-to-rule-delivery-integrity P2.2: score_skill_selection was repointed at the live skills tree via the shared resolver. It is the same shape as the two gates lowered before it — a scorer reading the retired container and scoring 0 of 288 skills — and here the consequence was sharper than a dead gate: the roadmap's pre-registered selection-accuracy criteria would have been compared against a baseline of silent zeros. Lowered 48→47 on 2026-08-13, and this one is a catch-up rather than a repair: the pass reported 47 against a baseline of 48, so a gain had already landed without the ratchet following it. Attributed to 455160160 (fix(evals): resolve the eval orchestrator against the live skills tree), the most recent repair in this branch's base that removes a path-constructing line — SKILLS_ROOT repointed through _lib/agent_src.ts::SRC_SKILLS(). A loose ratchet is not harmless: it silently permits one new violation to be added back without any gate noticing, which is the shape this entry exists to prevent."
|
|
14
14
|
},
|
|
15
15
|
"audit_user_type_axis": {
|
|
16
16
|
"count": 1,
|
|
@@ -22,6 +22,12 @@
|
|
|
22
22
|
"landed": "2026-08-02",
|
|
23
23
|
"note": "All 18 are `handoff_tier_mismatch`: a senior-tier skill links to a peer whose frontmatter carries no `tier` (reported as tier='unset') — e.g. build-buy-partner → adr-create, customer-research → po-discovery, gated-reach → threat-modeling. This is a tier-metadata backfill backlog on the LINKED-TO skills, not a broken link. The one genuinely dangling link revealed by the same repair (competitive-positioning → a non-existent ../analyze-reference-repo/SKILL.md; it is a command, not a skill) was FIXED in the repairing commit rather than baselined. Clearing this entry means backfilling `tier` on the linked-to skills, or deciding that `tier: unset` on a link target is not a violation and narrowing the rule."
|
|
24
24
|
},
|
|
25
|
+
"lint_roadmap_blockers:decidability": {
|
|
26
|
+
"count": 34,
|
|
27
|
+
"landed": "2026-08-15",
|
|
28
|
+
"note": "Open blocker entries that are not yet DECIDABLE by the person who owns them — missing `Recommendation:` (which option and why), missing `If you do nothing:` (the cost of the non-decision), or a `What to do:` carrying no command, path or enumerated option set. Revealed by adding the decidability half to lint_roadmap_blockers, not created by it: the five original fields describe a situation and never made it actionable, so a blocker could pass the contract while handing the analysis back to the person least equipped to redo it. Measured at introduction: 36 open entries, ALL 36 undecidable, and 14 of the 46 total entries carry no command/path/option at all in `What to do`. Baselined rather than hard-failed because 36 findings nobody can clear in the change that reveals them is the gate-that-lands-as-N-instant-blockers failure this repository has refused before — the same reasoning as ci-parity:local-only above. First measured at 34 rather than 36 because the two blockers on the branch that introduced this (`ac3-false-positive-reading`, `publish-side-marker-invariant`) were rewritten to the new standard and then closed in the same change; a baseline above the truth silently permits new violations. Re-measured at 38 when the branch was re-pointed at current main, and the +4 is population growth rather than a loosening: main gained the four `road-to-inbox-harvest-2026-08-d-*` roadmaps (context-ledger, runtime-skill-routing, scheduled-deprecation, top-band-model-economy), each carrying one open blocker authored before this requirement existed. That is the honest number for the population this gate now scans — recording 34 against a 38-entry tree would have failed the gate on its own introducing commit and taught the next reader to distrust it. Lowering happens one blocker at a time, and every roadmap touched for other reasons is a chance to lower it. Lowered 38→37 by the scheduled-deprecation PR, which is exactly that shape: code-graph-removal-authorisation was rewritten to the new standard because the roadmap was being touched anyway. Its `If you do nothing:` was one of the few that was not the common no-cost answer — the release gate that PR ships would have refused the next major cut while the blocker stayed open. Recorded in the past tense because the maintainer then RESOLVED that blocker on the trunk by withdrawing the commitment, so nothing refuses a cut today. The lowering stands on the rewrite, not on the consequence, and the sentence is corrected rather than deleted because a baseline note arguing from a retracted state is how a ratchet's rationale rots. The 56-day expiry is the point, not a hazard: if this number has not moved in two months, the fields are not being written and the gate should fail until someone decides whether the requirement is real. Lowered 37→34 when the scheduled-deprecation branch merged current main: three blockers were resolved or rewritten on the trunk in the meantime, so the drop is a genuine drain plus a merge, not a loosening. Re-tightened here rather than left loose because a ratchet that lags its own tree permits violations back in silently.",
|
|
29
|
+
"falsifier": "./scripts-run src/scripts/lint_roadmap_blockers --quiet"
|
|
30
|
+
},
|
|
25
31
|
"lint_pack_boundaries": {
|
|
26
32
|
"count": 337,
|
|
27
33
|
"landed": "2026-08-02",
|
|
@@ -58,10 +58,16 @@
|
|
|
58
58
|
"instrument": "rule-trips.json warn counters per concern"
|
|
59
59
|
},
|
|
60
60
|
"unbounded_output_advisory_rate": {
|
|
61
|
-
"definition": "Roadmap 4.3 + 4.4 registration (advisory-degraded per the resolved pretooluse-rewrite-semantics blocker: no updatedInput in the v1 contract, so nothing caps and nothing can be bypassed - the demand signal is the fire count itself). rtk-wrap cap-advisory fires per session from the OUTPUT_CAP_TABLE branch; adoption (did the next run use a bounded form) via conformance audits.
|
|
61
|
+
"definition": "Roadmap 4.3 + 4.4 registration (advisory-degraded per the resolved pretooluse-rewrite-semantics blocker: no updatedInput in the v1 contract, so nothing caps and nothing can be bypassed - the demand signal is the fire count itself). rtk-wrap cap-advisory fires per session from the OUTPUT_CAP_TABLE branch; adoption (did the next run use a bounded form) via conformance audits. GAP CLOSED 2026-08-15 (road-to-inbox-harvest-2026-08-d-context-ledger Step 1.1): the tool-result byte counter now exists and its stream is registered below as `tool_result_bytes`. The pre/post bytes half of roadmap 4.4 is measurable from that census once it carries data; it stays unread, not unmeasurable, until a baseline is published.",
|
|
62
62
|
"instrument": "rule-trips.json warn counters for the rtk-wrap concern + conformance audits",
|
|
63
63
|
"threshold": "none committed before data - baseline first, threshold at review date"
|
|
64
64
|
},
|
|
65
|
+
"tool_result_bytes": {
|
|
66
|
+
"definition": "road-to-inbox-harvest-2026-08-d-context-ledger 1.1: UTF-8 bytes of every tool RESULT entering context, per call, keyed by tool name. Closes the gap `unbounded_output_advisory_rate` registered above - the injection census measures what this suite puts into context, this measures what the host's tools do, and the second is the larger term. CAPTURE ONLY: the concern emits zero bytes to the model, so it carries no per-concern injection cap; it is registered here because this file already owns the owner/review discipline for context-cost instruments.",
|
|
67
|
+
"instrument": "the `tool-result-bytes` concern (src/scripts/hooks/tool_result_bytes_hook.ts) on post_tool_use, appending {ts, tool, bytes, measurable} to agents/runtime/state/tool-result-census.jsonl",
|
|
68
|
+
"privacy": "census lines carry a tool NAME, a byte COUNT and a timestamp - the record type has no field able to hold file contents, command output or any free text, so there is no scrubber that can fail",
|
|
69
|
+
"threshold": "none committed before data - baseline first, threshold at review date. A `measurable: false` line means the host's payload carried no readable result; that absence is itself a coverage finding and is never counted as zero bytes"
|
|
70
|
+
},
|
|
65
71
|
"turns_per_task": {
|
|
66
72
|
"definition": "user_prompt_submit count keyed to the task envelope - the invisible multiplier (every turn re-pays the accumulated context at read rates).",
|
|
67
73
|
"instrument": "session-register / chat-history turn counters; HONEST GAP: no task-envelope key exists yet in those counters - the number is per-SESSION until a task key ships; registered with that stated limitation rather than silently redefined",
|
|
@@ -35,6 +35,34 @@
|
|
|
35
35
|
"p95": 50000,
|
|
36
36
|
"_comment": "The roadmap's candidate numbers, kept as the destination. Reaching them needs reductions this package has not built yet; scope-dedup (C-3) removes a redundant COPY at the consumer, it does not shrink the suite itself."
|
|
37
37
|
},
|
|
38
|
+
"target_schedule": {
|
|
39
|
+
"_comment": "road-to-inbox-harvest-2026-08-d-context-ledger Step 5.3. The target above was a destination with no route: the ratchet fails on GROWTH only, so the corpus can drift away from 40k indefinitely without any gate objecting. These milestones give the destination a schedule. They are DATES WITH NUMBERS, not a derivation - no measurement in this tree says the estate can reach 85k by a given day, and pretending otherwise would be the invented-threshold failure this file's own baseline_history is careful to avoid. What they buy is that a miss becomes a published fact with an owner instead of a silent drift.",
|
|
40
|
+
"owner": "maintainer",
|
|
41
|
+
"measured_at_registration": {
|
|
42
|
+
"tokens": 125593,
|
|
43
|
+
"at": "2026-08-15",
|
|
44
|
+
"note": "MEASURED total at registration time, from check_preamble_payload_budget. It is ~23k ABOVE both baseline_tokens (102520) and the derived ceiling, i.e. the gate is red on the tree as it stands. The baseline is deliberately NOT raised to meet it - raising a ratchet baseline to clear a failing check is the config-weakening move this repo blocks by construction. It is recorded here so the milestones below are planned against the real starting point rather than a stale one. Per-rule ranking: agents/evidence/analysis/rule-paths-coverage-census.md"
|
|
45
|
+
},
|
|
46
|
+
"milestones": [
|
|
47
|
+
{
|
|
48
|
+
"by": "2026-11-10",
|
|
49
|
+
"tokens": 102520,
|
|
50
|
+
"why": "Return to the registered baseline. This is a RECOVERY milestone, not progress toward 40k - it undoes drift rather than shrinking the estate. The date is the review_by both budget files already carry, so it needs no new calendar."
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"by": "2027-02-10",
|
|
54
|
+
"tokens": 85000,
|
|
55
|
+
"why": "First real reduction. The rule-paths census shows 92.1% of rule weight sits in the auto tier and the top 20 files carry 35.5% of it, so a scoped tranche is the plausible mechanism - GATED on the paths-scoping consumer decision, which is a human call and may resolve against scoping entirely."
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"by": "2027-05-10",
|
|
59
|
+
"tokens": 60000,
|
|
60
|
+
"why": "Second reduction. No mechanism is committed for this one; it exists so the destination keeps a date after the first tranche lands, and it is the milestone most likely to be revised on evidence."
|
|
61
|
+
}
|
|
62
|
+
],
|
|
63
|
+
"on_miss": "A missed milestone is PUBLISHED - recorded here with the measured number and the reason - and never silently re-dated. Two consecutive misses mean the schedule was wrong or the destination is unreachable with the mechanisms available; either outcome is a decision to surface, not a date to move again.",
|
|
64
|
+
"revisit_if": "The paths-scoping decision resolves against scoping (removing the only named mechanism for the 85k milestone), or a measured reduction lands ahead of schedule and the remaining milestones are re-derived from it."
|
|
65
|
+
},
|
|
38
66
|
"reference_measurements": {
|
|
39
67
|
"measured_cold_start_median_tokens": 230930,
|
|
40
68
|
"c3_scope_dedup_reduction_pct": 38,
|
|
@@ -250,6 +250,11 @@ Tier 2 — maintenance / internal (hooks, MCP, memory, telemetry):
|
|
|
250
250
|
router + projection freshness, host bridge status.
|
|
251
251
|
Flags: --platform <p>, --workspace <path>, --json, --strict,
|
|
252
252
|
--no-freshness
|
|
253
|
+
workspace:doctor One answer to "where am I": repo root, main worktree, current
|
|
254
|
+
worktree, branch, PR base — each with its provenance — plus
|
|
255
|
+
session claim, conflicting records and worktree pressure.
|
|
256
|
+
Read-only; no disposal path by design.
|
|
257
|
+
Flags: --from <dir>, --json, --strict
|
|
253
258
|
route:explain Deterministic rule-routing trace for one prompt: matched
|
|
254
259
|
triggers, tier, injected-vs-pointer disposition, budget
|
|
255
260
|
consumption, rejected candidates. Trigger-match level only
|
|
@@ -447,6 +452,9 @@ require_tsx() {
|
|
|
447
452
|
# command surface (`sync`, `doctor`, `validate`, `upgrade`, …) and its
|
|
448
453
|
# basenames are unique, so the mapping is collision-free. Other exec_ts
|
|
449
454
|
# callers (resolve_script results, the work engine, …) are unaffected.
|
|
455
|
+
#
|
|
456
|
+
# In a DEV tree the bundle is also suppressed when any `src/**/*.ts` is newer
|
|
457
|
+
# than it — see cli_delegate_bundle_is_stale.
|
|
450
458
|
cli_delegate_bundle() {
|
|
451
459
|
local ts_abs="$1"
|
|
452
460
|
case "$ts_abs" in
|
|
@@ -457,18 +465,52 @@ cli_delegate_bundle() {
|
|
|
457
465
|
name="$(basename "${ts_abs%.ts}")"
|
|
458
466
|
local bundle="$PACKAGE_ROOT/dist/cli-delegate/$name.js"
|
|
459
467
|
if [[ -f "$bundle" ]] && command -v node >/dev/null 2>&1; then
|
|
468
|
+
cli_delegate_bundle_is_stale "$bundle" && return 0
|
|
460
469
|
printf '%s' "$bundle"
|
|
461
470
|
fi
|
|
462
471
|
}
|
|
463
472
|
|
|
473
|
+
# Is a `dist/cli-delegate/` bundle older than the sources it was built from?
|
|
474
|
+
#
|
|
475
|
+
# Only asked in a DEV tree — `$PACKAGE_ROOT/src` exists there and nowhere else.
|
|
476
|
+
# A consumer install ships no `src/`, so it returns "not stale" without a single
|
|
477
|
+
# stat and the ADR-204 fast path is untouched.
|
|
478
|
+
#
|
|
479
|
+
# The scan covers `src` WHOLE, not `src/scripts`: `_cli/*.ts` imports reach into
|
|
480
|
+
# `src/shared`, `src/install`, `src/server`, `src/agent`, `src/config` and
|
|
481
|
+
# `src/agent-src`, and the defect this guard exists for lived two hops away in
|
|
482
|
+
# `src/scripts/_lib/cc_transcript.ts` — a scan narrowed to the entry point's own
|
|
483
|
+
# directory would have missed it.
|
|
484
|
+
#
|
|
485
|
+
# Cost, measured 2026-08-14 on the local tree (1075 `.ts` files): 78 ms when the
|
|
486
|
+
# bundle is current (the full walk) and ~12 ms when it is not (`-quit` exits at
|
|
487
|
+
# the first newer file). The bundle saves ~290 ms against the tsx path, so the
|
|
488
|
+
# worst case still leaves most of that — and buys the guarantee that a dev-tree
|
|
489
|
+
# edit is never silently ignored in favour of a stale compile.
|
|
490
|
+
cli_delegate_bundle_is_stale() {
|
|
491
|
+
local bundle="$1"
|
|
492
|
+
[[ -d "$PACKAGE_ROOT/src" ]] || return 1
|
|
493
|
+
local newer
|
|
494
|
+
newer="$(find "$PACKAGE_ROOT/src" -name '*.ts' -newer "$bundle" -print -quit 2>/dev/null)"
|
|
495
|
+
[[ -n "$newer" ]]
|
|
496
|
+
}
|
|
497
|
+
|
|
464
498
|
# Run an absolute script path. The argument is an absolute path that may carry
|
|
465
499
|
# a `.py` (legacy) or `.ts` extension; we resolve the `.ts` twin.
|
|
466
500
|
#
|
|
467
|
-
# A precompiled `dist/cli-delegate/` bundle wins when present
|
|
468
|
-
# tree ships no tsx (see require_tsx), and the bundle is also
|
|
469
|
-
# than the npx path it replaces (p50 56-71 ms vs 346-392 ms,
|
|
470
|
-
# 2026-07-31; see docs/decisions/ADR-204). The tsx path stays as the
|
|
471
|
-
# route and as the fallback for every non-`_cli` caller.
|
|
501
|
+
# A precompiled `dist/cli-delegate/` bundle wins when present AND not stale —
|
|
502
|
+
# the consumer tree ships no tsx (see require_tsx), and the bundle is also
|
|
503
|
+
# ~5.7x faster than the npx path it replaces (p50 56-71 ms vs 346-392 ms,
|
|
504
|
+
# measured 2026-07-31; see docs/decisions/ADR-204). The tsx path stays as the
|
|
505
|
+
# dev-tree route and as the fallback for every non-`_cli` caller.
|
|
506
|
+
#
|
|
507
|
+
# "Not stale" is the load-bearing qualifier, and it was added because the
|
|
508
|
+
# unqualified version shipped a real failure: a dev-tree `dist/cli-delegate/`
|
|
509
|
+
# built before a `projectStoreSlug` fix kept running the OLD slug, so
|
|
510
|
+
# `agent-config handoff --list` reported "no recent sessions" in any worktree
|
|
511
|
+
# whose path carried a `+`, while the fixed source right next to it listed ten.
|
|
512
|
+
# A compiled copy that silently outranks the source it was built from turns
|
|
513
|
+
# every edit into a coin flip — see cli_delegate_bundle_is_stale.
|
|
472
514
|
#
|
|
473
515
|
# Argv/stdin/stdout/stderr/exit-code pass through unchanged in both routes —
|
|
474
516
|
# mirrors src/scripts/run.ts resolution.
|
|
@@ -862,6 +904,10 @@ cmd_routing_doctor() {
|
|
|
862
904
|
exec_hook "src/scripts/routing_doctor" "$@"
|
|
863
905
|
}
|
|
864
906
|
|
|
907
|
+
cmd_workspace_doctor() {
|
|
908
|
+
exec_hook "src/scripts/workspace_doctor" "$@"
|
|
909
|
+
}
|
|
910
|
+
|
|
865
911
|
cmd_hooks_replay() {
|
|
866
912
|
exec_hook "src/scripts/hooks/replay_hook" "$@"
|
|
867
913
|
}
|
|
@@ -1385,6 +1431,7 @@ main() {
|
|
|
1385
1431
|
hooks:status) cmd_hooks_status "$@" ;;
|
|
1386
1432
|
hooks:doctor) cmd_hooks_doctor "$@" ;;
|
|
1387
1433
|
routing:doctor) cmd_routing_doctor "$@" ;;
|
|
1434
|
+
workspace:doctor) cmd_workspace_doctor "$@" ;;
|
|
1388
1435
|
route:explain) cmd_route_explain "$@" ;;
|
|
1389
1436
|
route:audit) cmd_route_audit "$@" ;;
|
|
1390
1437
|
hooks:replay) cmd_hooks_replay "$@" ;;
|
|
@@ -126,3 +126,176 @@ export function git_common_dir(project_root: string): string | null {
|
|
|
126
126
|
return null;
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
|
+
|
|
130
|
+
// ---------------------------------------------------------------------------
|
|
131
|
+
// Workspace identity
|
|
132
|
+
// ---------------------------------------------------------------------------
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* One answer to one identity question, and never a silent default.
|
|
136
|
+
*
|
|
137
|
+
* The census that motivated this type (`agents/evidence/analysis/
|
|
138
|
+
* workspace-identity-census.md`) found three of eight repo-root sites falling
|
|
139
|
+
* back to a value that is *plausible but wrong* when git cannot answer —
|
|
140
|
+
* `process.cwd()`, a path derived from the script's own location, an
|
|
141
|
+
* exception. A caller cannot distinguish those from a real answer, which is
|
|
142
|
+
* how a gate ends up scanning the wrong tree and exiting green.
|
|
143
|
+
*/
|
|
144
|
+
export type IdentityField =
|
|
145
|
+
| { readonly resolved: true; readonly value: string; readonly provenance: string }
|
|
146
|
+
| { readonly resolved: false; readonly reason: string };
|
|
147
|
+
|
|
148
|
+
/** The five workspace-identity questions, each independently resolvable. */
|
|
149
|
+
export interface WorkspaceIdentity {
|
|
150
|
+
/**
|
|
151
|
+
* Top level of the working tree the caller is in — the drop-in for
|
|
152
|
+
* `git rev-parse --show-toplevel`. Inside a linked worktree this is the
|
|
153
|
+
* worktree's own root, exactly as git reports it.
|
|
154
|
+
*/
|
|
155
|
+
readonly repoRoot: IdentityField;
|
|
156
|
+
/**
|
|
157
|
+
* The main (non-linked) checkout. Derived from the common git dir, so it
|
|
158
|
+
* is the same value from every worktree of the repo. This is the field the
|
|
159
|
+
* two shipped misclassification defects needed and did not have.
|
|
160
|
+
*/
|
|
161
|
+
readonly mainWorktree: IdentityField;
|
|
162
|
+
/**
|
|
163
|
+
* The checkout the caller is in. Its `value` equals `repoRoot` by git's own
|
|
164
|
+
* definition; the two fields exist separately because the *provenance*
|
|
165
|
+
* differs and that is the part callers need — `main-checkout` versus
|
|
166
|
+
* `linked-worktree` is precisely the question `isStandardLocation` got
|
|
167
|
+
* wrong twice.
|
|
168
|
+
*/
|
|
169
|
+
readonly currentWorktree: IdentityField;
|
|
170
|
+
/** Branch of the current checkout; unresolved on a detached HEAD. */
|
|
171
|
+
readonly branch: IdentityField;
|
|
172
|
+
/**
|
|
173
|
+
* The remote's default branch, as a `refs/remotes/<remote>/<name>` ref —
|
|
174
|
+
* the offline notion of "what a PR from here would target".
|
|
175
|
+
*
|
|
176
|
+
* Deliberately NOT the `gh`-derived base of an actual open PR: that needs
|
|
177
|
+
* network and auth, and `check_branch_freshness.ts` already owns it. This
|
|
178
|
+
* field answers the question a gate can answer without leaving the disk,
|
|
179
|
+
* and reports `unresolved` rather than guessing `main` when the repo has
|
|
180
|
+
* no recorded default.
|
|
181
|
+
*/
|
|
182
|
+
readonly prBase: IdentityField;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function resolved(value: string, provenance: string): IdentityField {
|
|
186
|
+
return { resolved: true, value, provenance };
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function unresolved(reason: string): IdentityField {
|
|
190
|
+
return { resolved: false, reason };
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Walk up from `start` to the first directory holding a `.git` entry.
|
|
195
|
+
*
|
|
196
|
+
* File-based on purpose, like everything else here: `rev-parse --show-toplevel`
|
|
197
|
+
* would be redirected by an inherited `GIT_DIR`, and the symptom is a wrong
|
|
198
|
+
* path rather than an error.
|
|
199
|
+
*/
|
|
200
|
+
function discover_root(start: string): string | null {
|
|
201
|
+
let dir = realpath_or_self(path.resolve(start));
|
|
202
|
+
for (;;) {
|
|
203
|
+
if (fs.existsSync(path.join(dir, '.git'))) return dir;
|
|
204
|
+
const parent = path.dirname(dir);
|
|
205
|
+
if (parent === dir) return null;
|
|
206
|
+
dir = parent;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Is `project_root`'s `.git` a linked-worktree pointer file rather than a
|
|
212
|
+
* directory? Returns `null` when there is no `.git` entry at all.
|
|
213
|
+
*/
|
|
214
|
+
function is_linked_worktree(project_root: string): boolean | null {
|
|
215
|
+
try {
|
|
216
|
+
return !fs.statSync(path.join(project_root, '.git')).isDirectory();
|
|
217
|
+
} catch {
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/** The remote default branch ref, read from disk. `null` when unrecorded. */
|
|
223
|
+
function remote_head_ref(common_dir: string, remote: string): string | null {
|
|
224
|
+
// A symbolic ref is stored loose; `git pack-refs` never packs one, so
|
|
225
|
+
// packed-refs is not a fallback for this specific ref — a repo that has
|
|
226
|
+
// never run `git remote set-head` simply has no answer on disk.
|
|
227
|
+
try {
|
|
228
|
+
const raw = fs.readFileSync(path.join(common_dir, 'refs', 'remotes', remote, 'HEAD'), 'utf-8');
|
|
229
|
+
const m = raw.match(/^ref:\s*(refs\/remotes\/.+?)\s*$/m);
|
|
230
|
+
return m === null ? null : m[1]!.trim();
|
|
231
|
+
} catch {
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Resolve all five workspace-identity questions from `start` (default: the
|
|
238
|
+
* process cwd), reading files only.
|
|
239
|
+
*
|
|
240
|
+
* Every field is either a value with its provenance or an explicit reason it
|
|
241
|
+
* could not be resolved. Nothing here throws and nothing guesses.
|
|
242
|
+
*/
|
|
243
|
+
export function workspaceIdentity(
|
|
244
|
+
start: string = process.cwd(),
|
|
245
|
+
remote = 'origin',
|
|
246
|
+
): WorkspaceIdentity {
|
|
247
|
+
const root = discover_root(start);
|
|
248
|
+
if (root === null) {
|
|
249
|
+
const why = `no .git entry in ${path.resolve(start)} or any ancestor`;
|
|
250
|
+
return {
|
|
251
|
+
repoRoot: unresolved(why),
|
|
252
|
+
mainWorktree: unresolved(why),
|
|
253
|
+
currentWorktree: unresolved(why),
|
|
254
|
+
branch: unresolved(why),
|
|
255
|
+
prBase: unresolved(why),
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const linked = is_linked_worktree(root);
|
|
260
|
+
const repoRoot = resolved(root, 'upward .git walk from cwd');
|
|
261
|
+
const currentWorktree = resolved(
|
|
262
|
+
root,
|
|
263
|
+
linked === true
|
|
264
|
+
? 'linked-worktree (.git is a gitdir pointer file)'
|
|
265
|
+
: 'main-checkout (.git is a directory)',
|
|
266
|
+
);
|
|
267
|
+
|
|
268
|
+
const common = git_common_dir(root);
|
|
269
|
+
let mainWorktree: IdentityField;
|
|
270
|
+
if (common === null) {
|
|
271
|
+
mainWorktree = unresolved('no common git dir resolvable from the repo root');
|
|
272
|
+
} else if (path.basename(common) === '.git') {
|
|
273
|
+
mainWorktree = resolved(path.dirname(common), 'dirname of the common git dir');
|
|
274
|
+
} else {
|
|
275
|
+
// Bare repo, `core.worktree`, or a separate-gitdir layout: the common
|
|
276
|
+
// dir is not `<main>/.git`, so `dirname` would name a directory that is
|
|
277
|
+
// not a checkout. Refusing is the point of the type.
|
|
278
|
+
mainWorktree = unresolved(
|
|
279
|
+
`common git dir ${common} is not named .git — bare or separate-gitdir layout has no main worktree to derive`,
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const br = current_branch(root);
|
|
284
|
+
const branch = br === null
|
|
285
|
+
? unresolved('detached HEAD, or HEAD unreadable in the per-worktree git dir')
|
|
286
|
+
: resolved(br, 'ref line of <git-dir>/HEAD');
|
|
287
|
+
|
|
288
|
+
let prBase: IdentityField;
|
|
289
|
+
if (common === null) {
|
|
290
|
+
prBase = unresolved('no common git dir resolvable from the repo root');
|
|
291
|
+
} else {
|
|
292
|
+
const ref = remote_head_ref(common, remote);
|
|
293
|
+
prBase = ref === null
|
|
294
|
+
? unresolved(
|
|
295
|
+
`no refs/remotes/${remote}/HEAD on disk — run \`git remote set-head ${remote} -a\`; not guessed`,
|
|
296
|
+
)
|
|
297
|
+
: resolved(ref, `symbolic ref refs/remotes/${remote}/HEAD`);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
return { repoRoot, mainWorktree, currentWorktree, branch, prBase };
|
|
301
|
+
}
|
|
@@ -25,7 +25,16 @@ import fs from "node:fs";
|
|
|
25
25
|
|
|
26
26
|
// Tier → Claude model. The ONLY per-vendor mapping the package maintains
|
|
27
27
|
// (ADR-035 § 3); other agents resolve the tier band to their own line-up.
|
|
28
|
+
//
|
|
29
|
+
// `frontier` was added by ADR-232, which amends ADR-035 § Decision 1 on that
|
|
30
|
+
// record's own reopen condition. The asymmetry that triggered it is worth
|
|
31
|
+
// keeping visible here: `MODEL_FAMILIES` in the orchestration-record hook has
|
|
32
|
+
// enumerated four families since it shipped, while this map named three — so a
|
|
33
|
+
// dispatch on the fourth band was recordable but not declarable. Adding the row
|
|
34
|
+
// here rather than a second table elsewhere is what keeps ADR-035 § 3 intact:
|
|
35
|
+
// one mapping, one owner, no two-clocks drift.
|
|
28
36
|
export const TIER_TO_CLAUDE_MODEL: Record<string, string> = {
|
|
37
|
+
frontier: "fable",
|
|
29
38
|
high: "opus",
|
|
30
39
|
medium: "sonnet",
|
|
31
40
|
lite: "haiku",
|