@event4u/agent-config 14.21.0 → 14.23.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 +164 -187
- package/CREDITS.md +37 -0
- package/README.md +1 -1
- package/dist/agent-src/commands/analyze/inbox.md +380 -5
- package/dist/agent-src/commands/analyze/repo.md +4 -2
- package/dist/agent-src/commands/pr/merge.md +47 -38
- package/dist/agent-src/commands/roadmap/next.md +8 -0
- package/dist/agent-src/contexts/communication/rules-auto/token-efficiency-mechanics.md +69 -0
- package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +5 -5
- package/dist/agent-src/contexts/execution/autonomy-mechanics.md +12 -0
- package/dist/agent-src/rules/external-code-graph-interop.md +19 -14
- package/dist/agent-src/rules/notes-first-reasoning.md +36 -25
- package/dist/agent-src/rules/token-efficiency.md +26 -3
- package/dist/agent-src/scripts/_cli_entry.ts +51 -0
- package/dist/agent-src/scripts/archive_completed_roadmaps.ts +120 -27
- package/dist/agent-src/scripts/roadmap_gates.ts +4 -20
- package/dist/agent-src/scripts/roadmap_set_step.ts +5 -2
- package/dist/agent-src/scripts/stubs_due.ts +4 -18
- package/dist/agent-src/scripts/update_roadmap_progress.ts +7 -24
- package/dist/agent-src/skills/code-intelligence/SKILL.md +82 -1
- package/dist/agent-src/skills/git-workflow/references/push-closes-its-loop.md +9 -0
- package/dist/agent-src/skills/roadmap-writing/SKILL.md +17 -0
- package/dist/agent-src/skills/tailwind-engineer/SKILL.md +52 -2
- package/dist/agent-src/templates/agent-settings.md +0 -1
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/cli/registry.js +1 -1
- package/dist/cli-delegate/_cli_entry.js +8 -0
- package/dist/cli-delegate/_lib/pin_resolver.js +170 -0
- package/dist/cli-delegate/archival_sweep.js +8 -0
- package/dist/cli-delegate/archive_completed_roadmaps.js +542 -0
- package/dist/cli-delegate/check_update_banner.js +923 -0
- package/dist/cli-delegate/{chunk-ZVBOHSVF.js → chunk-2KKXJW25.js} +23 -9
- package/dist/cli-delegate/chunk-5EK5WQN6.js +28 -0
- package/dist/cli-delegate/chunk-7XGD2OEU.js +96 -0
- package/dist/cli-delegate/chunk-DBH4AHDK.js +155 -0
- package/dist/cli-delegate/{chunk-4FS4WRXP.js → chunk-IAI3XL43.js} +15 -3
- package/dist/cli-delegate/chunk-JO25G5H7.js +20 -0
- package/dist/cli-delegate/{chunk-643Z7FIC.js → chunk-KCNTUSPI.js} +7 -1
- package/dist/cli-delegate/chunk-LTYVIY76.js +7961 -0
- package/dist/cli-delegate/chunk-QAJS5YWY.js +999 -0
- package/dist/cli-delegate/{chunk-YS6XTLEK.js → chunk-TYSY33MD.js} +56 -6
- package/dist/cli-delegate/chunk-ULET4BYS.js +328 -0
- package/dist/cli-delegate/chunk-YDQSHTD7.js +187 -0
- package/dist/cli-delegate/chunk-YWVXLR44.js +48 -0
- package/dist/cli-delegate/chunk-ZZQBUHFK.js +273 -0
- package/dist/cli-delegate/cmd_conformance.js +2 -2
- package/dist/cli-delegate/cmd_export.js +2 -2
- package/dist/cli-delegate/cmd_handoff.js +45 -13
- package/dist/cli-delegate/cmd_prune.js +2 -2
- package/dist/cli-delegate/cmd_session_recycle.js +4 -14
- package/dist/cli-delegate/cmd_settings_migrate.js +2 -2
- package/dist/cli-delegate/cmd_settings_set.js +1 -1
- package/dist/cli-delegate/cmd_sync.js +2 -2
- package/dist/cli-delegate/cmd_uninstall.js +2 -2
- package/dist/cli-delegate/cmd_validate.js +2 -2
- package/dist/cli-delegate/dashboard_mode.js +16 -0
- package/dist/cli-delegate/gate_budget.js +24 -0
- package/dist/cli-delegate/gate_execute.js +25 -0
- package/dist/cli-delegate/guarded_baseline.js +18 -0
- package/dist/cli-delegate/resume_probe.js +22 -0
- package/dist/cli-delegate/roadmap_gates.js +638 -0
- package/dist/cli-delegate/roadmap_set_step.js +173 -0
- package/dist/cli-delegate/stub_queue.js +47 -0
- package/dist/cli-delegate/stubs_due.js +38 -0
- package/dist/cli-delegate/ticket_bundles.js +59 -0
- package/dist/cli-delegate/update_roadmap_progress.js +60 -0
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +13 -13
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +1 -1
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +2 -2
- package/dist/discovery/trust-report.md +1 -1
- package/dist/discovery/workspaces.json +2 -2
- package/dist/hooks/dispatch.js +1813 -946
- package/dist/install/claudeLayerCarriage.js +237 -0
- package/dist/install/claudePathsPlan.js +79 -0
- package/dist/install/hostLayerFingerprint.js +1 -1
- package/dist/install/install.mjs +21 -3
- package/dist/install/partitionEligibility.js +231 -117
- package/dist/install/ruleLayerPartition.js +10 -7
- package/dist/mcp/registry-manifest.json +2 -2
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +10870 -7641
- package/dist/scripts/_lib/lean_projection_mode.js +108 -0
- package/dist/scripts/_lib/router_match.js +243 -0
- package/dist/scripts/_lib/rule_injection.js +216 -0
- package/dist/scripts/condense.js +52 -45
- package/dist/scripts/project_thin_rules.js +139 -19
- package/dist/server/schemas/settings.js +16 -3
- package/docs/MIGRATION.md +105 -1
- package/docs/contracts/settings-classes.md +40 -8
- package/docs/guidelines/agent-infra/minimal-safe-diff-mechanics.md +73 -0
- package/docs/guidelines/agent-infra/notes-horizon-mechanics.md +90 -0
- package/llms.txt +1 -1
- package/package.json +7 -4
- package/src/agent-src/scripts/_cli_entry.ts +51 -0
- package/src/agent-src/scripts/archive_completed_roadmaps.ts +120 -27
- package/src/agent-src/scripts/roadmap_gates.ts +4 -20
- package/src/agent-src/scripts/roadmap_set_step.ts +5 -2
- package/src/agent-src/scripts/stubs_due.ts +4 -18
- package/src/agent-src/scripts/update_roadmap_progress.ts +7 -24
- package/src/config/agent-settings.template.yml +47 -1
- package/src/config/continuity-surface.json +516 -0
- package/src/config/estate-count-budget.json +1 -1
- package/src/config/evaluator-budgets.json +4 -4
- package/src/config/gate-coverage.yml +29 -8
- package/src/config/gate-violation-baselines.json +8 -8
- package/src/config/gitignore-block.txt +19 -0
- package/src/config/hook-token-budget.json +7 -6
- package/src/config/host-injection-effect.json +73 -0
- package/src/config/packed-binary-manifest.json +33 -0
- package/src/config/preamble-payload-budget.json +112 -105
- package/src/config/publish-surface.json +4 -2
- package/src/config/routing-coverage-seed.json +9 -2
- package/src/install/claudeLayerCarriage.ts +273 -0
- package/src/install/claudePathsPlan.ts +76 -0
- package/src/install/hostLayerFingerprint.ts +1 -1
- package/src/install/partitionEligibility.ts +261 -127
- package/src/install/ruleLayerPartition.ts +19 -23
- package/src/scripts/_cli/cmd_session_recycle.ts +2 -25
- package/src/scripts/_cli/handoff_sessions.ts +14 -44
- package/src/scripts/_dispatch.bash +77 -27
- package/src/scripts/_lib/auto_dispatch.ts +2 -2
- package/src/scripts/_lib/catalogue_layer_parity.ts +146 -0
- package/src/scripts/_lib/continuity_slot.ts +295 -0
- package/src/scripts/_lib/continuity_surface.ts +296 -0
- package/src/scripts/_lib/continuity_writer.ts +253 -0
- package/src/scripts/_lib/corpus_manifest.ts +26 -9
- package/src/scripts/_lib/hook_settings.ts +86 -1
- package/src/scripts/_lib/injection_effect.ts +151 -0
- package/src/scripts/_lib/layer_overlap_notice.ts +50 -6
- package/src/scripts/_lib/lean_projection_mode.ts +127 -0
- package/src/scripts/_lib/packed_binary_predicate.ts +262 -0
- package/src/scripts/_lib/pin_resolver.ts +13 -0
- package/src/scripts/_lib/recycle_envelope_paths.ts +109 -21
- package/src/scripts/_lib/regression_neighbourhood.ts +159 -22
- package/src/scripts/_lib/retired_status.ts +74 -0
- package/src/scripts/_lib/session_eol.ts +44 -0
- package/src/scripts/_lib/session_index_trust.ts +346 -0
- package/src/scripts/_lib/skill_catalogue.ts +156 -21
- package/src/scripts/_lib/standing_bound_ratchet.ts +154 -0
- package/src/scripts/_lib/subagent_capsule.ts +117 -8
- package/src/scripts/_lib/vendored_grammar_upstream.ts +280 -0
- package/src/scripts/ai_council/api_transport.ts +5 -0
- package/src/scripts/ai_council/deliberation_metrics.ts +353 -0
- package/src/scripts/ai_council/prompts.ts +9 -0
- package/src/scripts/ai_council/synthesis_disagreement.ts +206 -0
- package/src/scripts/audit_mcp_tools.ts +69 -25
- package/src/scripts/build_mcp_catalog.ts +24 -1
- package/src/scripts/capture_skill_catalogue.ts +24 -11
- package/src/scripts/check_candidate_lines.ts +499 -0
- package/src/scripts/check_continuity_surface.ts +475 -0
- package/src/scripts/check_dependency_floors.ts +13 -6
- package/src/scripts/check_estate_count.ts +40 -79
- package/src/scripts/check_host_tree_parity.ts +291 -0
- package/src/scripts/check_pack_size.ts +262 -23
- package/src/scripts/check_preamble_payload_budget.ts +136 -7
- package/src/scripts/check_roadmap_trackable.ts +19 -16
- package/src/scripts/check_rule_layer_partition.ts +54 -34
- package/src/scripts/check_rule_projection_integrity.ts +102 -2
- package/src/scripts/check_single_delivery.ts +97 -31
- package/src/scripts/check_update_banner.ts +13 -0
- package/src/scripts/ci_settle.ts +205 -5
- package/src/scripts/code_graph/build.ts +217 -15
- package/src/scripts/code_graph/cli.ts +334 -15
- package/src/scripts/code_graph/detect.ts +38 -0
- package/src/scripts/code_graph/extract.ts +11 -0
- package/src/scripts/code_graph/grammar_probe.ts +43 -0
- package/src/scripts/code_graph/loader.ts +88 -14
- package/src/scripts/code_graph/query.ts +144 -11
- package/src/scripts/code_graph/resolution_tiers.ts +238 -0
- package/src/scripts/code_graph/sqlite_store.ts +262 -6
- package/src/scripts/code_graph/types.ts +117 -3
- package/src/scripts/code_graph/validate.ts +26 -1
- package/src/scripts/code_graph/verbs.ts +590 -0
- package/src/scripts/condense.ts +54 -42
- package/src/scripts/corpus_manifest.ts +5 -5
- package/src/scripts/council_cli.ts +11 -12
- package/src/scripts/count_intent_disagreement.ts +426 -0
- package/src/scripts/handoff_context_hook.ts +118 -1
- package/src/scripts/hook_effect_doctor.ts +82 -1
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +87 -12
- package/src/scripts/hooks/block_speaking_inbox_dir.ts +182 -16
- package/src/scripts/hooks/chain_nudge_hook.ts +282 -0
- package/src/scripts/hooks/code_graph_context_hook.ts +201 -0
- package/src/scripts/hooks/concern_registry.ts +4 -2
- package/src/scripts/hooks/host_semantics.ts +1 -1
- package/src/scripts/hooks/orchestration_record_hook.ts +2 -2
- package/src/scripts/hooks/push_settle_hook.ts +3 -2
- package/src/scripts/hooks/rule_inject_hook.ts +108 -21
- package/src/scripts/hooks/session_eol_hook.ts +120 -2
- package/src/scripts/hooks/skill_route_hook.ts +11 -4
- package/src/scripts/hot_context_hook.ts +62 -7
- package/src/scripts/inbox_source_census.ts +322 -0
- package/src/scripts/install-hooks.sh +82 -0
- package/src/scripts/{lint_carrier_integrity.ts → lint_deferral_integrity.ts} +60 -214
- package/src/scripts/lint_plan_risk_register.ts +13 -17
- package/src/scripts/lint_roadmap_blockers.ts +164 -1
- package/src/scripts/mcp_server/consumer_tool_catalog.json +152 -2
- package/src/scripts/mcp_server/graph_tools.ts +294 -0
- package/src/scripts/mcp_server/path_util.ts +31 -0
- package/src/scripts/mcp_server/suggest_skill.ts +72 -0
- package/src/scripts/mcp_server/tool_catalog_source.ts +7 -1
- package/src/scripts/mcp_server/tools.ts +5 -69
- package/src/scripts/media/lib/adapter-contract.md +7 -2
- package/src/scripts/media/lib/fixtures/flux/asset-0001.png +0 -0
- package/src/scripts/media/lib/fixtures/gemini-image/asset-0001.png +0 -0
- package/src/scripts/media/lib/fixtures/ideogram/asset-0001.png +0 -0
- package/src/scripts/model_rule_injection.ts +61 -4
- package/src/scripts/project_thin_rules.ts +149 -16
- package/src/scripts/rdp_candidates_delta.ts +276 -0
- package/src/scripts/rdp_quality_eval.ts +217 -19
- package/src/scripts/release_mix_taxonomy.json +3 -2
- package/src/scripts/report_host_injection_effect.ts +189 -0
- package/src/scripts/report_layer_overlap.ts +41 -0
- package/src/scripts/report_skill_menu_census.ts +341 -0
- package/src/scripts/report_standing_payload_by_host.ts +650 -0
- package/src/scripts/schemas/agent-settings.schema.json +7 -1
- package/src/scripts/session_memory_index.ts +81 -8
- package/src/scripts/skill_tools/score_skill_relevance.ts +70 -6
- package/src/scripts/skill_tools/suggest_skill_for_task.ts +37 -3
- package/src/server/schemas/settings.ts +23 -4
- package/src/vendor/grammars/README.md +86 -0
- package/src/vendor/grammars/tree-sitter-javascript.wasm +0 -0
- package/src/vendor/grammars/tree-sitter-php.wasm +0 -0
- package/src/vendor/grammars/tree-sitter-typescript.wasm +0 -0
- package/src/scripts/_lib/carrier_status.ts +0 -118
- package/src/scripts/_lib/estate_carrier_cases.ts +0 -72
- package/src/scripts/hooks/code_graph_nudge_hook.ts +0 -191
|
@@ -12,30 +12,33 @@
|
|
|
12
12
|
* > neighbourhood names, and a fixture proves a neighbour regression is
|
|
13
13
|
* > caught.**
|
|
14
14
|
*
|
|
15
|
-
*
|
|
15
|
+
* TWO GRAPHS, BOTH DELIBERATE — the substitution is retired.
|
|
16
16
|
*
|
|
17
|
-
* The step says "the code graph".
|
|
18
|
-
*
|
|
17
|
+
* The step says "the code graph". Until 2026-09-08 this module could not read
|
|
18
|
+
* it: `agent-config code-graph detect` answered `no code-graph source detected`
|
|
19
|
+
* in a fresh checkout, so it selected over the artefact graph instead and said
|
|
20
|
+
* so. `road-to-a-graph-that-is-shipped` removed that premise — Phase 0.1 ships
|
|
21
|
+
* the parsers, Phase 1 builds the graph on install, and 3.1 added
|
|
22
|
+
* `impact --diff`, which is the reverse-reachability query this selector needs.
|
|
19
23
|
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* (`src/config/agent-settings.template.yml:1373-1374`), and
|
|
23
|
-
* `agent-config code-graph detect` in this checkout answers
|
|
24
|
-
* `no code-graph source detected`. There is no index to select against.
|
|
25
|
-
* · `src/scripts/discovery_graph.ts` — this suite's OWN artefact relation
|
|
26
|
-
* graph, five typed edges extracted from the discovery manifest's
|
|
27
|
-
* structured fields, with an `affected` BFS already implemented and
|
|
28
|
-
* answering. That is the surface this module builds on.
|
|
24
|
+
* So both surfaces are now first-class, and which one a candidate uses is a
|
|
25
|
+
* property OF THE CANDIDATE rather than of what happened to resolve:
|
|
29
26
|
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
27
|
+
* · **Code candidates** — a diff that edits `.ts` / `.php` symbols. Use
|
|
28
|
+
* {@link selectRegressionsFromCode}, which neighbours by SYMBOL relations
|
|
29
|
+
* over the native graph, filtered to accepted mechanisms
|
|
30
|
+
* (`resolved_via` not in `{name-lookup, dynamic}`) so a same-name guess
|
|
31
|
+
* never selects a regression.
|
|
32
|
+
* · **Artefact candidates** — a diff that edits rules, skills, guidelines.
|
|
33
|
+
* Use {@link selectRegressions}, which neighbours by ARTEFACT relations
|
|
34
|
+
* over `src/scripts/discovery_graph.ts` (`supersedes`, `routes_to`,
|
|
35
|
+
* `references_adr`, pack and workspace membership). For a rule rewrite that
|
|
36
|
+
* is the graph carrying the coupling a change can break; the code graph
|
|
37
|
+
* does not model it at all.
|
|
38
|
+
*
|
|
39
|
+
* Neither is a fallback for the other, and neither is silent: both paths REFUSE
|
|
40
|
+
* through {@link selectionVerdict} when a touched surface is absent from the
|
|
41
|
+
* graph they read, because an unknown neighbourhood is not an empty one.
|
|
39
42
|
*
|
|
40
43
|
* ## Why an unresolved surface refuses instead of selecting nothing
|
|
41
44
|
*
|
|
@@ -55,6 +58,9 @@
|
|
|
55
58
|
* A test asserts that identity rather than an id match, because an id match
|
|
56
59
|
* would also be satisfied by a synthesized spec carrying a copied id.
|
|
57
60
|
*/
|
|
61
|
+
import type { GraphState } from '../code_graph/detect.js';
|
|
62
|
+
import type { LoadedGraph } from '../code_graph/query.js';
|
|
63
|
+
import { impact } from '../code_graph/verbs.js';
|
|
58
64
|
import { affected, isSyntheticNode, type Graph } from '../discovery_graph.js';
|
|
59
65
|
|
|
60
66
|
/**
|
|
@@ -106,6 +112,48 @@ export interface NeighbourhoodReport {
|
|
|
106
112
|
selected: readonly Selection[];
|
|
107
113
|
/** Registry entries whose guards intersect nothing in the neighbourhood. */
|
|
108
114
|
skipped: readonly string[];
|
|
115
|
+
/**
|
|
116
|
+
* Which graph answered. Present so a verdict record can never be read as a
|
|
117
|
+
* claim about the other surface — the failure the retired substitution
|
|
118
|
+
* section describes, arriving through the report instead of through the
|
|
119
|
+
* docstring.
|
|
120
|
+
*/
|
|
121
|
+
graph: 'artefact' | 'code';
|
|
122
|
+
/**
|
|
123
|
+
* The graph's freshness at selection time: `fresh` / `behind:N` / `absent`
|
|
124
|
+
* on the code path, `null` on the artefact path (which is derived from the
|
|
125
|
+
* committed manifest and has no staleness axis).
|
|
126
|
+
*
|
|
127
|
+
* Added after an independent review found the code path hardcoding
|
|
128
|
+
* `'absent'` and dropping the value: the verbs are required to report
|
|
129
|
+
* staleness, `verbs.ts` argues the whole point is telling "dead" from "dead
|
|
130
|
+
* as of a graph 40 commits behind" — and the one in-repo CONSUMER of those
|
|
131
|
+
* verbs discarded it, so no selection could refuse on a stale graph.
|
|
132
|
+
*/
|
|
133
|
+
graph_state: GraphState | null;
|
|
134
|
+
/**
|
|
135
|
+
* Touched files in a language the code graph does not index. NOT a refusal
|
|
136
|
+
* reason: an unindexed `.md` is a file with no symbols, which is a fact
|
|
137
|
+
* about the language set rather than an unknown neighbourhood.
|
|
138
|
+
*/
|
|
139
|
+
not_indexed: readonly string[];
|
|
140
|
+
/**
|
|
141
|
+
* The edges that produced the neighbourhood, rendered, sorted.
|
|
142
|
+
*
|
|
143
|
+
* Required by step 3.4: *"the selected regressions and the producing edges
|
|
144
|
+
* enter the verdict record"*. Empty on the artefact path, whose `affected`
|
|
145
|
+
* BFS returns a relation name per hop rather than an edge — stated rather
|
|
146
|
+
* than faked, because an empty list a reader can attribute is better than a
|
|
147
|
+
* synthesised one they cannot.
|
|
148
|
+
*/
|
|
149
|
+
producing_edges: readonly string[];
|
|
150
|
+
/**
|
|
151
|
+
* The `resolved_via` histogram of the edges the walk REFUSED, on the code
|
|
152
|
+
* path. A selection that looks narrow because half the graph was a guess
|
|
153
|
+
* reads very differently from one that looks narrow because the code is
|
|
154
|
+
* decoupled, and this is the only field that distinguishes them.
|
|
155
|
+
*/
|
|
156
|
+
rejected_via: string;
|
|
109
157
|
/**
|
|
110
158
|
* Literal 0. This module selects from a registry; a non-zero value here
|
|
111
159
|
* would mean it authored a task, which is K9.
|
|
@@ -196,6 +244,80 @@ export function selectRegressions(
|
|
|
196
244
|
unresolved: unresolvedSurfaces(graph, candidate),
|
|
197
245
|
selected: selected.sort((a, b) => a.spec.id.localeCompare(b.spec.id)),
|
|
198
246
|
skipped: skipped.sort((a, b) => a.localeCompare(b)),
|
|
247
|
+
graph: 'artefact',
|
|
248
|
+
graph_state: null,
|
|
249
|
+
not_indexed: [],
|
|
250
|
+
producing_edges: [],
|
|
251
|
+
rejected_via: '(not applicable — the artefact graph has no mechanism axis)',
|
|
252
|
+
authored: 0,
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* The code-graph path (step 3.4).
|
|
258
|
+
*
|
|
259
|
+
* Neighbours a candidate by the symbols its diff touched, over the native code
|
|
260
|
+
* graph, using the same `impact --diff` reverse walk the CLI verb exposes. The
|
|
261
|
+
* neighbourhood's nodes are the seeds at depth 0 (`touched`) plus every
|
|
262
|
+
* accepted reverse-reachable node at its shallowest depth (`neighbour`), which
|
|
263
|
+
* is the identical shape {@link neighbourhood} produces for the artefact graph
|
|
264
|
+
* — so `selectRegressions`' matching logic is reused rather than forked.
|
|
265
|
+
*
|
|
266
|
+
* `touches` is read as FILE paths here, not artefact ids: a code candidate is a
|
|
267
|
+
* diff, and a diff names files. A touched file with no node in the graph lands
|
|
268
|
+
* in `unresolved` and therefore refuses through {@link selectionVerdict}, on
|
|
269
|
+
* exactly the terms the artefact path already uses.
|
|
270
|
+
*/
|
|
271
|
+
export function selectRegressionsFromCode(
|
|
272
|
+
g: LoadedGraph,
|
|
273
|
+
candidate: Candidate,
|
|
274
|
+
registry: readonly RegressionSpec[],
|
|
275
|
+
depth: number = DEFAULT_NEIGHBOURHOOD_DEPTH,
|
|
276
|
+
isTest: (relPath: string) => boolean = () => false,
|
|
277
|
+
graphState: GraphState = 'absent',
|
|
278
|
+
): NeighbourhoodReport {
|
|
279
|
+
const res = impact(g, candidate.touches, graphState, depth, isTest);
|
|
280
|
+
const best = new Map<string, NeighbourhoodNode>();
|
|
281
|
+
for (const seed of res.seeds) {
|
|
282
|
+
best.set(seed, { node: seed, reason: 'touched', depth: 0, via: '', synthetic: false });
|
|
283
|
+
}
|
|
284
|
+
for (const r of res.reached) {
|
|
285
|
+
if (best.has(r.node)) continue;
|
|
286
|
+
best.set(r.node, {
|
|
287
|
+
node: r.node,
|
|
288
|
+
reason: 'neighbour',
|
|
289
|
+
depth: r.depth,
|
|
290
|
+
via: `${r.via}/${r.resolved_via}`,
|
|
291
|
+
synthetic: false,
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
const hood = [...best.values()].sort((a, b) => a.depth - b.depth || a.node.localeCompare(b.node));
|
|
295
|
+
const reasonOf = new Map<string, NeighbourReason>(hood.map((n) => [n.node, n.reason]));
|
|
296
|
+
const selected: Selection[] = [];
|
|
297
|
+
const skipped: string[] = [];
|
|
298
|
+
for (const spec of registry) {
|
|
299
|
+
const matched = spec.guards.filter((x) => reasonOf.has(x)).sort((a, b) => a.localeCompare(b));
|
|
300
|
+
if (matched.length === 0) {
|
|
301
|
+
skipped.push(spec.id);
|
|
302
|
+
continue;
|
|
303
|
+
}
|
|
304
|
+
selected.push({
|
|
305
|
+
spec,
|
|
306
|
+
matched,
|
|
307
|
+
reason: matched.some((m) => reasonOf.get(m) === 'touched') ? 'touched' : 'neighbour',
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
return {
|
|
311
|
+
candidate_id: candidate.id,
|
|
312
|
+
neighbourhood: hood,
|
|
313
|
+
unresolved: [...res.unresolved_files].sort((a, b) => a.localeCompare(b)),
|
|
314
|
+
selected: selected.sort((a, b) => a.spec.id.localeCompare(b.spec.id)),
|
|
315
|
+
skipped: skipped.sort((a, b) => a.localeCompare(b)),
|
|
316
|
+
graph: 'code',
|
|
317
|
+
graph_state: graphState,
|
|
318
|
+
not_indexed: [...res.not_indexed_files].sort((a, b) => a.localeCompare(b)),
|
|
319
|
+
producing_edges: [...res.producing_edges].sort(),
|
|
320
|
+
rejected_via: res.rejected_via,
|
|
199
321
|
authored: 0,
|
|
200
322
|
};
|
|
201
323
|
}
|
|
@@ -209,9 +331,24 @@ export function selectRegressions(
|
|
|
209
331
|
*/
|
|
210
332
|
export function selectionVerdict(report: NeighbourhoodReport): readonly string[] | null {
|
|
211
333
|
const reasons: string[] = [];
|
|
334
|
+
// An ABSENT graph is the case the artefact path's own docstring warns
|
|
335
|
+
// about in the other direction: a lookup that cannot resolve and then
|
|
336
|
+
// selects nothing reports a clean sheet. `behind:N` is deliberately NOT a
|
|
337
|
+
// refusal — a stale graph still answers, and blocking on staleness would
|
|
338
|
+
// be the blocking-gate-on-a-stale-graph that K7 forbids. It is surfaced
|
|
339
|
+
// through `graph_state` so a caller that wants to refuse can.
|
|
340
|
+
if (report.graph === 'code' && report.graph_state === 'absent') {
|
|
341
|
+
reasons.push(
|
|
342
|
+
'the code graph is absent — a neighbourhood computed over no graph is empty for a ' +
|
|
343
|
+
'reason that has nothing to do with the candidate. Run `agent-config code-graph build`.',
|
|
344
|
+
);
|
|
345
|
+
}
|
|
212
346
|
if (report.unresolved.length > 0) {
|
|
347
|
+
// Named per graph: a code-path refusal that said "relation graph" would
|
|
348
|
+
// point a reader at the wrong surface to go fix.
|
|
349
|
+
const which = report.graph === 'code' ? 'code graph' : 'artefact relation graph';
|
|
213
350
|
reasons.push(
|
|
214
|
-
`touched surfaces absent from the
|
|
351
|
+
`touched surfaces absent from the ${which}: ${report.unresolved.join(', ')} — ` +
|
|
215
352
|
'their neighbourhood is unknown, and an unknown neighbourhood is not an empty one',
|
|
216
353
|
);
|
|
217
354
|
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Roadmap `status:` values this repository has RETIRED, and the diagnostic a
|
|
3
|
+
* reader gets when one survives in a file.
|
|
4
|
+
*
|
|
5
|
+
* `status: carrier` was deleted by ADR-262. It had two jobs welded together: a
|
|
6
|
+
* structural one (this roadmap is the live destination of an archived parent's
|
|
7
|
+
* `[~]` carries) and an authority one (an autonomous run may not act on it
|
|
8
|
+
* until a human flips it to `ready`). The second was authored by the repository
|
|
9
|
+
* about its own maintainer, was enforced by nothing, and contradicted the drain
|
|
10
|
+
* command's own FORBIDDEN NON-HALT REASONS. The first is a property of the
|
|
11
|
+
* deferral EDGES, which `lint_deferral_integrity` already verifies from both
|
|
12
|
+
* ends, so nothing was left for a node-level status to carry.
|
|
13
|
+
*
|
|
14
|
+
* Deleting a vocabulary term silently is the failure this module exists to
|
|
15
|
+
* prevent: an old file would keep a value nothing reads, and the next author
|
|
16
|
+
* would infer a meaning from its presence. So a retired value is REJECTED with
|
|
17
|
+
* a migration diagnostic rather than ignored.
|
|
18
|
+
*
|
|
19
|
+
* The read is frontmatter-scoped on purpose, and that is inherited rather than
|
|
20
|
+
* newly decided: a fenced `status: carrier` inside a roadmap documenting the
|
|
21
|
+
* syntax is not a declaration, and a body-wide match turned exactly that into a
|
|
22
|
+
* hard failure before a review caught it.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/** Retired `status:` values, mapped to the record that retired each one. */
|
|
26
|
+
export const RETIRED_STATUS_VALUES: ReadonlyMap<string, string> = new Map([
|
|
27
|
+
['carrier', 'ADR-262'],
|
|
28
|
+
]);
|
|
29
|
+
|
|
30
|
+
/** The leading `---\n…\n---` block, or null when the text carries none. */
|
|
31
|
+
export function frontmatterBlock(text: string): string | null {
|
|
32
|
+
const m = /^---\n([\s\S]*?)\n---/.exec(text);
|
|
33
|
+
return m === null ? null : (m[1] ?? '');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** The frontmatter `status:` value, lower-cased, or null when absent. */
|
|
37
|
+
export function frontmatterStatus(text: string | null | undefined): string | null {
|
|
38
|
+
if (text === null || text === undefined) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
const fm = frontmatterBlock(text);
|
|
42
|
+
if (fm === null) {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
const m = /^status:[ \t]*([A-Za-z-]+)[ \t]*$/m.exec(fm);
|
|
46
|
+
return m === null ? null : (m[1] ?? '').toLowerCase();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* The retired value this text declares, or null when it declares none.
|
|
51
|
+
*
|
|
52
|
+
* Returns the value rather than a boolean so the caller can name it in the
|
|
53
|
+
* diagnostic — "status: carrier is retired" is actionable, "invalid status" is
|
|
54
|
+
* not.
|
|
55
|
+
*/
|
|
56
|
+
export function declaresRetiredStatus(text: string | null | undefined): string | null {
|
|
57
|
+
const status = frontmatterStatus(text);
|
|
58
|
+
if (status === null) {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
return RETIRED_STATUS_VALUES.has(status) ? status : null;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** The migration diagnostic for a retired value. Names the record and the fix. */
|
|
65
|
+
export function retiredStatusDiagnostic(value: string): string {
|
|
66
|
+
const record = RETIRED_STATUS_VALUES.get(value) ?? 'a decision record';
|
|
67
|
+
return (
|
|
68
|
+
`declares the retired \`status: ${value}\`, deleted by ${record}. ` +
|
|
69
|
+
'A `status:` value no longer decides whether an autonomous run may act on ' +
|
|
70
|
+
'a roadmap. Use `status: ready` and put any genuine human-ACTION gate in a ' +
|
|
71
|
+
'`## Blockers` entry, or park the file under `agents/roadmaps/later/` with ' +
|
|
72
|
+
'an `entry_condition`. Both are read by a gate; a status is not.'
|
|
73
|
+
);
|
|
74
|
+
}
|
|
@@ -269,6 +269,50 @@ export function readEolCounters(
|
|
|
269
269
|
}
|
|
270
270
|
}
|
|
271
271
|
|
|
272
|
+
/**
|
|
273
|
+
* Committed substantive-content floor, in parsed transcript tokens (billable
|
|
274
|
+
* input of the last main-chain assistant record, per `cc_transcript.ts`) — the
|
|
275
|
+
* OR-arm for a session that produced real discussion without ever calling a
|
|
276
|
+
* tool.
|
|
277
|
+
*
|
|
278
|
+
* Derivation (`agents/evidence/analysis/handoff-substantive-threshold.md`, code-comment-allow provenance-comment -- unchanged relocation of a docblock whose whole point is that this threshold may only move on cited evidence
|
|
279
|
+
* 217 sessions of the local Claude store, 2026-08-10): 206 of the 207 sessions
|
|
280
|
+
* carrying an assistant record also carry a `tool_use` block, so this arm
|
|
281
|
+
* serves the ~0.5 % tail and the hosts whose transcripts log no tool blocks at
|
|
282
|
+
* all. 10 000 sits **25× below** the p10 of real working sessions (254 939),
|
|
283
|
+
* so it cannot hide one, and above a single trivial exchange. Changing it is a
|
|
284
|
+
* PR citing evidence, never a drive-by edit.
|
|
285
|
+
*/
|
|
286
|
+
export const SUBSTANTIVE_TOKEN_FLOOR = 10_000;
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Does this session hold anything worth resuming?
|
|
290
|
+
*
|
|
291
|
+
* `≥ 1 assistant turn AND (≥ 1 tool call OR parsed tokens ≥ the committed
|
|
292
|
+
* floor)`, read from the counts-only session-eol state.
|
|
293
|
+
*
|
|
294
|
+
* **Fail-open, deliberately** (Phase 1.2): absent, unreadable or mis-shaped
|
|
295
|
+
* state LISTS the candidate rather than filtering it, and a `tool_calls` key
|
|
296
|
+
* missing from a state file written before that counter existed reads as
|
|
297
|
+
* *unknown*, never as zero. A wrongly listed candidate is noise the user
|
|
298
|
+
* scrolls past; a wrongly hidden one is data loss they cannot even see.
|
|
299
|
+
*/
|
|
300
|
+
export function is_substantive(counters: StoredEolCounters | null): boolean {
|
|
301
|
+
if (counters === null) return true;
|
|
302
|
+
// Every "unknown" below is a NUMBER test, not an `=== undefined` test.
|
|
303
|
+
// Absent, null and NaN are all unknown, and each one reaches this code by
|
|
304
|
+
// a real path: a state file written before the counter existed is absent,
|
|
305
|
+
// `JSON.stringify` turns NaN into null on the way to disk, and a
|
|
306
|
+
// half-written file yields a parseable object with missing keys. Reading
|
|
307
|
+
// any of them as "counted zero" hides a session that did real work.
|
|
308
|
+
if (!Number.isFinite(counters.assistant_records)) return true;
|
|
309
|
+
if ((counters.assistant_records as number) < 1) return false;
|
|
310
|
+
if (!Number.isFinite(counters.tool_calls)) return true;
|
|
311
|
+
if ((counters.tool_calls as number) >= 1) return true;
|
|
312
|
+
if (!Number.isFinite(counters.final_context_tokens)) return true;
|
|
313
|
+
return (counters.final_context_tokens as number) >= SUBSTANTIVE_TOKEN_FLOOR;
|
|
314
|
+
}
|
|
315
|
+
|
|
272
316
|
export interface NewLinesRead {
|
|
273
317
|
/** The complete lines appended since `fromByte` (possibly empty). */
|
|
274
318
|
text: string;
|