@event4u/agent-config 14.21.0 → 14.22.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 +198 -0
- package/CREDITS.md +37 -0
- package/dist/agent-src/commands/analyze/inbox.md +380 -5
- package/dist/agent-src/commands/analyze/repo.md +4 -2
- 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/rules/external-code-graph-interop.md +19 -14
- 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 +14 -23
- 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 +25 -0
- package/dist/agent-src/skills/roadmap-writing/SKILL.md +17 -0
- 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-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 +494 -0
- package/dist/cli-delegate/check_update_banner.js +923 -0
- package/dist/cli-delegate/chunk-5EK5WQN6.js +28 -0
- package/dist/cli-delegate/chunk-7XGD2OEU.js +96 -0
- package/dist/cli-delegate/{chunk-643Z7FIC.js → chunk-BIXEDQPZ.js} +6 -0
- package/dist/cli-delegate/chunk-DBH4AHDK.js +155 -0
- package/dist/cli-delegate/chunk-JO25G5H7.js +20 -0
- package/dist/cli-delegate/chunk-LTYVIY76.js +7961 -0
- package/dist/cli-delegate/chunk-QAJS5YWY.js +999 -0
- package/dist/cli-delegate/{chunk-ZVBOHSVF.js → chunk-TGIPZBCW.js} +1 -1
- 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 +1 -1
- package/dist/cli-delegate/cmd_handoff.js +26 -2
- package/dist/cli-delegate/cmd_prune.js +1 -1
- package/dist/cli-delegate/cmd_session_recycle.js +2 -2
- 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/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 +8 -8
- 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 +1193 -917
- 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 +6 -0
- 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 +39219 -38995
- package/dist/scripts/condense.js +32 -25
- package/docs/MIGRATION.md +49 -1
- package/docs/contracts/settings-classes.md +1 -1
- package/docs/guidelines/agent-infra/minimal-safe-diff-mechanics.md +73 -0
- package/package.json +7 -4
- package/src/agent-src/scripts/_cli_entry.ts +51 -0
- package/src/agent-src/scripts/archive_completed_roadmaps.ts +14 -23
- 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/continuity-surface.json +509 -0
- package/src/config/estate-count-budget.json +1 -1
- 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/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/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/_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_surface.ts +296 -0
- package/src/scripts/_lib/corpus_manifest.ts +26 -9
- package/src/scripts/_lib/hook_settings.ts +1 -1
- package/src/scripts/_lib/injection_effect.ts +151 -0
- package/src/scripts/_lib/layer_overlap_notice.ts +50 -6
- package/src/scripts/_lib/packed_binary_predicate.ts +225 -0
- package/src/scripts/_lib/pin_resolver.ts +13 -0
- package/src/scripts/_lib/regression_neighbourhood.ts +1 -1
- package/src/scripts/_lib/retired_status.ts +74 -0
- package/src/scripts/_lib/skill_catalogue.ts +156 -21
- package/src/scripts/_lib/subagent_capsule.ts +117 -8
- 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/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_pack_size.ts +262 -23
- package/src/scripts/check_roadmap_trackable.ts +19 -16
- package/src/scripts/check_rule_layer_partition.ts +54 -34
- package/src/scripts/check_single_delivery.ts +97 -31
- package/src/scripts/check_update_banner.ts +13 -0
- package/src/scripts/code_graph/build.ts +138 -15
- package/src/scripts/code_graph/cli.ts +76 -8
- 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 +121 -11
- package/src/scripts/code_graph/resolution_tiers.ts +238 -0
- package/src/scripts/code_graph/sqlite_store.ts +247 -6
- package/src/scripts/code_graph/types.ts +66 -1
- package/src/scripts/code_graph/validate.ts +23 -0
- package/src/scripts/condense.ts +34 -22
- 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 +79 -0
- package/src/scripts/hook_effect_doctor.ts +82 -1
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +64 -12
- package/src/scripts/hooks/chain_nudge_hook.ts +282 -0
- package/src/scripts/hooks/code_graph_context_hook.ts +212 -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/rule_inject_hook.ts +1 -1
- package/src/scripts/hooks/skill_route_hook.ts +11 -4
- 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/mcp_server/suggest_skill.ts +72 -0
- package/src/scripts/mcp_server/tools.ts +2 -56
- 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/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/skill_tools/score_skill_relevance.ts +70 -6
- package/src/scripts/skill_tools/suggest_skill_for_task.ts +37 -3
- package/src/vendor/grammars/README.md +61 -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
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Does a completed synthesis keep the disagreement it started with?
|
|
3
|
+
*
|
|
4
|
+
* Three elements have to survive into the final text, and a synthesis that
|
|
5
|
+
* drops any of them has resolved the disagreement by not reporting it:
|
|
6
|
+
*
|
|
7
|
+
* 1. the unresolved disagreement itself — both sides, named;
|
|
8
|
+
* 2. the strongest evidence the minority side actually offered;
|
|
9
|
+
* 3. the observation that would settle it.
|
|
10
|
+
*
|
|
11
|
+
* Element 1 was already asked for by every lens template (`Clashes`,
|
|
12
|
+
* `Conflicts`, `Outliers`, or the mandated divergence prose). Element 2 was
|
|
13
|
+
* asked for by one. Element 3 was asked for by none, which is the gap
|
|
14
|
+
* {@link RESOLVING_EVIDENCE_SECTION} closes.
|
|
15
|
+
*
|
|
16
|
+
* WHY A CHECKER AND NOT ONLY A TEMPLATE CLAUSE. A template is an instruction to
|
|
17
|
+
* the host agent, and an instruction nobody can check is a hope. Both council
|
|
18
|
+
* seats that reviewed this refused a prose-only build in as many words. So the
|
|
19
|
+
* template carries the ask and this module makes the answer decidable: given a
|
|
20
|
+
* completed synthesis, {@link auditSynthesisElements} reports which of the three
|
|
21
|
+
* elements are present, by structure, without deciding whether their content is
|
|
22
|
+
* any good.
|
|
23
|
+
*
|
|
24
|
+
* WHAT IT DECIDES, AND WHAT IT DOES NOT. Presence and shape. A synthesis that
|
|
25
|
+
* names a clash, cites a minority exhibit and proposes a resolving measurement
|
|
26
|
+
* PASSES even when the measurement is a bad one — grading that needs the
|
|
27
|
+
* benchmark, and the benchmark has not run. This is the same honest scope the
|
|
28
|
+
* sibling minority-retention audit states for itself, and for the same reason:
|
|
29
|
+
* an audit that claimed to grade quality would be inventing the number.
|
|
30
|
+
*
|
|
31
|
+
* REPORT, NEVER THROW. Not every council pass produces dissent, and a synthesis
|
|
32
|
+
* of a unanimous pass has no disagreement to retain. So the audit reports
|
|
33
|
+
* `dissentPresent: false` and grades nothing, rather than failing a synthesis
|
|
34
|
+
* for the absence of a thing that did not happen. A caller with independent
|
|
35
|
+
* knowledge that the pass dissented passes {@link AuditOptions.dissentPresent}
|
|
36
|
+
* and gets the full grading regardless of what the text looks like.
|
|
37
|
+
*
|
|
38
|
+
* Pure, offline, no model call.
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
/** The three elements a dissenting synthesis has to carry. */
|
|
42
|
+
export type SynthesisElement =
|
|
43
|
+
| 'unresolved-disagreement'
|
|
44
|
+
| 'minority-evidence'
|
|
45
|
+
| 'resolving-evidence';
|
|
46
|
+
|
|
47
|
+
export const SYNTHESIS_ELEMENTS: readonly SynthesisElement[] = Object.freeze([
|
|
48
|
+
'unresolved-disagreement',
|
|
49
|
+
'minority-evidence',
|
|
50
|
+
'resolving-evidence',
|
|
51
|
+
]);
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* The section every lens template now closes its disagreement reporting with.
|
|
55
|
+
*
|
|
56
|
+
* One section rather than two because elements 2 and 3 are both per-clash
|
|
57
|
+
* follow-ups: splitting them would let a synthesis answer one clash's evidence
|
|
58
|
+
* and another clash's resolution and still look complete.
|
|
59
|
+
*/
|
|
60
|
+
export const RESOLVING_EVIDENCE_SECTION = `### Resolving evidence
|
|
61
|
+
One line per unresolved disagreement above, in this shape:
|
|
62
|
+
\`<clash> — strongest minority evidence: <what the losing side actually
|
|
63
|
+
showed> · resolved by: <the observation that would settle it>\`.
|
|
64
|
+
Name a measurement, an artefact or a run — never a further opinion. Write
|
|
65
|
+
\`no resolving evidence identified — <why>\` when nothing observable would
|
|
66
|
+
settle it: an unanswerable disagreement is a finding, and silence is not.`;
|
|
67
|
+
|
|
68
|
+
/** Headings under which a lens reports an unresolved disagreement. */
|
|
69
|
+
const DISAGREEMENT_HEADINGS = ['Clashes', 'Conflicts', 'Outliers', 'Divergence'];
|
|
70
|
+
|
|
71
|
+
/** The heading element 3 lives under. */
|
|
72
|
+
export const RESOLVING_EVIDENCE_HEADING = 'Resolving evidence';
|
|
73
|
+
|
|
74
|
+
/** In-body markers the resolving-evidence section is asked to emit. */
|
|
75
|
+
const MINORITY_EVIDENCE_MARKER = /strongest minority evidence\s*:/i;
|
|
76
|
+
const RESOLVED_BY_MARKER = /resolved by\s*:/i;
|
|
77
|
+
const NO_RESOLVING_EVIDENCE_MARKER = /no resolving evidence identified\s*[—:-]/i;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Text markers that say a pass dissented, used only when the caller does not
|
|
81
|
+
* tell us. Deliberately narrow: a heading with a non-empty body, or an explicit
|
|
82
|
+
* split verdict. A loose match here would grade unanimous syntheses.
|
|
83
|
+
*/
|
|
84
|
+
const SPLIT_VERDICT_MARKER = /^\s*\*{0,2}verdict\*{0,2}\s*:\s*split\b/im;
|
|
85
|
+
|
|
86
|
+
export interface ElementFinding {
|
|
87
|
+
readonly element: SynthesisElement;
|
|
88
|
+
readonly present: boolean;
|
|
89
|
+
/** The heading or marker that satisfied it, or `null`. */
|
|
90
|
+
readonly satisfiedBy: string | null;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export interface SynthesisElementAudit {
|
|
94
|
+
/** Whether the pass had a disagreement to retain at all. */
|
|
95
|
+
readonly dissentPresent: boolean;
|
|
96
|
+
/** How `dissentPresent` was decided — `caller` or `text`. */
|
|
97
|
+
readonly dissentSource: 'caller' | 'text';
|
|
98
|
+
readonly elements: readonly ElementFinding[];
|
|
99
|
+
readonly missing: readonly SynthesisElement[];
|
|
100
|
+
/** True when a dissenting pass rendered all three. Always true with no dissent. */
|
|
101
|
+
readonly complete: boolean;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export interface AuditOptions {
|
|
105
|
+
/**
|
|
106
|
+
* Override the text-derived dissent decision. Pass `true` when the run's own
|
|
107
|
+
* tally recorded a split; pass `false` to grade nothing.
|
|
108
|
+
*/
|
|
109
|
+
readonly dissentPresent?: boolean;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function _headingBody(text: string, heading: string): string | null {
|
|
113
|
+
const lines = text.split('\n');
|
|
114
|
+
const headingRe = new RegExp(`^#{2,4}\\s+${heading}\\s*$`, 'i');
|
|
115
|
+
const idx = lines.findIndex((l) => headingRe.test(l));
|
|
116
|
+
if (idx === -1) return null;
|
|
117
|
+
let body = '';
|
|
118
|
+
for (let i = idx + 1; i < lines.length; i++) {
|
|
119
|
+
if (/^#{2,4}\s/.test(lines[i] as string)) break;
|
|
120
|
+
body += (lines[i] as string) + '\n';
|
|
121
|
+
}
|
|
122
|
+
return body;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/** A heading with a non-empty, non-placeholder body. */
|
|
126
|
+
function _nonEmptySection(text: string, heading: string): boolean {
|
|
127
|
+
const body = _headingBody(text, heading);
|
|
128
|
+
if (body === null) return false;
|
|
129
|
+
const stripped = body.replace(/^\s*[*_]*(none|n\/a|nothing)[.*_\s]*$/gim, '').trim();
|
|
130
|
+
return stripped.length > 0;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/** Audit a COMPLETED synthesis — the host- or chairman-authored text. */
|
|
134
|
+
export function auditSynthesisElements(
|
|
135
|
+
text: string,
|
|
136
|
+
opts: AuditOptions = {},
|
|
137
|
+
): SynthesisElementAudit {
|
|
138
|
+
const disagreementHeading =
|
|
139
|
+
DISAGREEMENT_HEADINGS.find((h) => _nonEmptySection(text, h)) ?? null;
|
|
140
|
+
|
|
141
|
+
const dissentSource: 'caller' | 'text' = opts.dissentPresent === undefined ? 'text' : 'caller';
|
|
142
|
+
const dissentPresent =
|
|
143
|
+
opts.dissentPresent ?? (disagreementHeading !== null || SPLIT_VERDICT_MARKER.test(text));
|
|
144
|
+
|
|
145
|
+
const resolvingBody = _headingBody(text, RESOLVING_EVIDENCE_HEADING) ?? '';
|
|
146
|
+
const declaredNone = NO_RESOLVING_EVIDENCE_MARKER.test(resolvingBody);
|
|
147
|
+
|
|
148
|
+
const elements: ElementFinding[] = [
|
|
149
|
+
{
|
|
150
|
+
element: 'unresolved-disagreement',
|
|
151
|
+
present: disagreementHeading !== null,
|
|
152
|
+
satisfiedBy: disagreementHeading === null ? null : `### ${disagreementHeading}`,
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
element: 'minority-evidence',
|
|
156
|
+
present: MINORITY_EVIDENCE_MARKER.test(resolvingBody) || _nonEmptySection(text, 'Outliers'),
|
|
157
|
+
satisfiedBy: MINORITY_EVIDENCE_MARKER.test(resolvingBody)
|
|
158
|
+
? 'strongest minority evidence:'
|
|
159
|
+
: _nonEmptySection(text, 'Outliers')
|
|
160
|
+
? '### Outliers'
|
|
161
|
+
: null,
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
element: 'resolving-evidence',
|
|
165
|
+
present: RESOLVED_BY_MARKER.test(resolvingBody) || declaredNone,
|
|
166
|
+
satisfiedBy: RESOLVED_BY_MARKER.test(resolvingBody)
|
|
167
|
+
? 'resolved by:'
|
|
168
|
+
: declaredNone
|
|
169
|
+
? 'no resolving evidence identified'
|
|
170
|
+
: null,
|
|
171
|
+
},
|
|
172
|
+
];
|
|
173
|
+
|
|
174
|
+
const missing = dissentPresent
|
|
175
|
+
? elements.filter((e) => !e.present).map((e) => e.element)
|
|
176
|
+
: [];
|
|
177
|
+
|
|
178
|
+
return {
|
|
179
|
+
dissentPresent,
|
|
180
|
+
dissentSource,
|
|
181
|
+
elements,
|
|
182
|
+
missing,
|
|
183
|
+
complete: missing.length === 0,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/** Human-readable audit text. */
|
|
188
|
+
export function renderSynthesisElementAudit(a: SynthesisElementAudit): string {
|
|
189
|
+
if (!a.dissentPresent) {
|
|
190
|
+
return (
|
|
191
|
+
'synthesis element audit: SKIPPED — no unresolved disagreement in this pass ' +
|
|
192
|
+
`(decided from ${a.dissentSource}); there is nothing to retain\n`
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
const rows = a.elements
|
|
196
|
+
.map(
|
|
197
|
+
(e) =>
|
|
198
|
+
` - ${e.element}: ${e.present ? 'present' : 'MISSING'}` +
|
|
199
|
+
(e.satisfiedBy === null ? '' : ` [${e.satisfiedBy}]`),
|
|
200
|
+
)
|
|
201
|
+
.join('\n');
|
|
202
|
+
const verdict = a.complete
|
|
203
|
+
? 'synthesis retains all three elements of the unresolved disagreement'
|
|
204
|
+
: `synthesis DROPS ${a.missing.length} of 3 elements: ${a.missing.join(', ')}`;
|
|
205
|
+
return `${verdict}\n${rows}\n`;
|
|
206
|
+
}
|
|
@@ -71,7 +71,7 @@ import * as path from 'node:path';
|
|
|
71
71
|
import { fileURLToPath } from 'node:url';
|
|
72
72
|
|
|
73
73
|
import {
|
|
74
|
-
|
|
74
|
+
PROJECTION_CATALOGUE_ROOT,
|
|
75
75
|
OBSERVATION_LOG,
|
|
76
76
|
analyzeSelector,
|
|
77
77
|
buildHostEventRecord,
|
|
@@ -85,8 +85,9 @@ import {
|
|
|
85
85
|
measureCatalogueVolume,
|
|
86
86
|
parseHostBudgetEvent,
|
|
87
87
|
readObservationLog,
|
|
88
|
+
readCatalogueAcross,
|
|
88
89
|
readProjectedCatalogue,
|
|
89
|
-
|
|
90
|
+
resolveSkillCatalogueRoots,
|
|
90
91
|
type HostProjectionRow,
|
|
91
92
|
type ProjectionMode,
|
|
92
93
|
type ProjectionModeCounts,
|
|
@@ -118,13 +119,18 @@ function resolveCatalogueRoot(explicit: string | null): string {
|
|
|
118
119
|
}
|
|
119
120
|
return explicit;
|
|
120
121
|
}
|
|
121
|
-
|
|
122
|
+
// The PROJECTION first, then the authored tree — deliberately NOT the generic
|
|
123
|
+
// ranker order, and deliberately not `DEFAULT_CATALOGUE_ROOTS`, which became a
|
|
124
|
+
// label list on 2026-09-07 (its `~/` entry joins to `<repo>/~/.claude/skills`,
|
|
125
|
+
// a path that can never exist). This module compares what a host DELIVERED
|
|
126
|
+
// against what was PROJECTED, so the projection is the subject; ranking it
|
|
127
|
+
// against `src/skills` would answer a different question with the same words.
|
|
128
|
+
const CANDIDATES = [PROJECTION_CATALOGUE_ROOT, 'src/skills'] as const;
|
|
129
|
+
for (const candidate of CANDIDATES) {
|
|
122
130
|
const abs = path.join(REPO, candidate);
|
|
123
131
|
if (fs.existsSync(abs)) return abs;
|
|
124
132
|
}
|
|
125
|
-
throw new Error(
|
|
126
|
-
`no catalogue root found — tried ${DEFAULT_CATALOGUE_ROOTS.join(', ')} under ${REPO}`,
|
|
127
|
-
);
|
|
133
|
+
throw new Error(`no catalogue root found — tried ${CANDIDATES.join(', ')} under ${REPO}`);
|
|
128
134
|
}
|
|
129
135
|
|
|
130
136
|
function argValue(flag: string): string | null {
|
|
@@ -326,17 +332,24 @@ function projectionModeFlagFor(host: string, counts: ProjectionModeCounts): { fl
|
|
|
326
332
|
*/
|
|
327
333
|
function runPointableBareMode(): number {
|
|
328
334
|
const explicitRoot = argValue('--catalogue-root');
|
|
329
|
-
|
|
330
|
-
|
|
335
|
+
// The RANKER'S roots, which is what this join claims to read — corrected twice
|
|
336
|
+
// in one day. It first used `resolveSkillsRoot`; then, on the reasoning that
|
|
337
|
+
// "the projection is the subject", `.claude/skills` alone. Both were wrong
|
|
338
|
+
// after the ADR-236 amendment EMPTIED that directory of skills: the join read
|
|
339
|
+
// 49 command wrappers as the catalogue and published pointableBare 0 against
|
|
340
|
+
// unpointableBare 16, with the empty-guard silent because 49 is not 0. An
|
|
341
|
+
// explicit --catalogue-root still means exactly that one tree.
|
|
342
|
+
const rankerRoots = explicitRoot ? [resolveCatalogueRoot(explicitRoot)] : resolveSkillCatalogueRoots(REPO);
|
|
343
|
+
if (rankerRoots.length === 0) {
|
|
331
344
|
process.stderr.write(
|
|
332
|
-
|
|
333
|
-
`${DEFAULT_CATALOGUE_ROOTS.join(', ')} under ${REPO}.\n` +
|
|
345
|
+
`❌ no catalogue root resolved for the ranker under ${REPO}.\n` +
|
|
334
346
|
' An empty catalogue is never a clean join: it would report 0 pointable\n' +
|
|
335
347
|
' entries because nothing was read, not because nothing diverged.\n',
|
|
336
348
|
);
|
|
337
349
|
return 1;
|
|
338
350
|
}
|
|
339
|
-
const
|
|
351
|
+
const rankerRoot = rankerRoots[0] as string;
|
|
352
|
+
const catalogueNames = readCatalogueAcross(rankerRoots).map((entry) => entry.name);
|
|
340
353
|
// The guard the error text above already promised, and did not have. A
|
|
341
354
|
// present-but-empty or half-generated projection resolves fine — the
|
|
342
355
|
// resolver returns the first EXISTING directory, not the first non-empty
|