@event4u/agent-config 14.7.0 → 14.9.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.
Files changed (230) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +175 -390
  3. package/README.md +1 -1
  4. package/agents/templates/.ai-council.yml.example +34 -4
  5. package/dist/agent-src/commands/evals/git-pr-merge.json +13 -0
  6. package/dist/agent-src/commands/evals/roadmap.json +17 -1
  7. package/dist/agent-src/commands/pr/create.md +14 -2
  8. package/dist/agent-src/commands/pr/merge.md +383 -0
  9. package/dist/agent-src/commands/review/changes.md +95 -14
  10. package/dist/agent-src/commands/roadmap/process-full.md +157 -3
  11. package/dist/agent-src/commands/roadmap.md +1 -1
  12. package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +46 -36
  13. package/dist/agent-src/contexts/execution/autonomy-mechanics.md +37 -2
  14. package/dist/agent-src/contexts/execution/host-capability-manifest.md +77 -0
  15. package/dist/agent-src/contexts/execution/roadmap-execution-contract.md +100 -2
  16. package/dist/agent-src/contexts/execution/roadmap-process-loop.md +154 -2
  17. package/dist/agent-src/contexts/execution/subagent-response-contract.md +80 -0
  18. package/dist/agent-src/rules/artifact-drafting-protocol.md +5 -1
  19. package/dist/agent-src/rules/decision-revisit-gate.md +65 -33
  20. package/dist/agent-src/rules/recurring-criticism.md +1 -1
  21. package/dist/agent-src/rules/roadmap-progress-sync.md +19 -0
  22. package/dist/agent-src/rules/source-confidentiality.md +1 -1
  23. package/dist/agent-src/rules/untrusted-input-defense.md +9 -3
  24. package/dist/agent-src/scripts/archive_completed_roadmaps.ts +7 -4
  25. package/dist/agent-src/scripts/dashboard_mode.ts +212 -0
  26. package/dist/agent-src/scripts/update_roadmap_progress.ts +47 -48
  27. package/dist/agent-src/skills/adr-create/SKILL.md +124 -5
  28. package/dist/agent-src/skills/code-review/evals/evals.json +87 -46
  29. package/dist/agent-src/skills/decision-record/SKILL.md +61 -3
  30. package/dist/agent-src/skills/decision-review/SKILL.md +65 -0
  31. package/dist/agent-src/skills/humanizer/SKILL.md +39 -0
  32. package/dist/agent-src/skills/humanizer/evals/strip_fixtures.json +57 -0
  33. package/dist/agent-src/skills/humanizer/references/fixtures.md +54 -0
  34. package/dist/agent-src/skills/judge-spec-compliance/SKILL.md +154 -0
  35. package/dist/agent-src/skills/judge-synthesis/SKILL.md +45 -0
  36. package/dist/agent-src/skills/merge-conflicts/SKILL.md +26 -0
  37. package/dist/agent-src/skills/roadmap-writing/SKILL.md +18 -18
  38. package/dist/agent-src/skills/security/SKILL.md +8 -0
  39. package/dist/agent-src/skills/security-audit/SKILL.md +12 -1
  40. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  41. package/dist/agent-src/templates/roadmaps.md +28 -2
  42. package/dist/cli/registry.js +3 -0
  43. package/dist/cli/registry.js.map +1 -1
  44. package/dist/cli-delegate/{chunk-FBKL6JWT.js → chunk-77GR3VD4.js} +68 -43
  45. package/dist/cli-delegate/{chunk-JZ4NR2TW.js → chunk-7PRE6ZV2.js} +1 -1
  46. package/dist/cli-delegate/{chunk-UEZ7D35A.js → chunk-CYH5SP6M.js} +4 -23
  47. package/dist/cli-delegate/{chunk-Q26HT4QT.js → chunk-E46KPN6K.js} +251 -150
  48. package/dist/cli-delegate/{chunk-74E3TKWV.js → chunk-H4VIVD4C.js} +5 -5
  49. package/dist/cli-delegate/chunk-I3EIN2YG.js +36 -0
  50. package/dist/cli-delegate/{chunk-4VR4ORQ6.js → chunk-LPPWO5CE.js} +4 -3
  51. package/dist/cli-delegate/{chunk-7F3VYSM2.js → chunk-PLSG6UL5.js} +14 -14
  52. package/dist/cli-delegate/cmd_adr_effective.js +1162 -0
  53. package/dist/cli-delegate/cmd_conformance.js +101 -25
  54. package/dist/cli-delegate/cmd_converge.js +3 -3
  55. package/dist/cli-delegate/cmd_doctor.js +7 -7
  56. package/dist/cli-delegate/cmd_export.js +6 -6
  57. package/dist/cli-delegate/cmd_handoff.js +7 -6
  58. package/dist/cli-delegate/cmd_memory_get.js +2 -1
  59. package/dist/cli-delegate/cmd_migrate.js +2 -2
  60. package/dist/cli-delegate/cmd_preflight.js +5 -5
  61. package/dist/cli-delegate/cmd_prune.js +6 -6
  62. package/dist/cli-delegate/cmd_route_audit.js +6 -5
  63. package/dist/cli-delegate/cmd_route_explain.js +3 -3
  64. package/dist/cli-delegate/cmd_session_recycle.js +3 -3
  65. package/dist/cli-delegate/cmd_settings_get.js +4 -4
  66. package/dist/cli-delegate/cmd_settings_migrate.js +6 -6
  67. package/dist/cli-delegate/cmd_settings_set.js +1 -1
  68. package/dist/cli-delegate/cmd_sync.js +6 -6
  69. package/dist/cli-delegate/cmd_uninstall.js +6 -6
  70. package/dist/cli-delegate/cmd_update.js +3 -3
  71. package/dist/cli-delegate/cmd_upgrade.js +3 -3
  72. package/dist/cli-delegate/cmd_validate.js +6 -6
  73. package/dist/cli-delegate/cmd_versions.js +3 -3
  74. package/dist/discovery/deprecation-report.md +1 -1
  75. package/dist/discovery/discovery-manifest.json +83 -30
  76. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  77. package/dist/discovery/discovery-manifest.summary.md +4 -4
  78. package/dist/discovery/dormancy-report.md +1 -1
  79. package/dist/discovery/orphan-report.md +1 -1
  80. package/dist/discovery/packs.json +11 -9
  81. package/dist/discovery/trust-report.md +2 -2
  82. package/dist/discovery/workspaces.json +9 -7
  83. package/dist/hooks/dispatch.js +1295 -812
  84. package/dist/install/globalRuleLayers.js +169 -0
  85. package/dist/install/globalRuleLayers.js.map +1 -0
  86. package/dist/install/partitionEligibility.js +156 -0
  87. package/dist/install/partitionEligibility.js.map +1 -1
  88. package/dist/install/ruleLayerPartition.js +157 -0
  89. package/dist/install/ruleLayerPartition.js.map +1 -0
  90. package/dist/mcp/registry-manifest.json +3 -3
  91. package/dist/mcp/server.json +2 -2
  92. package/dist/mcp/server.mjs +1358 -805
  93. package/dist/scripts/_lib/claude_plugin.js +162 -0
  94. package/dist/scripts/_lib/claude_plugin.js.map +1 -0
  95. package/dist/scripts/_lib/environment_detector.js +397 -0
  96. package/dist/scripts/_lib/environment_detector.js.map +1 -0
  97. package/dist/scripts/_lib/prune_empty_dirs.js +85 -0
  98. package/dist/scripts/_lib/prune_empty_dirs.js.map +1 -0
  99. package/dist/scripts/_lib/spawn_env.js +129 -0
  100. package/dist/scripts/_lib/spawn_env.js.map +1 -0
  101. package/dist/scripts/ai_council/modes.js +199 -0
  102. package/dist/scripts/ai_council/modes.js.map +1 -0
  103. package/dist/scripts/ai_council/transport_resolver.js +418 -0
  104. package/dist/scripts/ai_council/transport_resolver.js.map +1 -0
  105. package/dist/scripts/condense.js +52 -89
  106. package/dist/scripts/condense.js.map +1 -1
  107. package/dist/server/routes/wizard.js +3 -2
  108. package/dist/server/routes/wizard.js.map +1 -1
  109. package/dist/ui/assets/index-Cxgy63kz.js +26 -0
  110. package/dist/ui/assets/index-Cxgy63kz.js.map +1 -0
  111. package/dist/ui/index.html +1 -1
  112. package/docs/guidelines/agent-infra/artifact-drafting-protocol-mechanics.md +45 -1
  113. package/docs/guidelines/agent-infra/false-green.md +47 -1
  114. package/docs/guidelines/agent-infra/traceability-field-mechanics.md +50 -0
  115. package/docs/guidelines/agent-infra/untrusted-input-spotlighting.md +17 -0
  116. package/package.json +7 -3
  117. package/src/agent-src/scripts/archive_completed_roadmaps.ts +7 -4
  118. package/src/agent-src/scripts/dashboard_mode.ts +212 -0
  119. package/src/agent-src/scripts/update_roadmap_progress.ts +47 -48
  120. package/src/config/ci-local-parity.yml +21 -0
  121. package/src/config/estate-count-budget.json +13 -471
  122. package/src/config/evaluator-budgets.json +4 -4
  123. package/src/config/gate-coverage.yml +458 -12
  124. package/src/config/gate-violation-baselines.json +18 -8
  125. package/src/config/gitignore-block.txt +15 -2
  126. package/src/config/hook-latency-budget.json +5 -0
  127. package/src/config/publish-surface.json +60 -0
  128. package/src/config/requirements-trace-budget.json +32 -0
  129. package/src/config/rule-stub-ceilings.json +25 -4
  130. package/src/install/globalRuleLayers.ts +197 -0
  131. package/src/install/partitionEligibility.ts +177 -0
  132. package/src/install/ruleLayerPartition.ts +212 -0
  133. package/src/scripts/_cli/cmd_adr_effective.ts +484 -0
  134. package/src/scripts/_dispatch.bash +18 -0
  135. package/src/scripts/_lib/adr_frontmatter.test.ts +365 -0
  136. package/src/scripts/_lib/adr_frontmatter.ts +459 -0
  137. package/src/scripts/_lib/base_tree.ts +175 -0
  138. package/src/scripts/_lib/billing_grant.ts +165 -0
  139. package/src/scripts/_lib/billing_grant_cli.ts +123 -0
  140. package/src/scripts/_lib/council_fallback_posture.ts +53 -6
  141. package/src/scripts/_lib/council_fallback_wiring.ts +61 -1
  142. package/src/scripts/_lib/envelope_grounding.ts +11 -1
  143. package/src/scripts/_lib/host_capability.ts +59 -5
  144. package/src/scripts/_lib/layer_overlap_notice.ts +11 -2
  145. package/src/scripts/_lib/prune_empty_dirs.ts +80 -0
  146. package/src/scripts/_lib/quota_parked.ts +133 -0
  147. package/src/scripts/_lib/retrieval_sanitize.ts +62 -0
  148. package/src/scripts/_lib/review_telemetry.ts +196 -0
  149. package/src/scripts/_lib/subagent_response.ts +92 -0
  150. package/src/scripts/adr/evidence_census.ts +899 -0
  151. package/src/scripts/adr/regenerate_index.ts +25 -38
  152. package/src/scripts/adr_cite_check.ts +540 -39
  153. package/src/scripts/ai_council/clients.ts +12 -1
  154. package/src/scripts/ai_council/config.ts +72 -115
  155. package/src/scripts/ai_council/fallback_config.ts +19 -7
  156. package/src/scripts/ai_council/mid_flight_fallback.ts +88 -7
  157. package/src/scripts/ai_council/orchestrator.ts +2 -2
  158. package/src/scripts/ai_council/py_format.ts +124 -0
  159. package/src/scripts/ai_council/transport_resolver.ts +65 -2
  160. package/src/scripts/audit_adr_coverage.ts +134 -21
  161. package/src/scripts/bench_hook_latency.ts +204 -0
  162. package/src/scripts/build_archive_index.ts +34 -0
  163. package/src/scripts/check_adr_frontmatter.ts +574 -39
  164. package/src/scripts/check_council_pin_staleness.ts +300 -0
  165. package/src/scripts/check_estate_count.ts +420 -293
  166. package/src/scripts/check_gate_coverage.ts +91 -0
  167. package/src/scripts/check_hook_bundle_content.ts +219 -0
  168. package/src/scripts/check_new_adr_evidence.ts +529 -0
  169. package/src/scripts/check_no_stub_inventory_table.ts +292 -0
  170. package/src/scripts/check_pack_size.ts +234 -1
  171. package/src/scripts/check_publish_surface.ts +297 -0
  172. package/src/scripts/check_references.ts +18 -0
  173. package/src/scripts/check_requirements_trace.ts +378 -0
  174. package/src/scripts/check_rule_layer_partition.ts +531 -0
  175. package/src/scripts/check_secret_leak.ts +166 -12
  176. package/src/scripts/check_single_delivery.ts +137 -4
  177. package/src/scripts/check_standing_rule_delivery.ts +8 -2
  178. package/src/scripts/code_graph/cli.ts +44 -5
  179. package/src/scripts/code_graph/extract.ts +87 -0
  180. package/src/scripts/condense.ts +61 -91
  181. package/src/scripts/council_cli.ts +12 -16
  182. package/src/scripts/detect_ai_tells.ts +87 -0
  183. package/src/scripts/dispatch_r2_reviewer.ts +42 -0
  184. package/src/scripts/external_sources_denylist.json +4 -1
  185. package/src/scripts/generate_capabilities_index.ts +41 -0
  186. package/src/scripts/git_authorization_hook.ts +54 -4
  187. package/src/scripts/hooks/block_unauthorized_git.ts +41 -3
  188. package/src/scripts/hooks/dispatch_hook.ts +154 -187
  189. package/src/scripts/hooks/dispatch_issues.ts +38 -19
  190. package/src/scripts/hooks/fallback_yaml.ts +66 -0
  191. package/src/scripts/hooks/host_semantics.ts +21 -0
  192. package/src/scripts/hooks/injection_budget.ts +13 -3
  193. package/src/scripts/hooks/py_json_dumps.ts +103 -0
  194. package/src/scripts/hooks/run_continuation_hook.ts +3 -1
  195. package/src/scripts/hooks/state_io.ts +88 -1
  196. package/src/scripts/hooks/stdin_failure_policy.ts +96 -0
  197. package/src/scripts/hooks/subagent_ledger_hook.ts +76 -11
  198. package/src/scripts/injection_scan_hook.ts +257 -15
  199. package/src/scripts/lint_adr_sweep_routing.ts +365 -0
  200. package/src/scripts/lint_hook_manifest.ts +49 -0
  201. package/src/scripts/lint_provenance_vocabulary.ts +472 -4
  202. package/src/scripts/lint_workflow_security.ts +53 -10
  203. package/src/scripts/lint_workflow_security_allowlist.json +2 -18
  204. package/src/scripts/report_envelope_rate.ts +166 -0
  205. package/src/scripts/review_axis_report.ts +218 -0
  206. package/src/scripts/routing_doctor.ts +5 -1
  207. package/src/scripts/run_supervise.ts +46 -1
  208. package/src/scripts/schemas/evals.schema.json +5 -0
  209. package/src/scripts/sync_pr_branch.ts +170 -20
  210. package/dist/cli/commands/commands.candidates.test.js +0 -257
  211. package/dist/cli/commands/commands.candidates.test.js.map +0 -1
  212. package/dist/cli/commands/profiles.test.js +0 -88
  213. package/dist/cli/commands/profiles.test.js.map +0 -1
  214. package/dist/cli/commands/recordTriggerEval.test.js +0 -113
  215. package/dist/cli/commands/recordTriggerEval.test.js.map +0 -1
  216. package/dist/cli/configRoot.test.js +0 -97
  217. package/dist/cli/configRoot.test.js.map +0 -1
  218. package/dist/cli/mcp/content.test.js +0 -54
  219. package/dist/cli/mcp/content.test.js.map +0 -1
  220. package/dist/cli/mcp/dispatch.test.js +0 -108
  221. package/dist/cli/mcp/dispatch.test.js.map +0 -1
  222. package/dist/server/writeRoot.test.js +0 -91
  223. package/dist/server/writeRoot.test.js.map +0 -1
  224. package/dist/shared/capabilities.test.js +0 -39
  225. package/dist/shared/capabilities.test.js.map +0 -1
  226. package/dist/ui/assets/index-C1pBRm1f.js +0 -26
  227. package/dist/ui/assets/index-C1pBRm1f.js.map +0 -1
  228. package/dist/cli-delegate/{chunk-PPQO4NGR.js → chunk-6RJA2F5A.js} +3 -3
  229. package/dist/cli-delegate/{chunk-6EOCNQAM.js → chunk-E4XIZDIB.js} +0 -0
  230. package/dist/cli-delegate/{chunk-GJ5BVHXM.js → chunk-PMEKGDED.js} +3 -3
@@ -230,7 +230,9 @@ export { rule_in_scope } from '../install/ruleInScope.js';
230
230
  // Re-exported for in-repo consumers; definitions moved beside emit_host_rules_cli.ts (Phase 5).
231
231
  export { CLAUDE_PATHS_PATTERN_BUDGET, _claude_paths_plan, _escape_claude_bracket, _expanded_pattern_count, _has_non_path_trigger, _is_unresolved_placeholder, derive_trigger_globs, } from '../install/claudePathsPlan.js';
232
232
  import { rule_in_scope } from '../install/ruleInScope.js';
233
- import { isExclusivelyPackageOnly, partitionActive, setPartitionAnnounce } from '../install/partitionEligibility.js'; // ADR-236
233
+ import { pruneEmptyDirs } from './_lib/prune_empty_dirs.js';
234
+ import { commandsWithheld, partitionActive, personaPartition, setPartitionAnnounce } from '../install/partitionEligibility.js'; // ADR-236
235
+ import { dedupableRules, partitionRulesForDir } from '../install/ruleLayerPartition.js'; // ADR-236, per-host evidence
234
236
  import { _claude_paths_plan, derive_trigger_globs } from '../install/claudePathsPlan.js';
235
237
  const _HERE = path.dirname(fileURLToPath(import.meta.url)); // <repo>/src/scripts
236
238
  const _DEFAULT_PROJECT_ROOT = path.resolve(_HERE, '..', '..');
@@ -366,14 +368,6 @@ function _read_augment_rules_use_symlinks() {
366
368
  }
367
369
  return false;
368
370
  }
369
- /**
370
- * Per-tool user-scope rule directory, for the scope-dedup below. Only tools
371
- * whose host reads a user-scope rules directory can have a redundant twin;
372
- * everything else has nothing to de-duplicate against.
373
- */
374
- const USER_SCOPE_RULE_DIRS = {
375
- '.claude/rules': path.join('.claude', 'rules'),
376
- };
377
371
  function _read_projection_scope_dedup() {
378
372
  const data = load_agent_settings({ project_path: MODULE_STATE.SETTINGS_FILE });
379
373
  const projection = data['projection'];
@@ -389,63 +383,6 @@ function _read_projection_scope_dedup() {
389
383
  }
390
384
  return false;
391
385
  }
392
- /**
393
- * Rules whose user-scope twin is BYTE-IDENTICAL to the source, i.e. safe to
394
- * skip at project scope: the host still loads the same text, once instead of
395
- * twice, so nothing the model sees changes.
396
- *
397
- * Byte-identity is the whole safety argument and is not negotiable. Keying on
398
- * the filename alone would silently let a stale globally-installed copy win
399
- * whenever the two scopes hold different versions — which is the NORMAL state
400
- * while developing the package (measured: 110/110 shared filenames differing in
401
- * bytes). This is deliberately not the thin-projection mechanism: no rule
402
- * becomes trigger-gated, so the quality floor that disabled thin projection
403
- * does not apply here.
404
- */
405
- function _dedupable_rules(tool_dir, rules, userHome) {
406
- const relative = USER_SCOPE_RULE_DIRS[tool_dir];
407
- if (relative === undefined) {
408
- return new Set();
409
- }
410
- // A hostile or simply absent $HOME must make the dedup inert, not
411
- // adventurous. In a container `$HOME` is often unset (so `homedir()` can
412
- // resolve to `/`) or world-writable, and this function decides which rules
413
- // to STOP emitting — reading an unexpected tree there is how a projection
414
- // silently loses a rule. Council review of PR #1055 raised exactly this.
415
- let userDirStat;
416
- const userDir = path.join(userHome, relative);
417
- try {
418
- userDirStat = fs.statSync(userDir);
419
- }
420
- catch {
421
- return new Set();
422
- }
423
- if (!userDirStat.isDirectory()) {
424
- return new Set();
425
- }
426
- // World-writable user scope: anyone on the box could plant a byte-identical
427
- // twin and thereby delete a rule from the project projection. Refuse.
428
- if ((userDirStat.mode & 0o002) !== 0) {
429
- _print(` ⚠️ ${tool_dir}: user-scope rules dir is world-writable — scope-dedup skipped`);
430
- return new Set();
431
- }
432
- const skip = new Set();
433
- for (const rule of rules) {
434
- const twin = path.join(userDir, rule);
435
- const source = path.join(MODULE_STATE.RULES_SOURCE, rule);
436
- try {
437
- if (!_isFile(twin) || !_isFile(source))
438
- continue;
439
- if (fs.readFileSync(twin).equals(fs.readFileSync(source))) {
440
- skip.add(rule);
441
- }
442
- }
443
- catch {
444
- // An unreadable twin is simply not de-duplicable — emit the project copy.
445
- }
446
- }
447
- return skip;
448
- }
449
386
  function _lean_projection_mode() {
450
387
  const data = load_agent_settings({ project_path: MODULE_STATE.SETTINGS_FILE });
451
388
  const lean = data['lean_projection'];
@@ -1009,10 +946,16 @@ function _scoped_rule_basenames() {
1009
946
  // is its fourth consumer, after the router compiler, the dist writer, and
1010
947
  // check_sync. Same predicate in all four; that is the point.
1011
948
  .filter((p) => !skip_compile_disabled_rule(`rules/${path.basename(p)}`))
1012
- .filter((p) => !partitionActive(MODULE_STATE.PROJECT_ROOT) || isExclusivelyPackageOnly(p))
1013
949
  .map((p) => path.basename(p))
1014
950
  .sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));
1015
951
  }
952
+ /** Adapter over {@link partitionRulesForDir}; that module carries the reasoning. */
953
+ export function partition_rules_for_dir(tool_dir, rules, user_home = process.env['HOME'] ?? os.homedir()) {
954
+ return partitionRulesForDir({
955
+ toolDir: tool_dir, rules, userHome: user_home, announce: _print,
956
+ projectRoot: MODULE_STATE.PROJECT_ROOT, rulesSource: MODULE_STATE.RULES_SOURCE,
957
+ });
958
+ }
1016
959
  /**
1017
960
  * The emit plan of {@link generate_rule_symlinks}: active tool dir → the exact
1018
961
  * rule basenames it projects there.
@@ -1035,8 +978,12 @@ export function projected_rule_trees(user_home = process.env['HOME'] ?? os.homed
1035
978
  const dedup_on = _read_projection_scope_dedup();
1036
979
  const out = {};
1037
980
  for (const tool_dir of Object.keys(_filter_tool_dirs(TOOL_DIRS))) {
1038
- const skip = dedup_on ? _dedupable_rules(tool_dir, rules, user_home) : new Set();
1039
- out[tool_dir] = rules.filter((r) => !skip.has(r));
981
+ const skip = dedup_on
982
+ ? dedupableRules({ toolDir: tool_dir, rules, userHome: user_home,
983
+ rulesSource: MODULE_STATE.RULES_SOURCE, announce: _print })
984
+ : new Set();
985
+ const kept = rules.filter((r) => !skip.has(r));
986
+ out[tool_dir] = partition_rules_for_dir(tool_dir, kept, user_home);
1040
987
  }
1041
988
  return out;
1042
989
  }
@@ -1143,7 +1090,10 @@ export function generate_rule_symlinks() {
1143
1090
  return total;
1144
1091
  }
1145
1092
  export function generate_windsurfrules() {
1146
- const rules = _scoped_rule_basenames();
1093
+ // Windsurf's LEGACY single-file surface — same host, so the same evidence, keyed
1094
+ // on `.windsurf/rules`. Without this line removing the per-run filter regressed
1095
+ // it 13 → 113: the per-run filter had been covering it by accident.
1096
+ const rules = partition_rules_for_dir('.windsurf/rules', _scoped_rule_basenames());
1147
1097
  const parts = ['# Auto-generated from dist/agent-src/rules/ — do not edit directly\n'];
1148
1098
  for (const rule of rules) {
1149
1099
  const p = path.join(MODULE_STATE.RULES_SOURCE, rule);
@@ -1298,12 +1248,16 @@ function _clean_modern_dir(target_dir, valid_names) {
1298
1248
  export function generate_cursor_mdc_rules() {
1299
1249
  const scope = _read_rule_workspaces();
1300
1250
  const pack_scope = _read_rule_packs();
1301
- const rules = _rglobSorted(MODULE_STATE.RULES_SOURCE, '*.md')
1251
+ let rules = _rglobSorted(MODULE_STATE.RULES_SOURCE, '*.md')
1302
1252
  .filter((p) => _isFile(p))
1303
1253
  .filter((p) => rule_in_scope(p, scope, pack_scope))
1304
1254
  // ADR-004 manual rules are reference-only — never auto-injected into a
1305
1255
  // per-tool tree. Same predicate as generate_rule_symlinks.
1306
1256
  .filter((p) => !_is_manual_rule(p));
1257
+ // ADR-236 per-host partition (src/install/ruleLayerPartition.ts). Narrowing the
1258
+ // list is a REMOVAL, because `_clean_modern_dir` below sweeps to `valid`.
1259
+ const kept = new Set(partition_rules_for_dir('.cursor/rules', rules.map((r) => path.basename(r))));
1260
+ rules = rules.filter((r) => kept.has(path.basename(r)));
1307
1261
  const stems = rules.map((r) => path.basename(r, '.md'));
1308
1262
  const valid = new Set([
1309
1263
  ...stems.map((s) => `${s}.mdc`),
@@ -1319,12 +1273,15 @@ export function generate_cursor_mdc_rules() {
1319
1273
  export function generate_windsurf_modern_rules() {
1320
1274
  const scope = _read_rule_workspaces();
1321
1275
  const pack_scope = _read_rule_packs();
1322
- const rules = _rglobSorted(MODULE_STATE.RULES_SOURCE, '*.md')
1276
+ let rules = _rglobSorted(MODULE_STATE.RULES_SOURCE, '*.md')
1323
1277
  .filter((p) => _isFile(p))
1324
1278
  .filter((p) => rule_in_scope(p, scope, pack_scope))
1325
1279
  // ADR-004 manual rules are reference-only — never auto-injected into a
1326
1280
  // per-tool tree. Same predicate as generate_rule_symlinks.
1327
1281
  .filter((p) => !_is_manual_rule(p));
1282
+ // ADR-236 per-host partition — same shape as the cursor emitter above.
1283
+ const kept = new Set(partition_rules_for_dir('.windsurf/rules', rules.map((r) => path.basename(r))));
1284
+ rules = rules.filter((r) => kept.has(path.basename(r)));
1328
1285
  const valid = new Set(rules.map((r) => path.basename(r)));
1329
1286
  _clean_modern_dir(_WINDSURF_RULES_DIR(), valid);
1330
1287
  for (const rule of rules) {
@@ -1599,23 +1556,24 @@ function _nested_command_subpath(source_file) {
1599
1556
  /**
1600
1557
  * Project-scope `.claude/commands/<cluster>/<sub>.md` — the colon form.
1601
1558
  *
1602
- * Before this, the package repo's own `.claude/` carried NO commands
1603
- * directory: every command reached Claude Code as a hyphen-named skill
1604
- * wrapper in `.claude/skills/`, while the colon form existed only in the
1605
- * user-global tree written by `install.ts`. Every clustered command was
1606
- * therefore listed TWICE for anyone with a global install
1607
- * (`roadmap-process-full` AND `roadmap:process-full`), costing 4,214 GPT tok
1608
- * of always-loaded catalog for zero added reach — measured 2026-08-02.
1559
+ * Before this, the package repo's own `.claude/` carried NO commands directory:
1560
+ * every command reached Claude Code as a hyphen-named skill wrapper in
1561
+ * `.claude/skills/`, while the colon form existed only in the user-global tree
1562
+ * written by `install.ts`. Every clustered command was therefore listed TWICE
1563
+ * for anyone with a global install (`roadmap-process-full` AND
1564
+ * `roadmap:process-full`), costing 4,214 GPT tok of catalog — measured 2026-08-02.
1609
1565
  *
1610
1566
  * Emitting the nested form here lets `generate_claude_commands` stop wrapping
1611
1567
  * the clustered commands: one listing, same reachability, and reachability no
1612
- * longer depends on a global deploy having run. Claude Code dedupes project
1613
- * and user scope by name, so the two copies of `/cluster:sub` collapse.
1568
+ * longer depends on a global deploy. Dedup AND precedence: `commandsWithheld`.
1614
1569
  *
1615
1570
  * ADR-003 (colon canonical for clusters) and ADR-044 (flat commands stay
1616
1571
  * hyphenated) both hold: flat commands are untouched and keep their wrapper.
1617
1572
  */
1618
1573
  export function generate_claude_project_commands(active_command_slugs = null) {
1574
+ if (commandsWithheld(MODULE_STATE.PROJECT_ROOT))
1575
+ active_command_slugs = new Set();
1576
+ // Returns before the stale sweep — invariant, see `commandsWithheld`.
1619
1577
  if (!_isDir(path.join(MODULE_STATE.PROJECT_ROOT, 'src', 'domains'))) {
1620
1578
  return 0;
1621
1579
  }
@@ -1631,8 +1589,7 @@ export function generate_claude_project_commands(active_command_slugs = null) {
1631
1589
  }
1632
1590
  const target_root = _CLAUDE_COMMANDS_DIR();
1633
1591
  const valid = new Set(nested.map(([, sub]) => `${sub}.md`));
1634
- // Sweep stale links first: a renamed or deleted command must not linger as
1635
- // a dangling `/cluster:sub`.
1592
+ // Sweep stale links first — a renamed, deleted or WITHHELD command must not linger.
1636
1593
  if (_exists(target_root)) {
1637
1594
  for (const item of _rglobSorted(target_root, '*.md')) {
1638
1595
  const rel = _relativeToPosix(item, target_root);
@@ -1640,6 +1597,7 @@ export function generate_claude_project_commands(active_command_slugs = null) {
1640
1597
  fs.unlinkSync(item);
1641
1598
  }
1642
1599
  }
1600
+ pruneEmptyDirs(target_root); // else the gate counts 40 empty cluster dirs as 40 commands
1643
1601
  }
1644
1602
  let count = 0;
1645
1603
  for (const [source_file, sub] of nested) {
@@ -2077,7 +2035,7 @@ export function generate_persona_symlinks() {
2077
2035
  .map((p) => path.basename(p))
2078
2036
  .sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));
2079
2037
  void personas;
2080
- const list = direct;
2038
+ const partition = personaPartition(MODULE_STATE.PROJECT_ROOT, direct);
2081
2039
  const tool_dirs = _filter_tool_dirs(PERSONA_TOOL_DIRS);
2082
2040
  let total = 0;
2083
2041
  for (const [tool_dir, rel_prefix] of Object.entries(tool_dirs)) {
@@ -2085,11 +2043,11 @@ export function generate_persona_symlinks() {
2085
2043
  _mkdirp(target_dir);
2086
2044
  for (const item of _iterdirSorted(target_dir)) {
2087
2045
  const name = path.basename(item);
2088
- if (_isSymlink(item) && !list.includes(name) && name !== 'README.md') {
2046
+ if (_isSymlink(item) && !partition.listFor(tool_dir).includes(name) && name !== 'README.md') {
2089
2047
  fs.unlinkSync(item);
2090
2048
  }
2091
2049
  }
2092
- for (const persona of list) {
2050
+ for (const persona of partition.listFor(tool_dir)) {
2093
2051
  const link = path.join(target_dir, persona);
2094
2052
  const target = path.join(rel_prefix, persona);
2095
2053
  if (_existsOrSymlink(link)) {
@@ -2099,7 +2057,8 @@ export function generate_persona_symlinks() {
2099
2057
  total += 1;
2100
2058
  }
2101
2059
  }
2102
- info(` ✅ Created ${total} persona symlinks across ${Object.keys(tool_dirs).length} tool directories (${list.length} personas each)`);
2060
+ const per_dir = Object.keys(tool_dirs).map((d) => `${d}=${partition.countFor(d)}`);
2061
+ info(` ✅ Created ${total} persona symlinks — ${per_dir.join(' · ')}${partition.note}`);
2103
2062
  return total;
2104
2063
  }
2105
2064
  export function generate_user_type_symlinks() {
@@ -2272,10 +2231,14 @@ export function project_to_augment() {
2272
2231
  const current = new Set();
2273
2232
  let written = 0;
2274
2233
  if (_exists(src_rules)) {
2275
- const rules = _iterdirSorted(src_rules)
2234
+ // ADR-236 per-host partition, ahead of the `use_symlinks` branch so both
2235
+ // writers narrow; the `existing` minus `current` sweep below makes it a
2236
+ // removal. This emitter never had the scope or ADR-004 manual filters
2237
+ // either — why its count is 15 and the symlink trees' 13. Pre-existing.
2238
+ const rules = partition_rules_for_dir('.augment/rules', _iterdirSorted(src_rules)
2276
2239
  .filter((p) => p.endsWith('.md') && _isFile(p))
2277
2240
  .map((p) => path.basename(p))
2278
- .sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));
2241
+ .sort((a, b) => (a < b ? -1 : a > b ? 1 : 0)));
2279
2242
  for (const rule of rules) {
2280
2243
  const target = path.join(dst_rules, rule);
2281
2244
  if (_isSymlink(target) || _existsOrSymlink(target)) {