@event4u/agent-config 9.28.0 → 9.30.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/AGENTS.md +6 -6
- package/CHANGELOG.md +172 -5
- package/README.md +2 -1
- package/agents/templates/.ai-council.yml.example +55 -24
- package/dist/agent-src/commands/analyze/inbox.md +22 -1
- package/dist/agent-src/commands/cost/report.md +2 -2
- package/dist/agent-src/commands/explain-run.md +31 -1
- package/dist/agent-src/commands/team/adversarial.md +8 -7
- package/dist/agent-src/commands/team/delegate.md +14 -12
- package/dist/agent-src/commands/team/review.md +9 -8
- package/dist/agent-src/commands/team/status.md +9 -8
- package/dist/agent-src/commands/team.md +29 -19
- package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +88 -2
- package/dist/agent-src/contexts/execution/auto-orchestration-activation.md +29 -21
- package/dist/agent-src/contexts/execution/host-capability-manifest.md +26 -15
- package/dist/agent-src/contexts/execution/orchestration-telemetry.md +22 -1
- package/dist/agent-src/contexts/execution/roadmap-process-loop.md +17 -0
- package/dist/agent-src/contexts/execution/subagent-response-contract.md +65 -1
- package/dist/agent-src/contexts/execution/subagent-routing.md +13 -11
- package/dist/agent-src/contexts/execution/subagent-spawn-contract.md +25 -0
- package/dist/agent-src/contexts/execution/subagent-steering.md +6 -3
- package/dist/agent-src/rules/delegation-policy.md +11 -7
- package/dist/agent-src/rules/preservation-guard.md +9 -0
- package/dist/agent-src/rules/settings-ask-protocol.md +8 -7
- package/dist/agent-src/rules/token-budget-discipline.md +1 -1
- package/dist/agent-src/scripts/roadmap_gates.ts +312 -0
- package/dist/agent-src/scripts/update_roadmap_progress.ts +72 -4
- package/dist/agent-src/skills/forensics-report/SKILL.md +114 -0
- package/dist/agent-src/skills/forensics-report/evals/triggers.json +17 -0
- package/dist/agent-src/skills/premortem/SKILL.md +30 -1
- package/dist/agent-src/skills/reasoning-orchestrator/SKILL.md +2 -1
- package/dist/agent-src/skills/subagent-orchestration/SKILL.md +17 -5
- package/dist/agent-src/skills/subagent-orchestration/schemas/subagent-status.json +61 -3
- package/dist/agent-src/skills/test-case-discovery/SKILL.md +1 -1
- package/dist/agent-src/templates/AGENTS.md +4 -4
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/roadmaps.md +23 -0
- package/dist/cli/registry.js +2 -0
- package/dist/cli/registry.js.map +1 -1
- package/dist/cli-delegate/{chunk-22GCIJ2O.js → chunk-66OVWGB5.js} +1 -1
- package/dist/cli-delegate/{chunk-7OMQCH4V.js → chunk-BTJNRUX3.js} +22 -35
- package/dist/cli-delegate/{chunk-DVRS2KVR.js → chunk-DDUNNFYX.js} +24 -17
- package/dist/cli-delegate/{chunk-PQSAQKHW.js → chunk-EQY4FLJB.js} +3 -3
- package/dist/cli-delegate/{chunk-2BE5I2MN.js → chunk-IYTGIG2Y.js} +155 -91
- package/dist/cli-delegate/{chunk-GB2FSUEE.js → chunk-LCFJIQ4J.js} +32 -0
- package/dist/cli-delegate/{chunk-VSYT7OHO.js → chunk-LVRYBKTI.js} +31 -2
- package/dist/cli-delegate/chunk-MMJL4TIX.js +18 -0
- package/dist/cli-delegate/{chunk-JXARCGVN.js → chunk-MP3JT3IU.js} +1 -1
- package/dist/cli-delegate/chunk-O3CO5BFB.js +161 -0
- package/dist/cli-delegate/{chunk-REKCMYOU.js → chunk-PFBV6XRT.js} +36 -20
- package/dist/cli-delegate/chunk-RVGBH4XK.js +142 -0
- package/dist/cli-delegate/cmd_analyze_session.js +1 -1
- package/dist/cli-delegate/cmd_brand_status.js +1 -1
- package/dist/cli-delegate/cmd_conformance.js +2803 -137
- package/dist/cli-delegate/cmd_doctor.js +10 -5
- package/dist/cli-delegate/cmd_explain.js +2 -2
- package/dist/cli-delegate/cmd_export.js +4 -4
- package/dist/cli-delegate/cmd_handoff.js +88 -8
- package/dist/cli-delegate/cmd_mcp_available.js +1 -1
- package/dist/cli-delegate/cmd_migrate.js +2 -2
- package/dist/cli-delegate/cmd_packs_active.js +2 -2
- package/dist/cli-delegate/cmd_prune.js +4 -4
- package/dist/cli-delegate/cmd_route_audit.js +3 -2
- package/dist/cli-delegate/cmd_route_explain.js +1 -1
- package/dist/cli-delegate/cmd_session_recycle.js +177 -0
- package/dist/cli-delegate/cmd_settings_get.js +2 -8
- package/dist/cli-delegate/cmd_settings_migrate.js +4 -4
- package/dist/cli-delegate/cmd_settings_set.js +2 -2
- package/dist/cli-delegate/cmd_sync.js +4 -4
- package/dist/cli-delegate/cmd_uninstall.js +4 -4
- 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 +4 -4
- package/dist/cli-delegate/cmd_versions.js +1 -1
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +72 -23
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +3 -2
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +39 -2
- package/dist/discovery/trust-report.md +2 -2
- package/dist/discovery/workspaces.json +12 -4
- package/dist/hooks/dispatch.js +2278 -611
- package/dist/install/install.mjs +56 -17
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +4122 -699
- package/dist/router.json +1 -1
- package/dist/scripts/_lib/agent_settings.js +54 -0
- package/dist/scripts/_lib/agent_settings.js.map +1 -1
- package/dist/scripts/condense.js +147 -2
- package/dist/scripts/condense.js.map +1 -1
- package/dist/server/schemas/settings.js +12 -7
- package/dist/server/schemas/settings.js.map +1 -1
- package/dist/shared/settingsCarveOut.js +0 -9
- package/dist/shared/settingsCarveOut.js.map +1 -1
- package/dist/shared/settingsClasses.js +11 -9
- package/dist/shared/settingsClasses.js.map +1 -1
- package/dist/ui/assets/index-B5qGYOJo.js +26 -0
- package/dist/ui/assets/index-B5qGYOJo.js.map +1 -0
- package/dist/ui/index.html +1 -1
- package/docs/contracts/settings-classes.md +58 -12
- package/package.json +1 -1
- package/src/agent-src/scripts/roadmap_gates.ts +312 -0
- package/src/agent-src/scripts/update_roadmap_progress.ts +72 -4
- package/src/agent-src/templates/AGENTS.md +4 -4
- package/src/config/agent-settings.template.yml +88 -66
- package/src/config/discovery/packs.yml +11 -0
- package/src/config/discovery/workspaces.yml +1 -1
- package/src/config/dispatch-economy-metrics.json +61 -0
- package/src/config/evaluator-budgets.json +4 -4
- package/src/config/gate-violation-baselines.json +3 -3
- package/src/config/hook-token-budget.json +91 -0
- package/src/config/recycle-threshold-budget.json +12 -0
- package/src/config/rule-enforcement-baseline.json +86 -0
- package/src/scripts/_cli/cmd_conformance.ts +31 -44
- package/src/scripts/_cli/cmd_doctor.ts +65 -48
- package/src/scripts/_cli/cmd_session_recycle.ts +226 -0
- package/src/scripts/_dispatch.bash +23 -0
- package/src/scripts/_lib/agent_settings.ts +58 -0
- package/src/scripts/_lib/auto_dispatch.corpus.test.ts +1 -1
- package/src/scripts/_lib/auto_dispatch.ts +23 -18
- package/src/scripts/_lib/capsule_trigger.ts +124 -0
- package/src/scripts/_lib/host_capability.ts +63 -6
- package/src/scripts/_lib/judgment_ladder.ts +634 -0
- package/src/scripts/_lib/orchestration_gate.ts +8 -0
- package/src/scripts/_lib/orchestration_record.ts +78 -10
- package/src/scripts/_lib/orchestration_savings.ts +1 -1
- package/src/scripts/_lib/recycle_envelope_paths.ts +35 -0
- package/src/scripts/_lib/self_repair.ts +354 -13
- package/src/scripts/_lib/self_repair_store.ts +28 -0
- package/src/scripts/_lib/session_eol.ts +230 -0
- package/src/scripts/_lib/session_role.ts +42 -0
- package/src/scripts/_lib/subagent_capsule.ts +341 -0
- package/src/scripts/_lib/subagent_response.ts +94 -0
- package/src/scripts/_lib/subagent_spawn.ts +13 -0
- package/src/scripts/_lib/subagent_steering.ts +9 -4
- package/src/scripts/_lib/tier_budget_routing.ts +6 -1
- package/src/scripts/_lib/worker_budget.ts +37 -2
- package/src/scripts/ai_council/clients.ts +126 -55
- package/src/scripts/ai_council/config.ts +94 -6
- package/src/scripts/ai_council/handoff.ts +113 -0
- package/src/scripts/ai_council/modes.ts +19 -4
- package/src/scripts/ai_council/orchestrator.ts +105 -0
- package/src/scripts/ai_council/quorum.ts +84 -0
- package/src/scripts/ai_council/session.ts +44 -0
- package/src/scripts/ai_council/transport_resolver.ts +127 -1
- package/src/scripts/ai_team/availability.ts +110 -0
- package/src/scripts/ai_team/config.ts +34 -14
- package/src/scripts/ai_team/team_dispatch.ts +71 -29
- package/src/scripts/ask_transport.ts +221 -0
- package/src/scripts/bench_critic_protocol.ts +396 -0
- package/src/scripts/bench_hook_injection.ts +234 -0
- package/src/scripts/check_adr_frontmatter.ts +84 -40
- package/src/scripts/check_branch_freshness.ts +1 -0
- package/src/scripts/check_corpus_staleness.ts +18 -4
- package/src/scripts/check_detector_corpus.ts +219 -0
- package/src/scripts/check_gitignore_freshness.ts +42 -8
- package/src/scripts/check_hook_bundle_freshness.ts +24 -1
- package/src/scripts/check_kernel_prefix_stability.ts +1 -0
- package/src/scripts/check_standing_rule_delivery.ts +73 -32
- package/src/scripts/check_static_layer_stability.ts +154 -0
- package/src/scripts/check_suppression_hygiene.ts +48 -0
- package/src/scripts/condense.ts +162 -2
- package/src/scripts/council_cli.ts +401 -25
- package/src/scripts/dispatch_economy_report.ts +448 -0
- package/src/scripts/dispatch_r2_reviewer.ts +15 -2
- package/src/scripts/explain_run.ts +206 -4
- package/src/scripts/forensics_report.ts +333 -0
- package/src/scripts/generate_settings_reference.ts +1 -0
- package/src/scripts/handoff_context_hook.ts +112 -4
- package/src/scripts/hook_manifest.yaml +117 -10
- package/src/scripts/hooks/concern_registry.ts +8 -0
- package/src/scripts/hooks/delegation_nudge_hook.ts +106 -35
- package/src/scripts/hooks/dispatch_hook.ts +39 -2
- package/src/scripts/hooks/edit_shape_hook.ts +303 -0
- package/src/scripts/hooks/orchestration_record_hook.ts +19 -1
- package/src/scripts/hooks/reread_guard_hook.ts +314 -0
- package/src/scripts/hooks/rtk_wrap_hook.ts +133 -14
- package/src/scripts/hooks/session_eol_hook.ts +268 -0
- package/src/scripts/hooks/turn_end_gate_hook.ts +507 -0
- package/src/scripts/install-hooks.sh +1 -1
- package/src/scripts/language_mirror_hook.ts +89 -0
- package/src/scripts/lint_decision_impact.ts +14 -1
- package/src/scripts/lint_discovery_vocabulary.ts +2 -0
- package/src/scripts/lint_hook_manifest.ts +82 -0
- package/src/scripts/lint_never_silent.ts +276 -0
- package/src/scripts/lint_no_activation_gates.ts +271 -0
- package/src/scripts/lint_readme_serial_comma.ts +1 -0
- package/src/scripts/lint_rule_enforcement_declaration.ts +347 -0
- package/src/scripts/measure_turn_end_gate.ts +194 -0
- package/src/scripts/orchestration_record.ts +12 -1
- package/src/scripts/rebuild_hook_bundle.ts +178 -0
- package/src/scripts/release.ts +74 -2
- package/src/scripts/report_conformance_funnel.ts +284 -0
- package/src/scripts/report_imperative_density.ts +1 -0
- package/src/scripts/routing_doctor.ts +118 -36
- package/src/scripts/score_skill_selection.ts +19 -5
- package/src/scripts/self_repair_cli.ts +337 -59
- package/src/scripts/session_eol_report.ts +261 -0
- package/src/scripts/team_events_spike.ts +271 -0
- package/src/scripts/team_review_gate_hook.ts +31 -9
- package/src/server/schemas/settings.ts +24 -17
- package/src/shared/settingsCarveOut.ts +0 -10
- package/src/shared/settingsClasses.ts +11 -9
- package/src/templates/compact-instructions.md +40 -0
- package/dist/ui/assets/index-DmR0mbk4.js +0 -26
- package/dist/ui/assets/index-DmR0mbk4.js.map +0 -1
package/src/scripts/condense.ts
CHANGED
|
@@ -1174,11 +1174,27 @@ export function generate_rule_symlinks(): number {
|
|
|
1174
1174
|
const skip = new Set(rules.filter((r) => !emit_here.has(r)));
|
|
1175
1175
|
skipped_per_tool[tool_dir] = skip;
|
|
1176
1176
|
_mkdirp(target_dir);
|
|
1177
|
-
// Clean stale
|
|
1177
|
+
// Clean stale entries — a rule that became de-duplicable this run is
|
|
1178
1178
|
// stale at project scope too, so it has to go with the rest.
|
|
1179
|
+
//
|
|
1180
|
+
// Symlink-only was correct while every tool dir was a symlink tree. Two
|
|
1181
|
+
// paths now write REAL files (`thin` mode, and the Claude emitter
|
|
1182
|
+
// below), and a stale real file is invisible to an `_isSymlink` test —
|
|
1183
|
+
// so a renamed or newly de-duplicable rule would leave its body behind,
|
|
1184
|
+
// loaded unconditionally, forever.
|
|
1185
|
+
//
|
|
1186
|
+
// Ownership test for a real file: its basename is an agent-config rule
|
|
1187
|
+
// in the projection source. A consumer's own hand-written rule is only
|
|
1188
|
+
// touched if it collides with one of ours by name, in which case it was
|
|
1189
|
+
// already being overwritten.
|
|
1179
1190
|
for (const item of _iterdirSorted(target_dir)) {
|
|
1180
1191
|
const name = path.basename(item);
|
|
1181
|
-
if (
|
|
1192
|
+
if (name === 'README.md') {
|
|
1193
|
+
continue;
|
|
1194
|
+
}
|
|
1195
|
+
const is_ours =
|
|
1196
|
+
_isSymlink(item) || _isFile(path.join(MODULE_STATE.RULES_SOURCE, name));
|
|
1197
|
+
if (is_ours && (!rules.includes(name) || skip.has(name))) {
|
|
1182
1198
|
fs.unlinkSync(item);
|
|
1183
1199
|
}
|
|
1184
1200
|
}
|
|
@@ -1192,6 +1208,11 @@ export function generate_rule_symlinks(): number {
|
|
|
1192
1208
|
}
|
|
1193
1209
|
if (thin_files !== null) {
|
|
1194
1210
|
_writeText(link, thin_files[rule] as string);
|
|
1211
|
+
} else if (tool_dir === '.claude/rules') {
|
|
1212
|
+
// Host-native activation (P3.1): emit the rule with the host's
|
|
1213
|
+
// own `paths:` key instead of symlinking agent-config
|
|
1214
|
+
// frontmatter this host does not read.
|
|
1215
|
+
_emit_claude_rule(path.join(MODULE_STATE.RULES_SOURCE, rule), link);
|
|
1195
1216
|
} else {
|
|
1196
1217
|
fs.symlinkSync(path.join(rel_prefix, rule), link);
|
|
1197
1218
|
}
|
|
@@ -1355,6 +1376,145 @@ export function _emit_windsurf_rule(source: string, target: string): void {
|
|
|
1355
1376
|
_writeText(target, lines.join('\n'));
|
|
1356
1377
|
}
|
|
1357
1378
|
|
|
1379
|
+
/**
|
|
1380
|
+
* A brace group the host expands, versus an agent-config placeholder that only
|
|
1381
|
+
* LOOKS like one.
|
|
1382
|
+
*
|
|
1383
|
+
* `path_prefix: "{module_root}/"` in `roadmap-ci-steps-policy` is resolved by
|
|
1384
|
+
* this suite from `modules.root_paths`. Emitted verbatim into a host `paths:`
|
|
1385
|
+
* list it is a brace group with no comma, which the host expands to the literal
|
|
1386
|
+
* string `{module_root}` — a pattern that matches no file. The rule would then
|
|
1387
|
+
* reach the model **never** instead of on-demand, and nothing would say so: the
|
|
1388
|
+
* probed contract records this exact degradation as silent
|
|
1389
|
+
* (`claude-code-rules-dir-contract.md` § constraints).
|
|
1390
|
+
*
|
|
1391
|
+
* Dropping the pattern is fail-safe in the one direction that matters. A rule
|
|
1392
|
+
* left with no pattern at all carries no `paths:` key and loads
|
|
1393
|
+
* unconditionally — the status quo, not a regression. A rule carrying a
|
|
1394
|
+
* no-op pattern is invisible.
|
|
1395
|
+
*
|
|
1396
|
+
* The discriminator is the comma, not a placeholder allowlist: `{ts,tsx}` is a
|
|
1397
|
+
* real alternation, `{module_root}` cannot be one.
|
|
1398
|
+
*/
|
|
1399
|
+
export function _is_unresolved_placeholder(pattern: string): boolean {
|
|
1400
|
+
for (const m of pattern.matchAll(/\{([^}]*)\}/g)) {
|
|
1401
|
+
if (!(m[1] as string).includes(',')) {
|
|
1402
|
+
return true;
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
return false;
|
|
1406
|
+
}
|
|
1407
|
+
|
|
1408
|
+
/**
|
|
1409
|
+
* `[` opens a bracket expression for the host. An unparseable one makes that
|
|
1410
|
+
* pattern match nothing while the rule's other patterns keep working — so a
|
|
1411
|
+
* literal `[` in a trigger is escaped rather than trusted.
|
|
1412
|
+
*/
|
|
1413
|
+
export function _escape_claude_bracket(pattern: string): string {
|
|
1414
|
+
return pattern.replace(/\[/g, '\\[');
|
|
1415
|
+
}
|
|
1416
|
+
|
|
1417
|
+
/**
|
|
1418
|
+
* Expanded-pattern cost of one glob: the product of its brace alternations.
|
|
1419
|
+
* The host budgets a rule's whole `paths:` list at 1,000 expanded patterns and
|
|
1420
|
+
* 4 MiB, and a list over budget is used UNEXPANDED — braces then match
|
|
1421
|
+
* literally, i.e. nothing. Counting keeps the emitter under the cliff instead
|
|
1422
|
+
* of discovering it as a silent no-op.
|
|
1423
|
+
*/
|
|
1424
|
+
export function _expanded_pattern_count(pattern: string): number {
|
|
1425
|
+
let n = 1;
|
|
1426
|
+
for (const m of pattern.matchAll(/\{([^}]*)\}/g)) {
|
|
1427
|
+
n *= (m[1] as string).split(',').length;
|
|
1428
|
+
}
|
|
1429
|
+
return n;
|
|
1430
|
+
}
|
|
1431
|
+
|
|
1432
|
+
/** Host-documented budget for one rule's whole `paths:` list. */
|
|
1433
|
+
export const CLAUDE_PATHS_PATTERN_BUDGET = 1000;
|
|
1434
|
+
|
|
1435
|
+
export interface ClaudePathsPlan {
|
|
1436
|
+
/** Patterns to emit under `paths:`, in declaration order. */
|
|
1437
|
+
globs: string[];
|
|
1438
|
+
/** Patterns deliberately not emitted, with the reason a reader can act on. */
|
|
1439
|
+
dropped: { pattern: string; reason: 'unresolved-placeholder' | 'over-budget' }[];
|
|
1440
|
+
}
|
|
1441
|
+
|
|
1442
|
+
/**
|
|
1443
|
+
* Derive the host's `paths:` list for one rule, with every drop recorded.
|
|
1444
|
+
*
|
|
1445
|
+
* Kernel / always-apply rules get an EMPTY list on purpose: absent `paths:` is
|
|
1446
|
+
* how this host says "load unconditionally", which is exactly what an Iron-Law
|
|
1447
|
+
* rule needs. Scoping one would be a correctness regression dressed as a byte
|
|
1448
|
+
* saving — and the same contract notes path-scoped rules are not re-injected
|
|
1449
|
+
* after `/compact`, so an obligation that must survive compaction cannot be
|
|
1450
|
+
* path-scoped at all.
|
|
1451
|
+
*/
|
|
1452
|
+
export function _claude_paths_plan(meta: Record<string, unknown>): ClaudePathsPlan {
|
|
1453
|
+
const always_apply = Boolean(meta['alwaysApply'] || meta['type'] === 'always');
|
|
1454
|
+
if (always_apply) {
|
|
1455
|
+
return { globs: [], dropped: [] };
|
|
1456
|
+
}
|
|
1457
|
+
const globs: string[] = [];
|
|
1458
|
+
const dropped: ClaudePathsPlan['dropped'] = [];
|
|
1459
|
+
let spent = 0;
|
|
1460
|
+
for (const raw of derive_trigger_globs(meta)) {
|
|
1461
|
+
if (_is_unresolved_placeholder(raw)) {
|
|
1462
|
+
dropped.push({ pattern: raw, reason: 'unresolved-placeholder' });
|
|
1463
|
+
continue;
|
|
1464
|
+
}
|
|
1465
|
+
const cost = _expanded_pattern_count(raw);
|
|
1466
|
+
if (spent + cost > CLAUDE_PATHS_PATTERN_BUDGET) {
|
|
1467
|
+
dropped.push({ pattern: raw, reason: 'over-budget' });
|
|
1468
|
+
continue;
|
|
1469
|
+
}
|
|
1470
|
+
spent += cost;
|
|
1471
|
+
globs.push(_escape_claude_bracket(raw));
|
|
1472
|
+
}
|
|
1473
|
+
return { globs, dropped };
|
|
1474
|
+
}
|
|
1475
|
+
|
|
1476
|
+
/**
|
|
1477
|
+
* Emit a Claude Code rule carrying the host's OWN activation key.
|
|
1478
|
+
*
|
|
1479
|
+
* Sibling of {@link _emit_cursor_mdc} and {@link _emit_windsurf_rule}, and the
|
|
1480
|
+
* third member of a set that had two. `.claude/rules` was a symlink projection
|
|
1481
|
+
* of `dist/agent-src/rules`, which carried agent-config's own frontmatter
|
|
1482
|
+
* vocabulary (`type`, `tier`, `triggers`, `alwaysApply`, …) into a host that
|
|
1483
|
+
* reads **none** of it — so every rule loaded unconditionally and the corpus
|
|
1484
|
+
* arrived in full every session.
|
|
1485
|
+
*
|
|
1486
|
+
* Emitted frontmatter is therefore `paths:` and nothing else: the one key the
|
|
1487
|
+
* probed contract records as read by this host. A rule with no path-shaped
|
|
1488
|
+
* trigger gets no frontmatter at all rather than a block the host ignores —
|
|
1489
|
+
* keys that do nothing are bytes in every session's standing context.
|
|
1490
|
+
*
|
|
1491
|
+
* The body is copied byte-for-byte from the projection source (ADR-201's
|
|
1492
|
+
* copy-plus-rewrite discipline); only the frontmatter is host-shaped.
|
|
1493
|
+
*/
|
|
1494
|
+
export function _emit_claude_rule(source: string, target: string): void {
|
|
1495
|
+
const [meta, body] = _parse_frontmatter(_readText(source));
|
|
1496
|
+
const plan = _claude_paths_plan(meta);
|
|
1497
|
+
for (const d of plan.dropped) {
|
|
1498
|
+
_print(
|
|
1499
|
+
` ⚠️ ${path.basename(target)}: dropped \`paths:\` pattern ${JSON.stringify(d.pattern)} (${d.reason}) — ` +
|
|
1500
|
+
(plan.globs.length > 0
|
|
1501
|
+
? 'the rule keeps its other patterns'
|
|
1502
|
+
: 'the rule now loads unconditionally'),
|
|
1503
|
+
);
|
|
1504
|
+
}
|
|
1505
|
+
const lines: string[] = [];
|
|
1506
|
+
if (plan.globs.length > 0) {
|
|
1507
|
+
lines.push('---', 'paths:');
|
|
1508
|
+
for (const g of plan.globs) {
|
|
1509
|
+
lines.push(` - ${_yaml_scalar(g)}`);
|
|
1510
|
+
}
|
|
1511
|
+
lines.push('---', '');
|
|
1512
|
+
}
|
|
1513
|
+
lines.push(_pyRstrip(body) + '\n');
|
|
1514
|
+
_mkdirp(path.dirname(target));
|
|
1515
|
+
_writeText(target, lines.join('\n'));
|
|
1516
|
+
}
|
|
1517
|
+
|
|
1358
1518
|
/** Python str.rstrip() with no args. */
|
|
1359
1519
|
function _pyRstrip(s: string): string {
|
|
1360
1520
|
return s.replace(/\s+$/u, '');
|