@event4u/agent-config 14.7.0 → 14.8.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 (138) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +245 -388
  3. package/README.md +1 -1
  4. package/dist/agent-src/commands/evals/git-pr-merge.json +13 -0
  5. package/dist/agent-src/commands/evals/roadmap.json +17 -1
  6. package/dist/agent-src/commands/pr/create.md +14 -2
  7. package/dist/agent-src/commands/pr/merge.md +379 -0
  8. package/dist/agent-src/commands/roadmap/process-full.md +157 -3
  9. package/dist/agent-src/commands/roadmap.md +1 -1
  10. package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +46 -36
  11. package/dist/agent-src/contexts/execution/autonomy-mechanics.md +37 -2
  12. package/dist/agent-src/contexts/execution/roadmap-execution-contract.md +64 -2
  13. package/dist/agent-src/contexts/execution/roadmap-process-loop.md +154 -2
  14. package/dist/agent-src/rules/artifact-drafting-protocol.md +5 -1
  15. package/dist/agent-src/rules/decision-revisit-gate.md +65 -33
  16. package/dist/agent-src/rules/recurring-criticism.md +1 -1
  17. package/dist/agent-src/rules/roadmap-progress-sync.md +19 -0
  18. package/dist/agent-src/rules/source-confidentiality.md +1 -1
  19. package/dist/agent-src/scripts/archive_completed_roadmaps.ts +7 -4
  20. package/dist/agent-src/scripts/dashboard_mode.ts +212 -0
  21. package/dist/agent-src/scripts/update_roadmap_progress.ts +47 -48
  22. package/dist/agent-src/skills/adr-create/SKILL.md +124 -5
  23. package/dist/agent-src/skills/decision-record/SKILL.md +61 -3
  24. package/dist/agent-src/skills/decision-review/SKILL.md +65 -0
  25. package/dist/agent-src/skills/merge-conflicts/SKILL.md +26 -0
  26. package/dist/agent-src/skills/security/SKILL.md +8 -0
  27. package/dist/agent-src/skills/security-audit/SKILL.md +12 -1
  28. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  29. package/dist/agent-src/templates/roadmaps.md +20 -2
  30. package/dist/cli/registry.js +1 -0
  31. package/dist/cli/registry.js.map +1 -1
  32. package/dist/cli-delegate/{chunk-JZ4NR2TW.js → chunk-7PRE6ZV2.js} +1 -1
  33. package/dist/cli-delegate/{chunk-7F3VYSM2.js → chunk-EEJUMCDZ.js} +14 -14
  34. package/dist/cli-delegate/{chunk-74E3TKWV.js → chunk-H4VIVD4C.js} +5 -5
  35. package/dist/cli-delegate/chunk-I3EIN2YG.js +36 -0
  36. package/dist/cli-delegate/{chunk-4VR4ORQ6.js → chunk-LPPWO5CE.js} +4 -3
  37. package/dist/cli-delegate/{chunk-UEZ7D35A.js → chunk-N7CDDGI3.js} +4 -23
  38. package/dist/cli-delegate/cmd_adr_effective.js +1162 -0
  39. package/dist/cli-delegate/cmd_conformance.js +14 -14
  40. package/dist/cli-delegate/cmd_converge.js +3 -3
  41. package/dist/cli-delegate/cmd_doctor.js +7 -7
  42. package/dist/cli-delegate/cmd_export.js +6 -6
  43. package/dist/cli-delegate/cmd_handoff.js +7 -6
  44. package/dist/cli-delegate/cmd_memory_get.js +2 -1
  45. package/dist/cli-delegate/cmd_migrate.js +2 -2
  46. package/dist/cli-delegate/cmd_preflight.js +5 -5
  47. package/dist/cli-delegate/cmd_prune.js +6 -6
  48. package/dist/cli-delegate/cmd_route_audit.js +6 -5
  49. package/dist/cli-delegate/cmd_route_explain.js +3 -3
  50. package/dist/cli-delegate/cmd_session_recycle.js +3 -3
  51. package/dist/cli-delegate/cmd_settings_get.js +3 -3
  52. package/dist/cli-delegate/cmd_settings_migrate.js +6 -6
  53. package/dist/cli-delegate/cmd_sync.js +6 -6
  54. package/dist/cli-delegate/cmd_uninstall.js +6 -6
  55. package/dist/cli-delegate/cmd_update.js +3 -3
  56. package/dist/cli-delegate/cmd_upgrade.js +3 -3
  57. package/dist/cli-delegate/cmd_validate.js +6 -6
  58. package/dist/cli-delegate/cmd_versions.js +3 -3
  59. package/dist/discovery/deprecation-report.md +1 -1
  60. package/dist/discovery/discovery-manifest.json +53 -22
  61. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  62. package/dist/discovery/discovery-manifest.summary.md +3 -3
  63. package/dist/discovery/dormancy-report.md +1 -1
  64. package/dist/discovery/orphan-report.md +1 -1
  65. package/dist/discovery/packs.json +7 -6
  66. package/dist/discovery/trust-report.md +2 -2
  67. package/dist/discovery/workspaces.json +6 -5
  68. package/dist/hooks/dispatch.js +806 -681
  69. package/dist/install/globalRuleLayers.js +169 -0
  70. package/dist/install/globalRuleLayers.js.map +1 -0
  71. package/dist/install/partitionEligibility.js +156 -0
  72. package/dist/install/partitionEligibility.js.map +1 -1
  73. package/dist/install/ruleLayerPartition.js +157 -0
  74. package/dist/install/ruleLayerPartition.js.map +1 -0
  75. package/dist/mcp/registry-manifest.json +3 -3
  76. package/dist/mcp/server.json +2 -2
  77. package/dist/mcp/server.mjs +654 -578
  78. package/dist/scripts/_lib/prune_empty_dirs.js +85 -0
  79. package/dist/scripts/_lib/prune_empty_dirs.js.map +1 -0
  80. package/dist/scripts/condense.js +52 -89
  81. package/dist/scripts/condense.js.map +1 -1
  82. package/docs/guidelines/agent-infra/artifact-drafting-protocol-mechanics.md +45 -1
  83. package/docs/guidelines/agent-infra/false-green.md +47 -1
  84. package/package.json +1 -1
  85. package/src/agent-src/scripts/archive_completed_roadmaps.ts +7 -4
  86. package/src/agent-src/scripts/dashboard_mode.ts +212 -0
  87. package/src/agent-src/scripts/update_roadmap_progress.ts +47 -48
  88. package/src/config/ci-local-parity.yml +21 -0
  89. package/src/config/estate-count-budget.json +275 -2
  90. package/src/config/evaluator-budgets.json +3 -3
  91. package/src/config/gate-coverage.yml +220 -12
  92. package/src/config/gate-violation-baselines.json +73 -63
  93. package/src/config/gitignore-block.txt +15 -2
  94. package/src/config/hook-latency-budget.json +5 -0
  95. package/src/config/rule-stub-ceilings.json +17 -3
  96. package/src/install/globalRuleLayers.ts +197 -0
  97. package/src/install/partitionEligibility.ts +177 -0
  98. package/src/install/ruleLayerPartition.ts +212 -0
  99. package/src/scripts/_cli/cmd_adr_effective.ts +484 -0
  100. package/src/scripts/_dispatch.bash +11 -0
  101. package/src/scripts/_lib/adr_frontmatter.test.ts +365 -0
  102. package/src/scripts/_lib/adr_frontmatter.ts +459 -0
  103. package/src/scripts/_lib/envelope_grounding.ts +11 -1
  104. package/src/scripts/_lib/layer_overlap_notice.ts +11 -2
  105. package/src/scripts/_lib/prune_empty_dirs.ts +80 -0
  106. package/src/scripts/adr/evidence_census.ts +899 -0
  107. package/src/scripts/adr/regenerate_index.ts +12 -32
  108. package/src/scripts/adr_cite_check.ts +540 -39
  109. package/src/scripts/audit_adr_coverage.ts +103 -17
  110. package/src/scripts/bench_hook_latency.ts +204 -0
  111. package/src/scripts/build_archive_index.ts +34 -0
  112. package/src/scripts/check_adr_frontmatter.ts +574 -39
  113. package/src/scripts/check_hook_bundle_content.ts +219 -0
  114. package/src/scripts/check_new_adr_evidence.ts +529 -0
  115. package/src/scripts/check_references.ts +18 -0
  116. package/src/scripts/check_rule_layer_partition.ts +531 -0
  117. package/src/scripts/check_single_delivery.ts +137 -4
  118. package/src/scripts/check_standing_rule_delivery.ts +8 -2
  119. package/src/scripts/condense.ts +61 -91
  120. package/src/scripts/external_sources_denylist.json +4 -1
  121. package/src/scripts/hooks/block_unauthorized_git.ts +22 -2
  122. package/src/scripts/hooks/dispatch_hook.ts +154 -187
  123. package/src/scripts/hooks/dispatch_issues.ts +38 -19
  124. package/src/scripts/hooks/fallback_yaml.ts +66 -0
  125. package/src/scripts/hooks/host_semantics.ts +21 -0
  126. package/src/scripts/hooks/injection_budget.ts +13 -3
  127. package/src/scripts/hooks/py_json_dumps.ts +103 -0
  128. package/src/scripts/hooks/state_io.ts +88 -1
  129. package/src/scripts/hooks/stdin_failure_policy.ts +96 -0
  130. package/src/scripts/injection_scan_hook.ts +137 -5
  131. package/src/scripts/lint_hook_manifest.ts +49 -0
  132. package/src/scripts/lint_provenance_vocabulary.ts +472 -4
  133. package/src/scripts/routing_doctor.ts +5 -1
  134. package/src/scripts/sync_pr_branch.ts +163 -20
  135. package/dist/cli-delegate/{chunk-PPQO4NGR.js → chunk-6RJA2F5A.js} +3 -3
  136. package/dist/cli-delegate/{chunk-6EOCNQAM.js → chunk-E4XIZDIB.js} +0 -0
  137. package/dist/cli-delegate/{chunk-FBKL6JWT.js → chunk-MMSGVZKV.js} +3 -3
  138. package/dist/cli-delegate/{chunk-GJ5BVHXM.js → chunk-PMEKGDED.js} +3 -3
@@ -21,6 +21,11 @@
21
21
  * do not hand-merge) versus authored (a human decision). Auto-resolving a
22
22
  * content conflict is how a parallel session's work disappears.
23
23
  *
24
+ * Classification changes the ADVICE, not the conflict. A path stays a hotspot by
25
+ * frequency while becoming mechanical to resolve, so a class added here is never
26
+ * conflict-count reduction and must not be banked as drawdown (AI council
27
+ * 2026-08-21, both seats; roadmap road-to-merge-hotspot-drawdown).
28
+ *
24
29
  * Exit codes: 0 = already current, or merged cleanly · 1 = conflict, or the base
25
30
  * could not be resolved · 2 = internal error. `scanned:` on every path.
26
31
  */
@@ -35,10 +40,32 @@ const NETWORK_TIMEOUT_MS = 8_000;
35
40
 
36
41
  /** Paths that are GENERATED — a conflict here is regenerated, never hand-merged. */
37
42
  const GENERATED = [
43
+ // Untracked in THIS repository since 2026-08-21 (it was the #1 conflict
44
+ // path: 830 commits/60d, in the conflict set of every open CONFLICTING PR).
45
+ // The entry STAYS anyway, and the retirement criterion is a declared window
46
+ // rather than "one release" — the AI council flagged the release count as
47
+ // arbitrary and unverifiable. Remove this entry once no open branch predates
48
+ // the untrack commit, which is checkable:
49
+ //
50
+ // git branch -r --contains <untrack-commit> # must list every open branch
51
+ //
52
+ // Until then a straggler branch created before the untrack still carries the
53
+ // tracked file, and a conflict on it is still resolved by regeneration.
38
54
  'agents/roadmaps-progress.md',
39
55
  'agents/index.md',
40
56
  'docs/catalog.md',
41
57
  'dist/agent-src/',
58
+ // Written by `src/scripts/adr/regenerate_index.ts`, which takes the decisions
59
+ // directory as an ARGUMENT — so the path literal appears nowhere in the
60
+ // generator and every grep-based audit of this list missed it. Found instead
61
+ // by measurement: 4 of the last 50 sessions resolved a conflict here, and
62
+ // its only correct resolution is `task regenerate-adr-index`, never a hunk
63
+ // merge of two append-shaped indexes.
64
+ 'docs/decisions/INDEX.md',
65
+ // Compiled by `compile_router.ts`. The `dist/agent-src/` prefix above does
66
+ // NOT match a sibling one level up under `dist/`, so this file was routed to
67
+ // a human decision despite being pure build output.
68
+ 'dist/router.json',
42
69
  '.augment/',
43
70
  // Compiled from `hook_manifest.yaml` by `task build-ts`, never hand-written.
44
71
  // It was classified AUTHORED until 2026-08-20, so this tool told the reader
@@ -47,6 +74,44 @@ const GENERATED = [
47
74
  // times and named it structural: main adds a concern and recompiles, so
48
75
  // every open branch collides here. Regenerate; never merge.
49
76
  'src/scripts/hook_manifest.json',
77
+ // Written together by one `build_archive_index.ts` call (`:409-410`) from the
78
+ // archived roadmap tree, so neither is ever hand-authored. They were
79
+ // classified AUTHORED until 2026-08-21, which made this tool ask for a human
80
+ // decision about a file whose only correct resolution is regeneration --
81
+ // the identical defect the hook_manifest.json comment above records, on two
82
+ // more paths at 47 commits/60d each. They conflict in 2 of the 7 open PRs
83
+ // measured for road-to-merge-hotspot-drawdown. Regenerate; never merge.
84
+ 'agents/roadmaps/archive/INDEX.md',
85
+ 'agents/roadmaps/archive/index.json',
86
+ ];
87
+
88
+ /**
89
+ * Paths that are MEASURED BASELINES -- a conflict here is neither regenerated
90
+ * nor hand-merged. It is RE-MEASURED on the merged tree, and the number that
91
+ * measurement produces is the resolution.
92
+ *
93
+ * Why this is a third class and not a variant of GENERATED: a generated file has
94
+ * one correct content given the tree, so "regenerate" is a complete instruction.
95
+ * A ratchet baseline records what a tree MEASURED at a point in time, and two
96
+ * branches legitimately measured two different trees -- so there is no side to
97
+ * take and no file to re-render. Picking a side on a ratchet number is how the
98
+ * ratchet silently loosens, and mixing hunks yields a baseline matching neither
99
+ * branch.
100
+ *
101
+ * Why this tool never performs the re-measurement itself (AI council 2026-08-21,
102
+ * both seats): "re-measure instead of merge" delegates conflict resolution to a
103
+ * script and its execution environment, and a wrong or environment-dependent
104
+ * measurement would overwrite a deliberate tightening with nothing objecting,
105
+ * because the result looks measured either way. So this class NAMES the
106
+ * resolution and stops. The human runs it, with the result in front of them.
107
+ *
108
+ * Both members conflict in 7 of the 7 open PRs measured for
109
+ * road-to-merge-hotspot-drawdown. Neither is gitignorable: an untracked baseline
110
+ * is a baseline no PR diff can be compared against, which deletes the ratchet.
111
+ */
112
+ const REMEASURED = [
113
+ 'src/config/estate-count-budget.json',
114
+ 'src/config/gate-violation-baselines.json',
50
115
  ];
51
116
 
52
117
  function sh(cmd: string, args: readonly string[], cwd: string): { ok: boolean; out: string; err: string } {
@@ -60,17 +125,59 @@ function sh(cmd: string, args: readonly string[], cwd: string): { ok: boolean; o
60
125
  }
61
126
 
62
127
  /** True when `rel` is a generated artefact rather than an authored one. */
128
+ /**
129
+ * The subset of GENERATED that this repository no longer commits at all
130
+ * (`road-to-generated-artifacts-out-of-index`, 2026-08-22). They are still
131
+ * generated, so they stay in `GENERATED` and keep being reported — a straggler
132
+ * branch created before the untrack still carries them, which is exactly when
133
+ * the reader needs to be told something.
134
+ *
135
+ * What changes is the INSTRUCTION. A branch that predates the cutover hits a
136
+ * `modify/delete` conflict here, not a content conflict, and `git checkout
137
+ * --ours` has no side to check out: the correct resolution is to take the
138
+ * deletion. Printing the generic advice would send the reader to re-add the
139
+ * file, which is precisely how PR #1505 put the dashboard back on `main` a day
140
+ * after it was first untracked.
141
+ */
142
+ const UNTRACKED_BY_DESIGN: readonly string[] = [
143
+ 'agents/roadmaps-progress.md',
144
+ 'agents/roadmaps/archive/INDEX.md',
145
+ 'agents/roadmaps/archive/index.json',
146
+ ];
147
+
148
+ /** Is this a generated path this repository deliberately does not commit? */
149
+ export function isUntrackedByDesign(rel: string): boolean {
150
+ return UNTRACKED_BY_DESIGN.includes(rel);
151
+ }
152
+
63
153
  export function isGenerated(rel: string): boolean {
64
154
  const norm = rel.replace(/\\/g, '/');
65
155
  return GENERATED.some((g) => (g.endsWith('/') ? norm.startsWith(g) : norm === g));
66
156
  }
67
157
 
158
+ /**
159
+ * True when `rel` is listed as a measured ratchet baseline.
160
+ *
161
+ * This does NOT assert exclusivity against `GENERATED` — it only reads its own
162
+ * array. `classifyConflicts` establishes the precedence (generated first), so a
163
+ * path added to both arrays would route as generated while this predicate also
164
+ * returned true, and no test would catch it. Keep the arrays disjoint; the
165
+ * per-path exclusivity assertions in the test file cover today's two members
166
+ * only.
167
+ */
168
+ export function isRemeasured(rel: string): boolean {
169
+ const norm = rel.replace(/\\/g, '/');
170
+ return REMEASURED.some((g) => (g.endsWith('/') ? norm.startsWith(g) : norm === g));
171
+ }
172
+
68
173
  export interface Plan {
69
174
  /** 0 = nothing to do or merged · 1 = needs a human · 2 = internal. */
70
175
  exit: 0 | 1 | 2;
71
176
  message: string;
72
177
  /** Conflicted paths, split so the caller knows which to regenerate. */
73
178
  generated: string[];
179
+ /** Conflicted measured baselines — re-measure on the merged tree, never merge. */
180
+ remeasured: string[];
74
181
  authored: string[];
75
182
  scanned: number;
76
183
  }
@@ -82,14 +189,57 @@ export interface Plan {
82
189
  * the split is the useful part: a generated conflict has one correct resolution
83
190
  * (regenerate) and an authored one has none that a script may choose.
84
191
  */
85
- export function classifyConflicts(files: readonly string[]): Pick<Plan, 'generated' | 'authored'> {
192
+ export function classifyConflicts(files: readonly string[]): Pick<Plan, 'generated' | 'remeasured' | 'authored'> {
86
193
  const generated: string[] = [];
194
+ const remeasured: string[] = [];
87
195
  const authored: string[] = [];
88
196
  for (const f of files) {
89
- if (f.trim() === '') continue;
90
- (isGenerated(f.trim()) ? generated : authored).push(f.trim());
197
+ const rel = f.trim();
198
+ if (rel === '') continue;
199
+ if (isGenerated(rel)) generated.push(rel);
200
+ else if (isRemeasured(rel)) remeasured.push(rel);
201
+ else authored.push(rel);
91
202
  }
92
- return { generated, authored };
203
+ return { generated, remeasured, authored };
204
+ }
205
+
206
+ /**
207
+ * Render the conflict report for a plan that needs a human.
208
+ *
209
+ * Pure and exported so the WORDING is testable without producing a real merge
210
+ * conflict. That matters more than it looks: the per-class instruction is the
211
+ * entire value of the classification, and while this lived inline in `main()`
212
+ * the whole block could be deleted and every test stayed green — the header
213
+ * still counted the conflict, and the paths went unnamed with no instruction.
214
+ */
215
+ export function renderConflictReport(plan: Plan): string {
216
+ const out: string[] = [`❌ ${plan.message}\n`];
217
+ const untracked = plan.generated.filter(isUntrackedByDesign);
218
+ const regenerable = plan.generated.filter((f) => !isUntrackedByDesign(f));
219
+ if (regenerable.length > 0) {
220
+ out.push(`\n GENERATED (${String(regenerable.length)}) — resolve by REGENERATING, never by mixing hunks:\n`);
221
+ for (const f of regenerable) out.push(` · ${f}\n`);
222
+ out.push(' → git checkout --ours <file> && task sync && task generate-tools\n');
223
+ }
224
+ if (untracked.length > 0) {
225
+ out.push(
226
+ `\n UNTRACKED BY DESIGN (${String(untracked.length)}) — this repository does not commit these; TAKE THE DELETION:\n`,
227
+ );
228
+ for (const f of untracked) out.push(` · ${f}\n`);
229
+ out.push(' → git rm --cached -- <file> (the working-tree copy stays; regenerate it locally)\n');
230
+ }
231
+ if (plan.remeasured.length > 0) {
232
+ out.push(
233
+ `\n REMEASURED (${String(plan.remeasured.length)}) — RE-RUN THE MEASUREMENT on the merged tree; never merge, never pick a side:\n`,
234
+ );
235
+ for (const f of plan.remeasured) out.push(` · ${f}\n`);
236
+ out.push(' → resolve the tree, then re-run the gate that owns the baseline and record its number\n');
237
+ }
238
+ if (plan.authored.length > 0) {
239
+ out.push(`\n AUTHORED (${String(plan.authored.length)}) — a human decision, read both sides:\n`);
240
+ for (const f of plan.authored) out.push(` · ${f}\n`);
241
+ }
242
+ return out.join('');
93
243
  }
94
244
 
95
245
  /** Resolve the base this branch will actually merge into. */
@@ -125,7 +275,7 @@ export function resolveBase(repo: string, override: string | null): { base: stri
125
275
  export function sync(repo: string, baseOverride: string | null, dryRun: boolean): Plan {
126
276
  const { base, how } = resolveBase(repo, baseOverride);
127
277
  if (base === null) {
128
- return { exit: 1, message: `cannot resolve a base to update against — ${how}.`, generated: [], authored: [], scanned: 0 };
278
+ return { exit: 1, message: `cannot resolve a base to update against — ${how}.`, generated: [], remeasured: [], authored: [], scanned: 0 };
129
279
  }
130
280
 
131
281
  const fetched = sh('git', ['fetch', 'origin', '--prune'], repo);
@@ -136,6 +286,7 @@ export function sync(repo: string, baseOverride: string | null, dryRun: boolean)
136
286
  exit: 0,
137
287
  message: `unverified — could not fetch origin (${fetched.err.split('\n')[0] ?? '?'}). Base freshness NOT checked.`,
138
288
  generated: [],
289
+ remeasured: [],
139
290
  authored: [],
140
291
  scanned: 0,
141
292
  };
@@ -143,13 +294,14 @@ export function sync(repo: string, baseOverride: string | null, dryRun: boolean)
143
294
 
144
295
  const behind = sh('git', ['rev-list', '--count', `HEAD..${base}`], repo).out.trim();
145
296
  if (behind === '' || behind === '0') {
146
- return { exit: 0, message: `already current with ${base} (${how}).`, generated: [], authored: [], scanned: 1 };
297
+ return { exit: 0, message: `already current with ${base} (${how}).`, generated: [], remeasured: [], authored: [], scanned: 1 };
147
298
  }
148
299
  if (dryRun) {
149
300
  return {
150
301
  exit: 0,
151
302
  message: `${behind} commit(s) behind ${base} (${how}) — would merge it in. Dry run, nothing changed.`,
152
303
  generated: [],
304
+ remeasured: [],
153
305
  authored: [],
154
306
  scanned: 1,
155
307
  };
@@ -163,6 +315,7 @@ export function sync(repo: string, baseOverride: string | null, dryRun: boolean)
163
315
  `merged ${base} in (${how}, was ${behind} behind). REGENERATE derived files now — a clean ` +
164
316
  'auto-merge of a generated file is still wrong.',
165
317
  generated: [],
318
+ remeasured: [],
166
319
  authored: [],
167
320
  scanned: 1,
168
321
  };
@@ -173,7 +326,7 @@ export function sync(repo: string, baseOverride: string | null, dryRun: boolean)
173
326
  return {
174
327
  exit: 1,
175
328
  message:
176
- `merge of ${base} (${how}) hit ${String(split.generated.length + split.authored.length)} conflict(s). ` +
329
+ `merge of ${base} (${how}) hit ${String(split.generated.length + split.remeasured.length + split.authored.length)} conflict(s). ` +
177
330
  'NOT auto-resolved: a content conflict is where a parallel session\'s work disappears.',
178
331
  ...split,
179
332
  scanned: 1,
@@ -218,7 +371,8 @@ export function main(argv?: readonly string[]): number {
218
371
  ' Merges the PR base into the current branch so the PR does not go stale.\n' +
219
372
  ' Resolves the base from the open PR when there is one. A conflict is\n' +
220
373
  ' reported and never auto-resolved; generated and authored conflicts are\n' +
221
- ' listed separately because only the first has one correct resolution.\n',
374
+ ' listed separately because only the first has one correct resolution;\n' +
375
+ ' measured ratchet baselines are a third class, re-measured not merged.\n',
222
376
  );
223
377
  reportScanned({ gate: 'sync_pr_branch', scanned: 0, units: 'base ref(s)', roots: ['origin'], allowEmpty: 'help output' });
224
378
  return 0;
@@ -239,18 +393,7 @@ export function main(argv?: readonly string[]): number {
239
393
  }
240
394
 
241
395
  if (plan.exit === 1) {
242
- process.stdout.write(`❌ ${plan.message}\n`);
243
- if (plan.generated.length > 0) {
244
- process.stdout.write(
245
- `\n GENERATED (${String(plan.generated.length)}) — resolve by REGENERATING, never by mixing hunks:\n`,
246
- );
247
- for (const f of plan.generated) process.stdout.write(` · ${f}\n`);
248
- process.stdout.write(' → git checkout --ours <file> && task sync && task generate-tools\n');
249
- }
250
- if (plan.authored.length > 0) {
251
- process.stdout.write(`\n AUTHORED (${String(plan.authored.length)}) — a human decision, read both sides:\n`);
252
- for (const f of plan.authored) process.stdout.write(` · ${f}\n`);
253
- }
396
+ process.stdout.write(renderConflictReport(plan));
254
397
  } else if (plan.message.startsWith('unverified')) {
255
398
  // Loud even under --quiet: unverified reported silently is
256
399
  // indistinguishable from verified, which is the defect being closed.
@@ -1,10 +1,10 @@
1
1
  import { createRequire as __acCreateRequire } from 'node:module'; const require = globalThis.require ?? __acCreateRequire(import.meta.url);
2
- import {
3
- resolve_project_root
4
- } from "./chunk-NLP54U3J.js";
5
2
  import {
6
3
  resolvePackageRoot
7
4
  } from "./chunk-MCJYCQPF.js";
5
+ import {
6
+ resolve_project_root
7
+ } from "./chunk-NLP54U3J.js";
8
8
 
9
9
  // src/scripts/_cli/cmd_migrate.ts
10
10
  import { spawnSync } from "node:child_process";
@@ -1,4 +1,7 @@
1
1
  import { createRequire as __acCreateRequire } from 'node:module'; const require = globalThis.require ?? __acCreateRequire(import.meta.url);
2
+ import {
3
+ require_dist
4
+ } from "./chunk-OY53J6II.js";
2
5
  import {
3
6
  load_agent_settings
4
7
  } from "./chunk-NLP54U3J.js";
@@ -6,9 +9,6 @@ import {
6
9
  resolve_with_fallback,
7
10
  write_target
8
11
  } from "./chunk-NDJLNC6Q.js";
9
- import {
10
- require_dist
11
- } from "./chunk-OY53J6II.js";
12
12
  import {
13
13
  __export,
14
14
  __toESM
@@ -2,12 +2,12 @@ import { createRequire as __acCreateRequire } from 'node:module'; const require
2
2
  import {
3
3
  write_atomic
4
4
  } from "./chunk-MWRD5YOH.js";
5
- import {
6
- write_target
7
- } from "./chunk-NDJLNC6Q.js";
8
5
  import {
9
6
  require_dist
10
7
  } from "./chunk-OY53J6II.js";
8
+ import {
9
+ write_target
10
+ } from "./chunk-NDJLNC6Q.js";
11
11
  import {
12
12
  __export,
13
13
  __toESM