@event4u/agent-config 14.5.0 → 14.7.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 +384 -3
- package/README.md +1 -1
- package/dist/agent-src/commands/analyze/decision.md +7 -0
- package/dist/agent-src/commands/analyze/inbox.md +264 -10
- package/dist/agent-src/commands/analyze.md +1 -1
- package/dist/agent-src/commands/optimize/project.md +10 -0
- package/dist/agent-src/commands/roadmap/process-full.md +132 -4
- package/dist/agent-src/contexts/execution/roadmap-execution-contract.md +31 -0
- package/dist/agent-src/contexts/execution/roadmap-process-loop.md +161 -1
- package/dist/agent-src/rules/context-hygiene.md +2 -0
- package/dist/agent-src/rules/decision-revisit-gate.md +111 -7
- package/dist/agent-src/rules/fix-what-you-see.md +108 -0
- package/dist/agent-src/rules/no-roadmap-references.md +0 -5
- package/dist/agent-src/rules/recurring-criticism.md +110 -0
- package/dist/agent-src/rules/roadmap-progress-sync.md +1 -1
- package/dist/agent-src/rules/rule-type-governance.md +0 -2
- package/dist/agent-src/rules/self-repair-loop.md +17 -0
- package/dist/agent-src/rules/skill-quality.md +0 -2
- package/dist/agent-src/rules/source-confidentiality.md +37 -7
- package/dist/agent-src/scripts/archival_sweep.ts +117 -0
- package/dist/agent-src/scripts/archive_completed_roadmaps.ts +19 -3
- package/dist/agent-src/scripts/gate_budget.ts +282 -0
- package/dist/agent-src/scripts/gate_execute.ts +72 -31
- package/dist/agent-src/scripts/roadmap_gates.ts +74 -3
- package/dist/agent-src/scripts/update_roadmap_progress.ts +251 -7
- package/dist/agent-src/skills/adr-create/SKILL.md +25 -3
- package/dist/agent-src/skills/ai-council/SKILL.md +48 -807
- package/dist/agent-src/skills/ai-council/references/advanced-modes.md +320 -0
- package/dist/agent-src/skills/ai-council/references/cost-and-redaction.md +99 -0
- package/dist/agent-src/skills/ai-council/references/execution-modes.md +162 -0
- package/dist/agent-src/skills/ai-council/references/output-and-synthesis.md +125 -0
- package/dist/agent-src/skills/ai-council/references/procedure.md +143 -0
- package/dist/agent-src/skills/decision-review/SKILL.md +18 -0
- package/dist/agent-src/skills/quality-tools/SKILL.md +34 -326
- package/dist/agent-src/skills/quality-tools/references/js-ts-tools.md +113 -0
- package/dist/agent-src/skills/quality-tools/references/php-tools.md +222 -0
- package/dist/agent-src/skills/roadmap-management/SKILL.md +15 -409
- package/dist/agent-src/skills/roadmap-management/references/archival.md +226 -0
- package/dist/agent-src/skills/roadmap-management/references/authoring.md +107 -0
- package/dist/agent-src/skills/roadmap-management/references/dashboard.md +47 -0
- package/dist/agent-src/skills/roadmap-management/references/lifecycle.md +58 -0
- package/dist/agent-src/skills/skill-writing/SKILL.md +34 -570
- package/dist/agent-src/skills/skill-writing/references/procedure.md +275 -0
- package/dist/agent-src/skills/skill-writing/references/read-only-scripts.md +18 -0
- package/dist/agent-src/skills/skill-writing/references/section-patterns.md +298 -0
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/roadmaps.md +45 -2
- package/dist/agent-src/templates/scripts/telemetry/flush_sender.mjs +163 -0
- package/dist/agent-src/templates/scripts/telemetry/remote.ts +160 -7
- package/dist/agent-src/templates/scripts/telemetry/transport.ts +169 -0
- package/dist/cli/registry.js +1 -1
- package/dist/cli/registry.js.map +1 -1
- package/dist/cli-delegate/chunk-2GNWGMAL.js +172 -0
- package/dist/cli-delegate/{chunk-RLN73PR5.js → chunk-4VR4ORQ6.js} +10 -7
- package/dist/cli-delegate/chunk-6EOCNQAM.js +402 -0
- package/dist/cli-delegate/{chunk-XURJ4AQC.js → chunk-74E3TKWV.js} +381 -280
- package/dist/cli-delegate/{chunk-3UCJWMMP.js → chunk-7F3VYSM2.js} +4 -4
- package/dist/cli-delegate/{chunk-BKO2AZ7Z.js → chunk-B2ERU2VA.js} +1 -1
- package/dist/cli-delegate/{chunk-NXFWFAYV.js → chunk-G23AT6GD.js} +1 -0
- package/dist/cli-delegate/{chunk-63WSP6YZ.js → chunk-GJ5BVHXM.js} +72 -165
- package/dist/cli-delegate/{chunk-ZPSXJTLI.js → chunk-JZ4NR2TW.js} +353 -1
- package/dist/cli-delegate/chunk-MWRD5YOH.js +100 -0
- package/dist/cli-delegate/{chunk-GRRPEPRN.js → chunk-T7L2QK3K.js} +24 -5
- package/dist/cli-delegate/{chunk-EVTY7ISR.js → chunk-YM4GZDJG.js} +9 -1
- package/dist/cli-delegate/cmd_conformance.js +459 -709
- package/dist/cli-delegate/cmd_doctor.js +6 -6
- package/dist/cli-delegate/cmd_explain.js +1 -1
- package/dist/cli-delegate/cmd_export.js +7 -6
- package/dist/cli-delegate/cmd_handoff.js +6 -6
- package/dist/cli-delegate/cmd_packs_active.js +1 -1
- package/dist/cli-delegate/cmd_preflight.js +2 -2
- package/dist/cli-delegate/cmd_prune.js +7 -6
- package/dist/cli-delegate/cmd_session_recycle.js +840 -30
- package/dist/cli-delegate/cmd_settings_migrate.js +7 -6
- package/dist/cli-delegate/cmd_settings_set.js +1 -1
- package/dist/cli-delegate/cmd_sync.js +7 -6
- package/dist/cli-delegate/cmd_uninstall.js +9 -7
- package/dist/cli-delegate/cmd_update.js +1 -1
- package/dist/cli-delegate/cmd_upgrade.js +1 -1
- package/dist/cli-delegate/cmd_validate.js +7 -6
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +72 -29
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +4 -4
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +10 -8
- package/dist/discovery/trust-report.md +3 -3
- package/dist/discovery/workspaces.json +8 -6
- package/dist/hooks/dispatch.js +3127 -2022
- package/dist/install/claudePathsPlan.js +187 -0
- package/dist/install/claudePathsPlan.js.map +1 -0
- package/dist/install/hostLayerFingerprint.js +136 -0
- package/dist/install/hostLayerFingerprint.js.map +1 -0
- package/dist/install/install.mjs +553 -425
- package/dist/install/partitionEligibility.js +276 -0
- package/dist/install/partitionEligibility.js.map +1 -0
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +1744 -1191
- package/dist/router.json +1 -1
- package/dist/scripts/_lib/agent_src.js +41 -0
- package/dist/scripts/_lib/agent_src.js.map +1 -1
- package/dist/scripts/_lib/install_layout.js +83 -0
- package/dist/scripts/_lib/install_layout.js.map +1 -0
- package/dist/scripts/_lib/installed_lock.js +444 -0
- package/dist/scripts/_lib/installed_lock.js.map +1 -0
- package/dist/scripts/condense.js +13 -164
- package/dist/scripts/condense.js.map +1 -1
- package/dist/server/schemas/settings.js +4 -0
- package/dist/server/schemas/settings.js.map +1 -1
- package/docs/contracts/settings-classes.md +12 -6
- package/docs/guidelines/agent-infra/agent-interaction-and-decision-quality.md +8 -3
- package/docs/guidelines/agent-infra/context-hygiene-mechanics.md +26 -0
- package/docs/guidelines/agent-infra/engineering-memory-data-format.md +49 -0
- package/docs/guidelines/agent-infra/memory-access.md +17 -0
- package/docs/guidelines/agent-infra/recurring-criticism-mechanics.md +96 -0
- package/package.json +1 -1
- package/src/agent-src/scripts/archival_sweep.ts +117 -0
- package/src/agent-src/scripts/archive_completed_roadmaps.ts +19 -3
- package/src/agent-src/scripts/gate_budget.ts +282 -0
- package/src/agent-src/scripts/gate_execute.ts +72 -31
- package/src/agent-src/scripts/roadmap_gates.ts +74 -3
- package/src/agent-src/scripts/update_roadmap_progress.ts +251 -7
- package/src/agent-src/templates/scripts/telemetry/flush_sender.mjs +163 -0
- package/src/agent-src/templates/scripts/telemetry/remote.ts +160 -7
- package/src/agent-src/templates/scripts/telemetry/transport.ts +169 -0
- package/src/config/agent-settings.template.yml +27 -2
- package/src/config/ci-local-parity.yml +18 -0
- package/src/config/estate-count-budget.json +367 -3
- package/src/config/gate-violation-baselines.json +41 -41
- package/src/config/pack-size-budget.json +3 -2
- package/src/config/rule-activation-census.json +14 -6
- package/src/config/rule-stub-ceilings.json +19 -6
- package/src/install/claudePathsPlan.ts +196 -0
- package/src/install/hostLayerFingerprint.ts +145 -0
- package/src/install/partitionEligibility.ts +325 -0
- package/src/scripts/_cli/cmd_session_recycle.ts +9 -1
- package/src/scripts/_dispatch.bash +6 -1
- package/src/scripts/_lib/ac_heading.ts +30 -0
- package/src/scripts/_lib/agent_src.ts +42 -0
- package/src/scripts/_lib/bench_ab_pinned_repo.ts +162 -0
- package/src/scripts/_lib/bench_ab_workspace.ts +10 -1
- package/src/scripts/_lib/envelope_grounding.ts +38 -8
- package/src/scripts/_lib/installed_lock.ts +50 -5
- package/src/scripts/_lib/layer_overlap_notice.ts +85 -0
- package/src/scripts/_lib/md_section.ts +129 -0
- package/src/scripts/_lib/scope_guard.sh +86 -4
- package/src/scripts/_lib/self_repair.ts +19 -0
- package/src/scripts/_lib/self_repair_class_b.ts +171 -0
- package/src/scripts/_lib/subagent_capsule.ts +81 -1
- package/src/scripts/adr/regenerate_index.ts +13 -2
- package/src/scripts/adr_cite_check.ts +424 -0
- package/src/scripts/ai_council/cli_help.ts +55 -0
- package/src/scripts/before_complete_hook.ts +153 -28
- package/src/scripts/bench_ab_v2_complexity.ts +27 -7
- package/src/scripts/check_adr_frontmatter.ts +187 -1
- package/src/scripts/check_references.ts +60 -0
- package/src/scripts/check_release_published.ts +32 -11
- package/src/scripts/check_single_delivery.ts +517 -0
- package/src/scripts/ci_settle.ts +170 -0
- package/src/scripts/condense.ts +20 -170
- package/src/scripts/council_cli.ts +3 -3
- package/src/scripts/dispatch_r2_reviewer.ts +6 -14
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +77 -14
- package/src/scripts/hooks/block_no_verify.ts +61 -10
- package/src/scripts/hooks/block_unauthorized_git.ts +1 -1
- package/src/scripts/hooks/concern_registry.ts +4 -0
- package/src/scripts/hooks/rtk_wrap_hook.ts +8 -3
- package/src/scripts/hooks/run_continuation_hook.ts +887 -68
- package/src/scripts/hooks/ship_diff_volume_hook.ts +81 -15
- package/src/scripts/hooks/source_first_gate_hook.ts +464 -0
- package/src/scripts/hooks/state_io.ts +782 -20
- package/src/scripts/hooks/subagent_ledger_hook.ts +44 -15
- package/src/scripts/hooks/telemetry_flush_hook.ts +139 -0
- package/src/scripts/hooks/telemetry_self_repair.ts +128 -0
- package/src/scripts/hooks/telemetry_usage_hook.ts +22 -4
- package/src/scripts/hooks/turn_end_gate_hook.ts +81 -15
- package/src/scripts/install.sh +12 -2
- package/src/scripts/install.ts +16 -11
- package/src/scripts/language_mirror_hook.ts +561 -25
- package/src/scripts/lint_framework_leakage_allowlist.json +2 -2
- package/src/scripts/lint_plan_risk_register.ts +4 -3
- package/src/scripts/lint_skill_router_head.ts +4 -4
- package/src/scripts/mcp_server/tools.ts +2 -2
- package/src/scripts/memory_consolidation.ts +189 -0
- package/src/scripts/memory_eviction.ts +384 -0
- package/src/scripts/new_roadmap.ts +136 -0
- package/src/scripts/pack_mcp_content.ts +20 -5
- package/src/scripts/release.ts +37 -38
- package/src/scripts/report_layer_overlap.ts +78 -0
- package/src/scripts/report_memory_pointers.ts +622 -0
- package/src/scripts/self_repair_hook.ts +37 -5
- package/src/scripts/session_register_hook.ts +115 -15
- package/src/scripts/skill_usage_collect.ts +11 -1
- package/src/scripts/skill_usage_report.ts +278 -8
- package/src/scripts/sync_pr_branch.ts +7 -0
- package/src/server/schemas/settings.ts +8 -0
- package/dist/cli-delegate/chunk-EJITJBJX.js +0 -172
- package/dist/cli-delegate/chunk-PZWRPRWP.js +0 -38
- /package/dist/cli-delegate/{chunk-RYNADUFG.js → chunk-LWTYTX6F.js} +0 -0
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Claude Code `paths:` emission plan — which globs a rule projects, and which
|
|
3
|
+
* it deliberately does not.
|
|
4
|
+
*
|
|
5
|
+
* Extracted from `condense.ts` on 2026-08-20 (road-to-single-delivery Phase 5).
|
|
6
|
+
* Two reasons, and the second is the one that made it worth doing now.
|
|
7
|
+
*
|
|
8
|
+
* It belongs here on its own merits: this is host-activation-key logic, the same
|
|
9
|
+
* subject as `emit_host_rules_cli.ts` beside it, and `condense.ts` is the
|
|
10
|
+
* orchestrator that calls it rather than the place it lives.
|
|
11
|
+
*
|
|
12
|
+
* And it pays for the phase that moved it. Phase 5.1 removed the path triggers
|
|
13
|
+
* from four package-only rules so they load unconditionally — a change ABOUT
|
|
14
|
+
* this plan — and wiring the delivery partition into `condense.ts` and
|
|
15
|
+
* `install.ts` added lines to two files already past the 1,500-line source
|
|
16
|
+
* ceiling, where `check_source_size_budget` counts every added line as a
|
|
17
|
+
* violation. That gate's own convention is that the total moves down through
|
|
18
|
+
* extraction and never up through a baseline raise, so the extraction is the fix
|
|
19
|
+
* rather than a favour: the plan lands in a module under the ceiling, and the
|
|
20
|
+
* ratchet sees a net improvement instead of a regression.
|
|
21
|
+
*
|
|
22
|
+
* Side-effect-free, no CLI entry, no `process.exit`.
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* Derive host-native activation globs from a rule's `triggers:` frontmatter
|
|
26
|
+
* (road-to-request-scoped-rule-load Phase 2). `file_pattern` triggers map
|
|
27
|
+
* verbatim; `path_prefix` triggers map to `<prefix>**`. Keyword / phrase /
|
|
28
|
+
* command triggers produce no glob — those rules stay
|
|
29
|
+
* description-activated (Cursor Agent-Requested / Windsurf model_decision).
|
|
30
|
+
*/
|
|
31
|
+
export function derive_trigger_globs(meta) {
|
|
32
|
+
const triggers = meta['triggers'];
|
|
33
|
+
if (!Array.isArray(triggers)) {
|
|
34
|
+
return [];
|
|
35
|
+
}
|
|
36
|
+
const globs = [];
|
|
37
|
+
for (const t of triggers) {
|
|
38
|
+
if (t === null || typeof t !== 'object' || Array.isArray(t))
|
|
39
|
+
continue;
|
|
40
|
+
const obj = t;
|
|
41
|
+
if (typeof obj['file_pattern'] === 'string' && obj['file_pattern']) {
|
|
42
|
+
globs.push(obj['file_pattern']);
|
|
43
|
+
}
|
|
44
|
+
else if (typeof obj['path_prefix'] === 'string' && obj['path_prefix']) {
|
|
45
|
+
const prefix = obj['path_prefix'];
|
|
46
|
+
globs.push(prefix.endsWith('/') ? `${prefix}**` : `${prefix}**`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// De-dup, keep declaration order (deterministic output).
|
|
50
|
+
return [...new Set(globs)];
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* A brace group the host expands, versus an agent-config placeholder that only
|
|
54
|
+
* LOOKS like one.
|
|
55
|
+
*
|
|
56
|
+
* `path_prefix: "{module_root}/"` in `roadmap-ci-steps-policy` is resolved by
|
|
57
|
+
* this suite from `modules.root_paths`. Emitted verbatim into a host `paths:`
|
|
58
|
+
* list it is a brace group with no comma, which the host expands to the literal
|
|
59
|
+
* string `{module_root}` — a pattern that matches no file. The rule would then
|
|
60
|
+
* reach the model **never** instead of on-demand, and nothing would say so: the
|
|
61
|
+
* probed contract records this exact degradation as silent
|
|
62
|
+
* (`claude-code-rules-dir-contract.md` § constraints).
|
|
63
|
+
*
|
|
64
|
+
* Dropping the pattern is fail-safe in the one direction that matters. A rule
|
|
65
|
+
* left with no pattern at all carries no `paths:` key and loads
|
|
66
|
+
* unconditionally — the status quo, not a regression. A rule carrying a
|
|
67
|
+
* no-op pattern is invisible.
|
|
68
|
+
*
|
|
69
|
+
* The discriminator is the comma, not a placeholder allowlist: `{ts,tsx}` is a
|
|
70
|
+
* real alternation, `{module_root}` cannot be one.
|
|
71
|
+
*/
|
|
72
|
+
export function _is_unresolved_placeholder(pattern) {
|
|
73
|
+
for (const m of pattern.matchAll(/\{([^}]*)\}/g)) {
|
|
74
|
+
if (!m[1].includes(',')) {
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* `[` opens a bracket expression for the host. An unparseable one makes that
|
|
82
|
+
* pattern match nothing while the rule's other patterns keep working — so a
|
|
83
|
+
* literal `[` in a trigger is escaped rather than trusted.
|
|
84
|
+
*/
|
|
85
|
+
export function _escape_claude_bracket(pattern) {
|
|
86
|
+
return pattern.replace(/\[/g, '\\[');
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Expanded-pattern cost of one glob: the product of its brace alternations.
|
|
90
|
+
* The host budgets a rule's whole `paths:` list at 1,000 expanded patterns and
|
|
91
|
+
* 4 MiB, and a list over budget is used UNEXPANDED — braces then match
|
|
92
|
+
* literally, i.e. nothing. Counting keeps the emitter under the cliff instead
|
|
93
|
+
* of discovering it as a silent no-op.
|
|
94
|
+
*/
|
|
95
|
+
export function _expanded_pattern_count(pattern) {
|
|
96
|
+
let n = 1;
|
|
97
|
+
for (const m of pattern.matchAll(/\{([^}]*)\}/g)) {
|
|
98
|
+
n *= m[1].split(',').length;
|
|
99
|
+
}
|
|
100
|
+
return n;
|
|
101
|
+
}
|
|
102
|
+
/** Host-documented budget for one rule's whole `paths:` list. */
|
|
103
|
+
export const CLAUDE_PATHS_PATTERN_BUDGET = 1000;
|
|
104
|
+
/**
|
|
105
|
+
* Does this rule declare any trigger that is NOT path-shaped?
|
|
106
|
+
*
|
|
107
|
+
* Load-bearing for `_claude_paths_plan` below, because one `triggers:` list
|
|
108
|
+
* means two different things on two hosts. Cursor and Windsurf treat globs as
|
|
109
|
+
* ADDITIVE — a rule with empty globs still reaches the agent through its
|
|
110
|
+
* description (see `_emit_cursor_mdc`'s own comment). Claude Code treats
|
|
111
|
+
* `paths:` as EXCLUSIVE: with it the rule loads on a path match; without it the
|
|
112
|
+
* rule loads unconditionally. The emitter fed both semantics from one list, so
|
|
113
|
+
* a rule that declared keywords *and* one path glob silently became
|
|
114
|
+
* path-gated-only on Claude.
|
|
115
|
+
*/
|
|
116
|
+
export function _has_non_path_trigger(meta) {
|
|
117
|
+
const triggers = meta['triggers'];
|
|
118
|
+
if (!Array.isArray(triggers))
|
|
119
|
+
return false;
|
|
120
|
+
for (const t of triggers) {
|
|
121
|
+
if (t === null || typeof t !== 'object' || Array.isArray(t))
|
|
122
|
+
continue;
|
|
123
|
+
const obj = t;
|
|
124
|
+
if (typeof obj['keyword'] === 'string' && obj['keyword'])
|
|
125
|
+
return true;
|
|
126
|
+
if (typeof obj['phrase'] === 'string' && obj['phrase'])
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Derive the host's `paths:` list for one rule, with every drop recorded.
|
|
133
|
+
*
|
|
134
|
+
* Kernel / always-apply rules get an EMPTY list on purpose: absent `paths:` is
|
|
135
|
+
* how this host says "load unconditionally", which is exactly what an Iron-Law
|
|
136
|
+
* rule needs. Scoping one would be a correctness regression dressed as a byte
|
|
137
|
+
* saving — and the same contract notes path-scoped rules are not re-injected
|
|
138
|
+
* after `/compact`, so an obligation that must survive compaction cannot be
|
|
139
|
+
* path-scoped at all.
|
|
140
|
+
*/
|
|
141
|
+
export function _claude_paths_plan(meta) {
|
|
142
|
+
const always_apply = Boolean(meta['alwaysApply'] || meta['type'] === 'always');
|
|
143
|
+
if (always_apply) {
|
|
144
|
+
return { globs: [], dropped: [] };
|
|
145
|
+
}
|
|
146
|
+
const globs = [];
|
|
147
|
+
const dropped = [];
|
|
148
|
+
// A rule that ALSO declares keyword / phrase triggers gets no `paths:` at
|
|
149
|
+
// all, and therefore keeps loading unconditionally on Claude Code.
|
|
150
|
+
//
|
|
151
|
+
// Emitting `paths:` here would narrow the rule to a path match and discard
|
|
152
|
+
// every keyword the author wrote, because this host reads the list as the
|
|
153
|
+
// whole gate rather than as one way in. Measured before this guard: 25 of
|
|
154
|
+
// 110 projected rules carried `paths:` and 19 of them also carried keyword
|
|
155
|
+
// triggers — `design-fidelity` lost 21 of them, in exactly the pasted-
|
|
156
|
+
// screenshot and capability-URL handovers its own routing section names as
|
|
157
|
+
// the classes it exists to catch. Nothing in the tree recorded a decision
|
|
158
|
+
// to make that trade, which is why it is treated as a defect.
|
|
159
|
+
//
|
|
160
|
+
// The drop is REPORTED rather than silent, so a rule whose obligation
|
|
161
|
+
// really is path-bound is visible as a candidate for removing its keyword
|
|
162
|
+
// triggers — the narrowing then becomes an authoring decision instead of an
|
|
163
|
+
// emitter side effect. Cursor and Windsurf are untouched: globs are
|
|
164
|
+
// additive there, so the same rule keeps both routes.
|
|
165
|
+
if (_has_non_path_trigger(meta)) {
|
|
166
|
+
for (const raw of derive_trigger_globs(meta)) {
|
|
167
|
+
dropped.push({ pattern: raw, reason: 'mixed-triggers' });
|
|
168
|
+
}
|
|
169
|
+
return { globs, dropped };
|
|
170
|
+
}
|
|
171
|
+
let spent = 0;
|
|
172
|
+
for (const raw of derive_trigger_globs(meta)) {
|
|
173
|
+
if (_is_unresolved_placeholder(raw)) {
|
|
174
|
+
dropped.push({ pattern: raw, reason: 'unresolved-placeholder' });
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
const cost = _expanded_pattern_count(raw);
|
|
178
|
+
if (spent + cost > CLAUDE_PATHS_PATTERN_BUDGET) {
|
|
179
|
+
dropped.push({ pattern: raw, reason: 'over-budget' });
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
spent += cost;
|
|
183
|
+
globs.push(_escape_claude_bracket(raw));
|
|
184
|
+
}
|
|
185
|
+
return { globs, dropped };
|
|
186
|
+
}
|
|
187
|
+
//# sourceMappingURL=claudePathsPlan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claudePathsPlan.js","sourceRoot":"","sources":["../../src/install/claudePathsPlan.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deterministic content fingerprint of a host artefact layer.
|
|
3
|
+
*
|
|
4
|
+
* ## Why a fingerprint and not a version number
|
|
5
|
+
*
|
|
6
|
+
* The single-delivery partition is a *removal*: after it, `task generate-tools`
|
|
7
|
+
* writes 16 rules and zero skills into `<repo>/.claude/` and every other
|
|
8
|
+
* artefact is delivered ONLY by the host-global layer. That removes the build's
|
|
9
|
+
* own repair path — regeneration can no longer heal a stale global layer,
|
|
10
|
+
* because it stops writing the affected files at all.
|
|
11
|
+
*
|
|
12
|
+
* A package version proves *which installer claims to have written* the host
|
|
13
|
+
* directory. It does not prove that the directory holds the artefacts this
|
|
14
|
+
* checkout is about to omit. Measured on the maintainer machine 2026-08-20:
|
|
15
|
+
* `package.json` and the published release both read `14.6.0`, while **153
|
|
16
|
+
* skills existed only in the project layer** and 37 only in the global one. A
|
|
17
|
+
* version-equality predicate would have authorised the partition there and
|
|
18
|
+
* silently dropped 153 skills. So the predicate compares content.
|
|
19
|
+
*
|
|
20
|
+
* ## Cost — measured, and the earlier figure was wrong
|
|
21
|
+
*
|
|
22
|
+
* A prior revision of the blocker recorded 5.85 s per generation for a
|
|
23
|
+
* content comparison and used that number to argue the approach was too
|
|
24
|
+
* expensive. That figure was a **shell artefact**: it spawned one `cat` per
|
|
25
|
+
* file. Re-measured in Node on the same tree: **61 ms** over 664 source files,
|
|
26
|
+
* **103 ms** over 1019 host files. The comparison is cheap; the 5.85 s never
|
|
27
|
+
* described this mechanism.
|
|
28
|
+
*
|
|
29
|
+
* ## Contract
|
|
30
|
+
*
|
|
31
|
+
* Side-effect-free, no CLI entry, no `process.exit` — this module ships inside
|
|
32
|
+
* the consumer installer bundle, same constraint as `ruleInScope.ts`. Keep it
|
|
33
|
+
* that way.
|
|
34
|
+
*/
|
|
35
|
+
import { createHash } from 'node:crypto';
|
|
36
|
+
import * as fs from 'node:fs';
|
|
37
|
+
import * as path from 'node:path';
|
|
38
|
+
/**
|
|
39
|
+
* Fingerprint wire version. Bump when the digest input changes shape, so an
|
|
40
|
+
* old lockfile compares unequal instead of comparing wrong.
|
|
41
|
+
*/
|
|
42
|
+
export const FINGERPRINT_SCHEMA = 1;
|
|
43
|
+
/** Files under `dir`, recursively, sorted by path — deterministic order. */
|
|
44
|
+
function collectFiles(dir) {
|
|
45
|
+
const out = [];
|
|
46
|
+
const walk = (d) => {
|
|
47
|
+
let entries;
|
|
48
|
+
try {
|
|
49
|
+
entries = fs.readdirSync(d, { withFileTypes: true });
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return; // absent or unreadable → contributes nothing
|
|
53
|
+
}
|
|
54
|
+
const sorted = [...entries].sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
|
|
55
|
+
for (const e of sorted) {
|
|
56
|
+
const p = path.join(d, e.name);
|
|
57
|
+
if (e.isDirectory()) {
|
|
58
|
+
walk(p);
|
|
59
|
+
}
|
|
60
|
+
else if (e.isFile()) {
|
|
61
|
+
out.push(p);
|
|
62
|
+
}
|
|
63
|
+
// Symlinks are deliberately skipped: the project layer symlinks into
|
|
64
|
+
// `dist/`, the global layer holds real files, and following links
|
|
65
|
+
// would make two layers of identical CONTENT fingerprint differently
|
|
66
|
+
// depending on which side was read.
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
walk(dir);
|
|
70
|
+
return out.sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Content fingerprint over the given layers.
|
|
74
|
+
*
|
|
75
|
+
* The digest covers, per file, its **layer-relative** path and its bytes — so a
|
|
76
|
+
* rename, a deletion, an addition, and an edit each change it, while the
|
|
77
|
+
* absolute location of the layer does not. Layers are folded in the order
|
|
78
|
+
* given; pass them in a stable order.
|
|
79
|
+
*
|
|
80
|
+
* An absent layer root is not an error: it contributes zero files. That makes
|
|
81
|
+
* the fingerprint of "nothing installed" well-defined and unequal to any real
|
|
82
|
+
* layer, which is what the fail-safe branch of the partition predicate wants.
|
|
83
|
+
*/
|
|
84
|
+
export function fingerprintLayers(layers) {
|
|
85
|
+
const h = createHash('sha256');
|
|
86
|
+
h.update(`v${FINGERPRINT_SCHEMA}\0`);
|
|
87
|
+
for (const layer of layers) {
|
|
88
|
+
h.update(`layer:${layer.label}\0`);
|
|
89
|
+
for (const file of collectFiles(layer.root)) {
|
|
90
|
+
h.update(path.relative(layer.root, file));
|
|
91
|
+
h.update('\0');
|
|
92
|
+
try {
|
|
93
|
+
h.update(fs.readFileSync(file));
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
// A file that vanished between listing and reading is a partial
|
|
97
|
+
// install by definition. Fold a marker rather than throwing, so
|
|
98
|
+
// the digest differs from a complete layer instead of aborting
|
|
99
|
+
// the caller.
|
|
100
|
+
h.update('\0unreadable\0');
|
|
101
|
+
}
|
|
102
|
+
h.update('\0');
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return h.digest('hex');
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* The host-global artefact layers the partition depends on, in a FIXED order.
|
|
109
|
+
*
|
|
110
|
+
* **This is the one definition, and it has to be.** The installer fingerprints
|
|
111
|
+
* what it wrote; the build fingerprints what it finds and compares. Two inline
|
|
112
|
+
* lists would drift — and a drift here does not fail loudly, it makes the
|
|
113
|
+
* partition permanently unreachable while every fail-safe branch reports a
|
|
114
|
+
* plausible reason. Import this; never re-list the layers.
|
|
115
|
+
*
|
|
116
|
+
* Only `claude-code` is covered, and the narrowness is the measurement rather
|
|
117
|
+
* than an omission: the 110-rule / 203,873-token duplication ADR-236 partitions
|
|
118
|
+
* was measured on `~/.claude/`. Widening this list widens what must be verified
|
|
119
|
+
* before a single artefact is withheld, so it is a deliberate addition.
|
|
120
|
+
*
|
|
121
|
+
* `commands` is in the list because the project layer writes skills AND commands
|
|
122
|
+
* into ONE directory (`generate_claude_commands` targets `CLAUDE_SKILLS_DIR`)
|
|
123
|
+
* while the host layer keeps them apart in `~/.claude/skills` and
|
|
124
|
+
* `~/.claude/commands`. Emptying the project directory withholds commands too,
|
|
125
|
+
* so commands must be part of what gets verified first. Measured 2026-08-20:
|
|
126
|
+
* 414 project entries against 298 host skills plus 93 host commands.
|
|
127
|
+
*/
|
|
128
|
+
export function hostLayerInputs(userHome) {
|
|
129
|
+
const claude = path.join(userHome, '.claude');
|
|
130
|
+
return [
|
|
131
|
+
{ label: 'rules', root: path.join(claude, 'rules') },
|
|
132
|
+
{ label: 'skills', root: path.join(claude, 'skills') },
|
|
133
|
+
{ label: 'commands', root: path.join(claude, 'commands') },
|
|
134
|
+
];
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=hostLayerFingerprint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hostLayerFingerprint.js","sourceRoot":"","sources":["../../src/install/hostLayerFingerprint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC;AAUpC,4EAA4E;AAC5E,SAAS,YAAY,CAAC,GAAW;IAC7B,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,MAAM,IAAI,GAAG,CAAC,CAAS,EAAQ,EAAE;QAC7B,IAAI,OAAoB,CAAC;QACzB,IAAI,CAAC;YACD,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,CAAC,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QACzD,CAAC;QAAC,MAAM,CAAC;YACL,OAAO,CAAC,6CAA6C;QACzD,CAAC;QACD,MAAM,MAAM,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7F,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;YACrB,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;YAC/B,IAAI,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;gBAClB,IAAI,CAAC,CAAC,CAAC,CAAC;YACZ,CAAC;iBAAM,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;gBACpB,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAChB,CAAC;YACD,qEAAqE;YACrE,kEAAkE;YAClE,qEAAqE;YACrE,oCAAoC;QACxC,CAAC;IACL,CAAC,CAAC;IACF,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC5D,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAA6B;IAC3D,MAAM,CAAC,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IAC/B,CAAC,CAAC,MAAM,CAAC,IAAI,kBAAkB,IAAI,CAAC,CAAC;IACrC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QACzB,CAAC,CAAC,MAAM,CAAC,SAAS,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC;QACnC,KAAK,MAAM,IAAI,IAAI,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1C,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;YAC1C,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACf,IAAI,CAAC;gBACD,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC;YACpC,CAAC;YAAC,MAAM,CAAC;gBACL,gEAAgE;gBAChE,gEAAgE;gBAChE,+DAA+D;gBAC/D,cAAc;gBACd,CAAC,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;YAC/B,CAAC;YACD,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACnB,CAAC;IACL,CAAC;IACD,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,eAAe,CAAC,QAAgB;IAC5C,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IAC9C,OAAO;QACH,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE;QACpD,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE;QACtD,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE;KAC7D,CAAC;AACN,CAAC"}
|