@open-agent-toolkit/cli 0.3.7 → 0.3.9

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 (147) hide show
  1. package/README.md +3 -3
  2. package/assets/agents/oat-codebase-mapper.md +3 -2
  3. package/assets/agents/oat-reviewer.md +5 -13
  4. package/assets/agents/skeptical-evaluator.md +6 -2
  5. package/assets/bundle-metadata.json +1 -1
  6. package/assets/docs/cli-utilities/backlog-lifecycle.md +3 -2
  7. package/assets/docs/cli-utilities/bootstrap.md +5 -2
  8. package/assets/docs/cli-utilities/config-and-local-state.md +13 -6
  9. package/assets/docs/cli-utilities/configuration.md +25 -10
  10. package/assets/docs/cli-utilities/tool-packs.md +60 -10
  11. package/assets/docs/cli-utilities/workflow-gates.md +37 -0
  12. package/assets/docs/contributing/code.md +9 -5
  13. package/assets/docs/provider-sync/commands.md +17 -8
  14. package/assets/docs/provider-sync/instruction-sync.md +241 -39
  15. package/assets/docs/provider-sync/providers.md +20 -0
  16. package/assets/docs/provider-sync/scope-and-surface.md +3 -1
  17. package/assets/docs/reference/cli-reference.md +4 -1
  18. package/assets/docs/reference/oat-directory-structure.md +12 -11
  19. package/assets/docs/reference/troubleshooting.md +19 -4
  20. package/assets/docs/workflows/projects/evidence-layers.md +5 -1
  21. package/assets/docs/workflows/projects/implementation-execution.md +22 -8
  22. package/assets/docs/workflows/projects/lifecycle.md +4 -6
  23. package/assets/docs/workflows/projects/retro.md +7 -0
  24. package/assets/public-package-versions.json +4 -4
  25. package/assets/skills/oat-agent-instructions-analyze/SKILL.md +4 -4
  26. package/assets/skills/oat-agent-instructions-analyze/references/analysis-artifact-template.md +5 -5
  27. package/assets/skills/oat-agent-instructions-analyze/references/docs/rules-files.md +14 -11
  28. package/assets/skills/oat-agent-instructions-analyze/references/quality-checklist.md +2 -2
  29. package/assets/skills/oat-agent-instructions-analyze/scripts/resolve-instruction-files.sh +4 -3
  30. package/assets/skills/oat-agent-instructions-analyze/scripts/resolve-providers.sh +17 -6
  31. package/assets/skills/oat-agent-instructions-apply/SKILL.md +3 -3
  32. package/assets/skills/oat-agent-instructions-apply/references/docs/rules-files.md +14 -11
  33. package/assets/skills/oat-dispatch-subagents/SKILL.md +1 -1
  34. package/assets/skills/oat-dispatch-subagents/references/managed-claude-example.json +387 -0
  35. package/assets/skills/oat-dispatch-subagents/references/record-schema.md +75 -0
  36. package/assets/skills/oat-doctor/SKILL.md +17 -13
  37. package/assets/skills/oat-project-autonomous/references/gate-inventory.md +1 -1
  38. package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +1 -1
  39. package/assets/skills/oat-project-implement/SKILL.md +2 -2
  40. package/assets/skills/oat-project-implement/references/completion-and-closeout.md +33 -11
  41. package/assets/skills/oat-project-implement/references/dispatch-and-dry-run.md +24 -22
  42. package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +1 -1
  43. package/assets/skills/oat-project-implement/references/phase-execution.md +109 -8
  44. package/assets/skills/oat-project-lite/SKILL.md +23 -1
  45. package/assets/skills/oat-project-lite/references/docs/autonomy-contract.md +1 -1
  46. package/assets/skills/oat-project-next/SKILL.md +3 -3
  47. package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +1 -1
  48. package/assets/skills/oat-project-progress/SKILL.md +2 -2
  49. package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +1 -1
  50. package/assets/skills/oat-project-retro/SKILL.md +70 -6
  51. package/assets/skills/oat-project-review-provide/SKILL.md +3 -1
  52. package/assets/skills/oat-project-review-provide-remote/SKILL.md +3 -1
  53. package/assets/templates/docs-app-mkdocs/docs/contributing.md +1 -3
  54. package/assets/templates/pjm-agents.md +7 -3
  55. package/assets/templates/state.md +2 -2
  56. package/dist/agents/canonical/resolve.d.ts +6 -4
  57. package/dist/agents/canonical/resolve.d.ts.map +1 -1
  58. package/dist/agents/canonical/resolve.js +6 -4
  59. package/dist/commands/backlog/archive.d.ts +10 -2
  60. package/dist/commands/backlog/archive.d.ts.map +1 -1
  61. package/dist/commands/backlog/archive.js +22 -6
  62. package/dist/commands/backlog/index.d.ts.map +1 -1
  63. package/dist/commands/backlog/index.js +5 -1
  64. package/dist/commands/backlog/rewrite-references.d.ts +41 -0
  65. package/dist/commands/backlog/rewrite-references.d.ts.map +1 -0
  66. package/dist/commands/backlog/rewrite-references.js +516 -0
  67. package/dist/commands/config/index.d.ts +1 -0
  68. package/dist/commands/config/index.d.ts.map +1 -1
  69. package/dist/commands/config/index.js +69 -34
  70. package/dist/commands/gate/index.d.ts.map +1 -1
  71. package/dist/commands/gate/index.js +51 -2
  72. package/dist/commands/gate/review-verdict.d.ts +22 -0
  73. package/dist/commands/gate/review-verdict.d.ts.map +1 -1
  74. package/dist/commands/gate/review-verdict.js +111 -0
  75. package/dist/commands/init/index.d.ts +6 -0
  76. package/dist/commands/init/index.d.ts.map +1 -1
  77. package/dist/commands/init/index.js +27 -4
  78. package/dist/commands/init/tools/index.d.ts +18 -1
  79. package/dist/commands/init/tools/index.d.ts.map +1 -1
  80. package/dist/commands/init/tools/index.js +84 -17
  81. package/dist/commands/init/tools/project-guidance.d.ts +19 -4
  82. package/dist/commands/init/tools/project-guidance.d.ts.map +1 -1
  83. package/dist/commands/init/tools/project-guidance.js +58 -15
  84. package/dist/commands/init/tools/workflows/index.d.ts.map +1 -1
  85. package/dist/commands/init/tools/workflows/index.js +5 -1
  86. package/dist/commands/instructions/instructions.types.d.ts +105 -4
  87. package/dist/commands/instructions/instructions.types.d.ts.map +1 -1
  88. package/dist/commands/instructions/instructions.types.js +4 -5
  89. package/dist/commands/instructions/instructions.utils.d.ts +161 -6
  90. package/dist/commands/instructions/instructions.utils.d.ts.map +1 -1
  91. package/dist/commands/instructions/instructions.utils.js +650 -12
  92. package/dist/commands/instructions/sync/sync.d.ts.map +1 -1
  93. package/dist/commands/instructions/sync/sync.js +256 -18
  94. package/dist/commands/instructions/validate/validate.d.ts.map +1 -1
  95. package/dist/commands/instructions/validate/validate.js +36 -8
  96. package/dist/commands/pjm/index.d.ts.map +1 -1
  97. package/dist/commands/pjm/index.js +19 -4
  98. package/dist/commands/pjm/init.d.ts +3 -0
  99. package/dist/commands/pjm/init.d.ts.map +1 -1
  100. package/dist/commands/pjm/init.js +23 -5
  101. package/dist/commands/project/dispatch/canonical-role.d.ts +33 -0
  102. package/dist/commands/project/dispatch/canonical-role.d.ts.map +1 -0
  103. package/dist/commands/project/dispatch/canonical-role.js +114 -0
  104. package/dist/commands/project/dispatch/index.d.ts.map +1 -1
  105. package/dist/commands/project/dispatch/index.js +3 -1
  106. package/dist/commands/project/dispatch/record.d.ts.map +1 -1
  107. package/dist/commands/project/dispatch/record.js +146 -4
  108. package/dist/commands/shared/agents-md.d.ts +26 -5
  109. package/dist/commands/shared/agents-md.d.ts.map +1 -1
  110. package/dist/commands/shared/agents-md.js +182 -3
  111. package/dist/commands/sync/apply.d.ts.map +1 -1
  112. package/dist/commands/sync/apply.js +28 -21
  113. package/dist/commands/tools/guidance/index.d.ts +15 -0
  114. package/dist/commands/tools/guidance/index.d.ts.map +1 -0
  115. package/dist/commands/tools/guidance/index.js +81 -0
  116. package/dist/commands/tools/index.d.ts.map +1 -1
  117. package/dist/commands/tools/index.js +2 -0
  118. package/dist/commands/tools/shared/sync-evidence.d.ts.map +1 -1
  119. package/dist/commands/tools/shared/sync-evidence.js +32 -5
  120. package/dist/config/oat-config.d.ts +57 -3
  121. package/dist/config/oat-config.d.ts.map +1 -1
  122. package/dist/config/oat-config.js +223 -15
  123. package/dist/config/resolve.d.ts.map +1 -1
  124. package/dist/config/resolve.js +12 -2
  125. package/dist/engine/compute-plan.d.ts.map +1 -1
  126. package/dist/engine/compute-plan.js +31 -3
  127. package/dist/providers/claude/dispatch-envelope.d.ts +53 -0
  128. package/dist/providers/claude/dispatch-envelope.d.ts.map +1 -1
  129. package/dist/providers/claude/dispatch-envelope.js +324 -48
  130. package/dist/providers/claude/rule-transform.js +1 -1
  131. package/dist/providers/copilot/rule-transform.js +1 -1
  132. package/dist/providers/cursor/rule-transform.js +1 -1
  133. package/dist/providers/identity/absolute-paths.d.ts +13 -0
  134. package/dist/providers/identity/absolute-paths.d.ts.map +1 -1
  135. package/dist/providers/identity/absolute-paths.js +27 -14
  136. package/dist/providers/identity/generic-dispatch-record.d.ts +212 -0
  137. package/dist/providers/identity/generic-dispatch-record.d.ts.map +1 -1
  138. package/dist/providers/identity/generic-dispatch-record.js +78 -19
  139. package/dist/providers/identity/oat-dispatch-record.d.ts +5 -0
  140. package/dist/providers/identity/oat-dispatch-record.d.ts.map +1 -1
  141. package/dist/providers/identity/oat-dispatch-record.js +11 -2
  142. package/dist/providers/shared/registry.d.ts +6 -0
  143. package/dist/providers/shared/registry.d.ts.map +1 -1
  144. package/dist/providers/shared/registry.js +30 -0
  145. package/dist/rules/canonical/parse.d.ts.map +1 -1
  146. package/dist/rules/canonical/parse.js +38 -3
  147. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../../../src/commands/instructions/sync/sync.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,EAAE,EAAsB,MAAM,kBAAkB,CAAC;AAI3E,OAAO,EAKL,KAAK,mCAAmC,EACzC,MAAM,2CAA2C,CAAC;AAanD,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAQ5C,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,MAAM,EACZ,MAAM,GAAE,OAAO,EAAO,GACrB,OAAO,CAAC,IAAI,CAAC,CAEf;AAgTD,wBAAgB,6BAA6B,CAC3C,SAAS,GAAE,OAAO,CAAC,mCAAmC,CAAM,GAC3D,OAAO,CAwGT"}
1
+ {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../../../src/commands/instructions/sync/sync.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,EAAE,EAGH,MAAM,kBAAkB,CAAC;AAI1B,OAAO,EAKL,KAAK,mCAAmC,EAEzC,MAAM,2CAA2C,CAAC;AAuBnD,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAQ5C,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,MAAM,EACZ,MAAM,GAAE,OAAO,EAAO,GACrB,OAAO,CAAC,IAAI,CAAC,CAEf;AAiiBD,wBAAgB,6BAA6B,CAC3C,SAAS,GAAE,OAAO,CAAC,mCAAmC,CAAM,GAC3D,OAAO,CAyLT"}
@@ -1,8 +1,8 @@
1
- import { lstat, readFile, rm, symlink, writeFile } from 'node:fs/promises';
1
+ import { lstat, readFile, readlink, realpath, rm, symlink, writeFile, } from 'node:fs/promises';
2
2
  import { dirname, join, relative } from 'node:path';
3
3
  import { buildCommandContext } from '../../../app/command-context.js';
4
4
  import { INSTRUCTION_SYNC_STRATEGIES, } from '../../instructions/instructions.types.js';
5
- import { buildInstructionsPayload, DEFAULT_INSTRUCTION_SYNC_STRATEGY, EXPECTED_CLAUDE_CONTENT, formatInstructionsReport, resolveInstructionPointerExcludes, resolveInstructionSyncStrategy, scanInstructionFiles, } from '../../instructions/instructions.utils.js';
5
+ import { buildInstructionsPayload, EXPECTED_CLAUDE_CONTENT, formatInstructionsReport, readConfiguredInstructionSyncStrategy, resolveInstructionPointerExcludes, resolveInstructionSyncStrategy, findLeftoverClaudeFiles, findLinksThrough, inspectManagedShim, buildLeftoverClaudeWarnings, buildShimRemovalBlockWarning, describeShimRemovalBlock, findShimRemovalBlockers, omitHeldBackLeftovers, markBlockedShimEntries, scanInstructionFiles, verifyManagedShimUnchanged, } from '../../instructions/instructions.utils.js';
6
6
  import { readGlobalOptions } from '../../shared/shared.utils.js';
7
7
  import { CliError } from '../../../errors/cli-error.js';
8
8
  import { resolveProjectRoot } from '../../../fs/paths.js';
@@ -13,8 +13,13 @@ export async function removeInstructionFile(path, remove = rm) {
13
13
  function defaultDependencies() {
14
14
  return {
15
15
  buildCommandContext,
16
+ findLeftoverClaudeFiles,
16
17
  lstat,
18
+ readConfiguredInstructionSyncStrategy,
17
19
  readFile,
20
+ readFileBytes: (path) => readFile(path),
21
+ readlink,
22
+ realpath,
18
23
  removeFile: removeInstructionFile,
19
24
  resolveInstructionPointerExcludes,
20
25
  resolveProjectRoot,
@@ -25,18 +30,28 @@ function defaultDependencies() {
25
30
  writeFile,
26
31
  };
27
32
  }
33
+ function getShimLabel(strategy) {
34
+ switch (strategy) {
35
+ case 'symlink':
36
+ return 'symlink';
37
+ case 'copy':
38
+ return 'hard copy';
39
+ case 'none':
40
+ return 'removal';
41
+ default:
42
+ return 'pointer file';
43
+ }
44
+ }
28
45
  function getSyncReason(actionType, strategy) {
29
- const label = strategy === 'symlink'
30
- ? 'symlink'
31
- : strategy === 'copy'
32
- ? 'hard copy'
33
- : 'pointer file';
46
+ const label = getShimLabel(strategy);
34
47
  return actionType === 'create'
35
48
  ? `missing CLAUDE.md ${label}`
36
49
  : `overwrite CLAUDE.md with canonical ${label}`;
37
50
  }
38
51
  function getSyncedDetail(strategy) {
39
52
  switch (strategy) {
53
+ case 'none':
54
+ return 'no CLAUDE.md';
40
55
  case 'symlink':
41
56
  return 'symlink synced';
42
57
  case 'copy':
@@ -69,7 +84,66 @@ function wrapStrayResyncError(error, agentsPath, claudePath) {
69
84
  const message = error instanceof Error ? error.message : String(error);
70
85
  return new CliError(`Adopted stray instructions into ${agentsPath}, but failed to regenerate ${claudePath}: ${message}`, error instanceof CliError ? error.exitCode : 2);
71
86
  }
87
+ /**
88
+ * Plan strategy `none`: remove exact managed shims, adopt strays into
89
+ * AGENTS.md without writing a shim back, and never write or overwrite a
90
+ * CLAUDE.md. `--force` has no effect here: nothing that is not an exact
91
+ * managed shape is ever deleted.
92
+ */
93
+ function planNoShimActions(entries) {
94
+ const actions = [];
95
+ for (const entry of entries) {
96
+ if (entry.status === 'managed_shim' && entry.managedShim) {
97
+ actions.push({
98
+ type: 'remove',
99
+ target: entry.claudePath,
100
+ reason: `remove OAT-managed CLAUDE.md ${getShimLabel(entry.managedShim.shape)} (strategy none)`,
101
+ result: 'planned',
102
+ });
103
+ continue;
104
+ }
105
+ // Adopt, then remove: leaving the lone CLAUDE.md in place would make
106
+ // Claude Code's `agents-md` plugin stand down for the whole project.
107
+ if (entry.status === 'stray') {
108
+ actions.push({
109
+ type: 'create',
110
+ target: getAgentsPath(entry),
111
+ reason: 'adopt stray CLAUDE.md into canonical AGENTS.md',
112
+ result: 'planned',
113
+ });
114
+ actions.push({
115
+ type: 'remove',
116
+ target: entry.claudePath,
117
+ reason: 'remove adopted stray CLAUDE.md (strategy none)',
118
+ result: 'planned',
119
+ });
120
+ continue;
121
+ }
122
+ if (entry.status !== 'content_mismatch') {
123
+ continue;
124
+ }
125
+ if (hasUnreadableCanonicalAgents(entry) && entry.agentsPath) {
126
+ actions.push({
127
+ type: 'skip',
128
+ target: entry.agentsPath,
129
+ reason: 'canonical AGENTS.md unreadable; repair manually',
130
+ result: 'skipped',
131
+ });
132
+ continue;
133
+ }
134
+ actions.push({
135
+ type: 'skip',
136
+ target: entry.claudePath,
137
+ reason: 'CLAUDE.md unreadable; repair manually',
138
+ result: 'skipped',
139
+ });
140
+ }
141
+ return actions;
142
+ }
72
143
  function planSyncActions({ entries, force, strategy, }) {
144
+ if (strategy === 'none') {
145
+ return planNoShimActions(entries);
146
+ }
73
147
  const actions = [];
74
148
  for (const entry of entries) {
75
149
  if (entry.status === 'stray') {
@@ -139,9 +213,13 @@ function planSyncActions({ entries, force, strategy, }) {
139
213
  }
140
214
  return actions;
141
215
  }
142
- async function applySyncActions(actions, entries, dependencies, strategy) {
216
+ async function applySyncActions(actions, entries, dependencies, strategy, repoRoot) {
143
217
  const appliedActions = [];
144
218
  const entriesByTarget = new Map();
219
+ // Under `none`, what each adopted stray CLAUDE.md looked like right after its
220
+ // content was copied into AGENTS.md: the record its removal re-verifies
221
+ // against, or the reason it must be kept.
222
+ const adoptedStrays = new Map();
145
223
  for (const entry of entries) {
146
224
  entriesByTarget.set(entry.claudePath, entry);
147
225
  entriesByTarget.set(getAgentsPath(entry), entry);
@@ -157,6 +235,59 @@ async function applySyncActions(actions, entries, dependencies, strategy) {
157
235
  }
158
236
  const agentsPath = getAgentsPath(entry);
159
237
  const isAgentsAction = action.target === agentsPath;
238
+ if (action.type === 'remove') {
239
+ const isStray = entry.status === 'stray';
240
+ const planned = isStray
241
+ ? adoptedStrays.get(action.target)
242
+ : entry.managedShim;
243
+ if (planned === undefined) {
244
+ throw new CliError(`No planning record for CLAUDE.md removal at ${action.target}`, 2);
245
+ }
246
+ // Fail closed at the last moment: the file may have been edited or
247
+ // replaced since it was classified. Anything but the exact shim that
248
+ // was recorded is kept and reported, never deleted.
249
+ const changed = typeof planned === 'string'
250
+ ? planned
251
+ : await verifyManagedShimUnchanged(action.target, agentsPath, planned, dependencies);
252
+ // Also re-check, just as late, that no scanned instruction file has
253
+ // become a link through this CLAUDE.md: deleting it would dangle it.
254
+ const linkers = changed === null
255
+ ? await findLinksThrough(action.target, entries.flatMap((candidate) => candidate.agentsPath === null
256
+ ? [candidate.claudePath]
257
+ : [candidate.agentsPath, candidate.claudePath]), dependencies)
258
+ : [];
259
+ if (linkers.length > 0) {
260
+ const linked = linkers
261
+ .map((linker) => relative(repoRoot, linker).replaceAll('\\', '/'))
262
+ .join(', ');
263
+ appliedActions.push({
264
+ type: 'skip',
265
+ target: action.target,
266
+ reason: isStray
267
+ ? `CLAUDE.md kept after adoption into AGENTS.md (${linked} now link to it)`
268
+ : `CLAUDE.md changed since planning (${linked} now link to it); kept`,
269
+ result: 'skipped',
270
+ });
271
+ continue;
272
+ }
273
+ if (changed !== null) {
274
+ appliedActions.push({
275
+ type: 'skip',
276
+ target: action.target,
277
+ reason: isStray
278
+ ? `CLAUDE.md kept after adoption into AGENTS.md (${changed})`
279
+ : `CLAUDE.md changed since planning (${changed}); kept`,
280
+ result: 'skipped',
281
+ });
282
+ continue;
283
+ }
284
+ await dependencies.removeFile(action.target);
285
+ appliedActions.push({
286
+ ...action,
287
+ result: 'applied',
288
+ });
289
+ continue;
290
+ }
160
291
  if (isAgentsAction) {
161
292
  try {
162
293
  await dependencies.lstat(agentsPath);
@@ -170,8 +301,12 @@ async function applySyncActions(actions, entries, dependencies, strategy) {
170
301
  throw error;
171
302
  }
172
303
  }
304
+ const claudeBeforeAdoption = strategy === 'none' ? await dependencies.lstat(entry.claudePath) : null;
173
305
  const adoptedContent = await dependencies.readFile(entry.claudePath, 'utf8');
174
306
  await dependencies.writeFile(agentsPath, adoptedContent, 'utf8');
307
+ if (claudeBeforeAdoption) {
308
+ adoptedStrays.set(entry.claudePath, await recordAdoptedStray(entry.claudePath, agentsPath, claudeBeforeAdoption, dependencies));
309
+ }
175
310
  appliedActions.push({
176
311
  ...action,
177
312
  result: 'applied',
@@ -181,6 +316,9 @@ async function applySyncActions(actions, entries, dependencies, strategy) {
181
316
  if (!entry.agentsPath && action.type !== 'update') {
182
317
  throw new CliError(`Unable to resolve AGENTS.md for ${action.target}`, 2);
183
318
  }
319
+ if (strategy === 'none') {
320
+ throw new CliError(`Refusing to write ${action.target}: strategy none keeps no CLAUDE.md`, 2);
321
+ }
184
322
  try {
185
323
  if (action.type === 'update') {
186
324
  await dependencies.removeFile(action.target);
@@ -210,6 +348,28 @@ async function applySyncActions(actions, entries, dependencies, strategy) {
210
348
  }
211
349
  return appliedActions;
212
350
  }
351
+ /**
352
+ * After a stray's content is copied into AGENTS.md under `none`, the stray is
353
+ * removable only if it is now an exact managed shape of that AGENTS.md (in
354
+ * practice a byte-identical copy) and is still the same file that was read.
355
+ * Otherwise return why it must be kept.
356
+ */
357
+ async function recordAdoptedStray(claudePath, agentsPath, before, dependencies) {
358
+ const inspection = await inspectManagedShim(claudePath, agentsPath, dependencies);
359
+ if (inspection.kind === 'absent') {
360
+ return 'CLAUDE.md no longer exists';
361
+ }
362
+ if (inspection.kind === 'unmanaged' || inspection.kind === 'unreadable') {
363
+ return inspection.detail === 'hand-written or modified CLAUDE.md; kept'
364
+ ? 'its content differs from the adopted AGENTS.md'
365
+ : inspection.detail.replace(/; kept$/, '');
366
+ }
367
+ if (inspection.record.dev !== before.dev ||
368
+ inspection.record.ino !== before.ino) {
369
+ return 'CLAUDE.md was replaced during adoption';
370
+ }
371
+ return inspection.record;
372
+ }
213
373
  function getPostSyncEntries(entries, actions, strategy) {
214
374
  const actionByTarget = new Map(actions.map((action) => [action.target, action]));
215
375
  return entries.map((entry) => {
@@ -218,6 +378,30 @@ function getPostSyncEntries(entries, actions, strategy) {
218
378
  if (!action && !adoptedAction) {
219
379
  return entry;
220
380
  }
381
+ if (strategy === 'none' &&
382
+ entry.status === 'stray' &&
383
+ adoptedAction?.result === 'applied') {
384
+ return action?.type === 'remove' && action.result === 'applied'
385
+ ? {
386
+ ...entry,
387
+ agentsPath: getAgentsPath(entry),
388
+ status: 'ok',
389
+ detail: 'adopted into AGENTS.md; CLAUDE.md removed',
390
+ }
391
+ : {
392
+ ...entry,
393
+ agentsPath: getAgentsPath(entry),
394
+ status: 'unmanaged',
395
+ detail: 'adopted into AGENTS.md; CLAUDE.md kept',
396
+ };
397
+ }
398
+ if (action?.type === 'remove' && action.result === 'applied') {
399
+ return {
400
+ ...entry,
401
+ status: 'ok',
402
+ detail: 'OAT-managed CLAUDE.md removed',
403
+ };
404
+ }
221
405
  if (action?.result === 'applied' &&
222
406
  (entry.status !== 'stray' || adoptedAction?.result === 'applied')) {
223
407
  return {
@@ -238,18 +422,19 @@ export function createInstructionsSyncCommand(overrides = {}) {
238
422
  ...defaultDependencies(),
239
423
  ...overrides,
240
424
  };
425
+ // `--strategy` has no Commander default: a filled-in default is
426
+ // indistinguishable from an explicit flag and would always hide
427
+ // `instructions.claude.shims`.
241
428
  return new Command('sync')
242
429
  .description('Repair AGENTS.md/CLAUDE.md sync drift using the selected strategy')
243
430
  .option('--dry-run', 'Preview sync changes without applying')
244
431
  .option('--force', 'Overwrite mismatched CLAUDE.md files')
245
- .addOption(new Option('--strategy <strategy>', 'Sync strategy')
246
- .choices([...INSTRUCTION_SYNC_STRATEGIES])
247
- .default(DEFAULT_INSTRUCTION_SYNC_STRATEGY))
432
+ .addOption(new Option('--strategy <strategy>', 'Sync strategy for this run (overrides instructions.claude.shims)').choices([...INSTRUCTION_SYNC_STRATEGIES]))
248
433
  .action(async (options, command) => {
249
434
  const context = dependencies.buildCommandContext(readGlobalOptions(command));
250
435
  try {
251
436
  const repoRoot = await dependencies.resolveProjectRoot(context.cwd);
252
- const strategy = resolveInstructionSyncStrategy(options.strategy);
437
+ const strategy = resolveInstructionSyncStrategy(options.strategy, await dependencies.readConfiguredInstructionSyncStrategy(repoRoot));
253
438
  const exclusions = await dependencies.resolveInstructionPointerExcludes(repoRoot);
254
439
  // Warned before any work: an operator whose opt-out silently matches
255
440
  // nothing must hear about it even when the sync then succeeds.
@@ -260,30 +445,83 @@ export function createInstructionsSyncCommand(overrides = {}) {
260
445
  excludedPaths: exclusions.configured,
261
446
  strategy,
262
447
  });
263
- const plannedActions = planSyncActions({
448
+ // Removal under `none` is all or nothing: while any CLAUDE.md,
449
+ // .claude/CLAUDE.md, or CLAUDE.local.md has content of its own, a
450
+ // partial removal would leave some directories without their
451
+ // AGENTS.md instructions, so every planned removal is held back.
452
+ // Read-only and repository-wide, like the leftover warnings below.
453
+ const leftoversBeforeSync = strategy === 'none'
454
+ ? await dependencies.findLeftoverClaudeFiles(repoRoot)
455
+ : [];
456
+ const blockers = findShimRemovalBlockers(entries, leftoversBeforeSync);
457
+ const unblockedActions = planSyncActions({
264
458
  entries,
265
459
  force: options.force ?? false,
266
460
  strategy,
267
461
  });
462
+ const heldBack = unblockedActions
463
+ .filter((action) => action.type === 'remove')
464
+ .map((action) => action.target);
465
+ const blocked = blockers.length > 0 && heldBack.length > 0;
466
+ const plannedActions = blocked
467
+ ? unblockedActions.map((action) => action.type === 'remove'
468
+ ? {
469
+ type: 'skip',
470
+ target: action.target,
471
+ reason: describeShimRemovalBlock(repoRoot, blockers),
472
+ result: 'skipped',
473
+ }
474
+ : action)
475
+ : unblockedActions;
268
476
  const dryRun = options.dryRun ?? false;
269
477
  const actions = dryRun
270
478
  ? plannedActions
271
- : await applySyncActions(plannedActions, entries, dependencies, strategy);
479
+ : await applySyncActions(plannedActions, entries, dependencies, strategy, repoRoot);
480
+ // Read-only and repository-wide, independently of the mutation
481
+ // exclusions: Claude Code's walk does not honor OAT's excludes. A
482
+ // dry run reports what would remain, so planned removals are left
483
+ // out.
484
+ const plannedRemovals = new Set(plannedActions
485
+ .filter((action) => action.type === 'remove')
486
+ .map((action) => action.target));
487
+ const leftoverClaudeFiles = strategy !== 'none'
488
+ ? []
489
+ : dryRun
490
+ ? leftoversBeforeSync.filter((leftover) => !plannedRemovals.has(leftover.path))
491
+ : await dependencies.findLeftoverClaudeFiles(repoRoot);
492
+ const mode = dryRun ? 'dry-run' : 'apply';
493
+ const reportedEntries = dryRun
494
+ ? entries
495
+ : getPostSyncEntries(entries, actions, strategy);
272
496
  const payload = buildInstructionsPayload({
273
- mode: dryRun ? 'dry-run' : 'apply',
274
- entries: dryRun
275
- ? entries
276
- : getPostSyncEntries(entries, actions, strategy),
497
+ mode,
498
+ strategy,
499
+ entries: blocked
500
+ ? markBlockedShimEntries(reportedEntries)
501
+ : reportedEntries,
277
502
  actions,
278
503
  excludedPaths: exclusions.configured,
279
504
  effectiveExcludedPaths: exclusions.effective,
280
505
  exclusionWarnings: exclusions.warnings,
506
+ warnings: [
507
+ ...(blocked
508
+ ? [
509
+ buildShimRemovalBlockWarning(repoRoot, blockers, heldBack, mode),
510
+ ]
511
+ : []),
512
+ ...buildLeftoverClaudeWarnings(repoRoot, blocked
513
+ ? omitHeldBackLeftovers(leftoverClaudeFiles, heldBack)
514
+ : leftoverClaudeFiles),
515
+ ],
281
516
  });
282
517
  if (context.json) {
283
518
  context.logger.json(payload);
284
519
  }
285
520
  else {
286
521
  context.logger.info(formatInstructionsReport(payload, repoRoot));
522
+ for (const warning of payload.warnings ?? []) {
523
+ context.logger.warn(warning.message);
524
+ }
287
525
  if (dryRun) {
288
526
  context.logger.warn('\nDry-run only: no filesystem changes were made.');
289
527
  if (plannedActions.length > 0) {
@@ -1 +1 @@
1
- {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../../../src/commands/instructions/validate/validate.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,uCAAuC,EAC7C,MAAM,2CAA2C,CAAC;AAYnD,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAW5C,wBAAgB,iCAAiC,CAC/C,SAAS,GAAE,OAAO,CAAC,uCAAuC,CAAM,GAC/D,OAAO,CAsET"}
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../../../src/commands/instructions/validate/validate.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,uCAAuC,EAC7C,MAAM,2CAA2C,CAAC;AAmBnD,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAa5C,wBAAgB,iCAAiC,CAC/C,SAAS,GAAE,OAAO,CAAC,uCAAuC,CAAM,GAC/D,OAAO,CA+GT"}
@@ -1,6 +1,6 @@
1
1
  import { buildCommandContext } from '../../../app/command-context.js';
2
2
  import { INSTRUCTION_SYNC_STRATEGIES, } from '../../instructions/instructions.types.js';
3
- import { buildInstructionsPayload, DEFAULT_INSTRUCTION_SYNC_STRATEGY, formatInstructionsReport, resolveInstructionPointerExcludes, resolveInstructionSyncStrategy, scanInstructionFiles, } from '../../instructions/instructions.utils.js';
3
+ import { buildInstructionsPayload, buildLeftoverClaudeWarnings, buildShimRemovalBlockWarning, findLeftoverClaudeFiles, findShimRemovalBlockers, omitHeldBackLeftovers, listShimRemovals, markBlockedShimEntries, formatInstructionsReport, readConfiguredInstructionSyncStrategy, resolveInstructionPointerExcludes, resolveInstructionSyncStrategy, scanInstructionFiles, } from '../../instructions/instructions.utils.js';
4
4
  import { readGlobalOptions } from '../../shared/shared.utils.js';
5
5
  import { CliError } from '../../../errors/cli-error.js';
6
6
  import { resolveProjectRoot } from '../../../fs/paths.js';
@@ -8,6 +8,8 @@ import { Command, Option } from 'commander';
8
8
  function defaultDependencies() {
9
9
  return {
10
10
  buildCommandContext,
11
+ findLeftoverClaudeFiles,
12
+ readConfiguredInstructionSyncStrategy,
11
13
  resolveInstructionPointerExcludes,
12
14
  resolveProjectRoot,
13
15
  scanInstructionFiles,
@@ -18,16 +20,15 @@ export function createInstructionsValidateCommand(overrides = {}) {
18
20
  ...defaultDependencies(),
19
21
  ...overrides,
20
22
  };
23
+ // `--strategy` has no Commander default; see `oat instructions sync`.
21
24
  return new Command('validate')
22
25
  .description('Validate AGENTS.md/CLAUDE.md sync integrity for the selected strategy')
23
- .addOption(new Option('--strategy <strategy>', 'Sync strategy')
24
- .choices([...INSTRUCTION_SYNC_STRATEGIES])
25
- .default(DEFAULT_INSTRUCTION_SYNC_STRATEGY))
26
+ .addOption(new Option('--strategy <strategy>', 'Sync strategy to check (overrides instructions.claude.shims)').choices([...INSTRUCTION_SYNC_STRATEGIES]))
26
27
  .action(async (options, command) => {
27
28
  const context = dependencies.buildCommandContext(readGlobalOptions(command));
28
- const strategy = resolveInstructionSyncStrategy(options.strategy);
29
29
  try {
30
30
  const repoRoot = await dependencies.resolveProjectRoot(context.cwd);
31
+ const strategy = resolveInstructionSyncStrategy(options.strategy, await dependencies.readConfiguredInstructionSyncStrategy(repoRoot));
31
32
  const exclusions = await dependencies.resolveInstructionPointerExcludes(repoRoot);
32
33
  // Warned before any work: an operator whose opt-out silently matches
33
34
  // nothing must hear about it even when validate then reports `ok`.
@@ -38,21 +39,48 @@ export function createInstructionsValidateCommand(overrides = {}) {
38
39
  excludedPaths: exclusions.configured,
39
40
  strategy,
40
41
  });
42
+ const leftovers = strategy === 'none'
43
+ ? await dependencies.findLeftoverClaudeFiles(repoRoot)
44
+ : [];
45
+ // The same all-or-nothing rule sync applies: while a CLAUDE.md has
46
+ // content of its own, sync removes none of the shims below.
47
+ const blockers = findShimRemovalBlockers(entries, leftovers);
48
+ const wouldRemove = listShimRemovals(entries);
49
+ const blocked = blockers.length > 0 && wouldRemove.length > 0;
41
50
  const payload = buildInstructionsPayload({
42
51
  mode: 'validate',
43
- entries,
52
+ strategy,
53
+ entries: blocked ? markBlockedShimEntries(entries) : entries,
44
54
  actions: [],
45
55
  excludedPaths: exclusions.configured,
46
56
  effectiveExcludedPaths: exclusions.effective,
47
57
  exclusionWarnings: exclusions.warnings,
58
+ // Warnings, never drift: they do not change the exit code.
59
+ warnings: [
60
+ ...(blocked
61
+ ? [
62
+ buildShimRemovalBlockWarning(repoRoot, blockers, wouldRemove, 'validate'),
63
+ ]
64
+ : []),
65
+ ...buildLeftoverClaudeWarnings(repoRoot, blocked
66
+ ? omitHeldBackLeftovers(leftovers, wouldRemove)
67
+ : leftovers),
68
+ ],
48
69
  });
49
70
  if (context.json) {
50
71
  context.logger.json(payload);
51
72
  }
52
73
  else {
53
74
  context.logger.info(formatInstructionsReport(payload, repoRoot));
54
- if (payload.status === 'drift') {
55
- const fixCommand = strategy === DEFAULT_INSTRUCTION_SYNC_STRATEGY
75
+ for (const warning of payload.warnings ?? []) {
76
+ context.logger.warn(warning.message);
77
+ }
78
+ // While the block holds, sync cannot clear this drift; the
79
+ // warning above names what can.
80
+ if (payload.status === 'drift' && !blocked) {
81
+ // Repeat the flag only when this run was given one: without it,
82
+ // a bare sync resolves the same configured or default strategy.
83
+ const fixCommand = options.strategy === undefined
56
84
  ? 'Fix with: oat instructions sync'
57
85
  : `Fix with: oat instructions sync --strategy ${strategy}`;
58
86
  context.logger.info(fixCommand);
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/pjm/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAuB,MAAM,sBAAsB,CAAC;AAGhF,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAE/C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,EAAE,uBAAuB,EAA0B,MAAM,QAAQ,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAiBxD,UAAU,sBAAsB;IAC9B,mBAAmB,EAAE,OAAO,mBAAmB,CAAC;IAChD,kBAAkB,EAAE,OAAO,kBAAkB,CAAC;IAC9C,iBAAiB,EAAE,OAAO,iBAAiB,CAAC;IAC5C,kBAAkB,EAAE,OAAO,kBAAkB,CAAC;IAC9C,uBAAuB,EAAE,OAAO,uBAAuB,CAAC;IACxD,kBAAkB,EAAE,OAAO,kBAAkB,CAAC;IAC9C,cAAc,EAAE,OAAO,cAAc,CAAC;IACtC,sBAAsB,EAAE,OAAO,sBAAsB,CAAC;IACtD,sBAAsB,EAAE,OAAO,sBAAsB,CAAC;CACvD;AA8FD,wBAAgB,gBAAgB,CAC9B,SAAS,GAAE,OAAO,CAAC,sBAAsB,CAAM,GAC9C,OAAO,CA0LT"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/pjm/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAuB,MAAM,sBAAsB,CAAC;AAGhF,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAE/C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,EAIL,uBAAuB,EAExB,MAAM,QAAQ,CAAC;AAChB,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAiBxD,UAAU,sBAAsB;IAC9B,mBAAmB,EAAE,OAAO,mBAAmB,CAAC;IAChD,kBAAkB,EAAE,OAAO,kBAAkB,CAAC;IAC9C,iBAAiB,EAAE,OAAO,iBAAiB,CAAC;IAC5C,kBAAkB,EAAE,OAAO,kBAAkB,CAAC;IAC9C,uBAAuB,EAAE,OAAO,uBAAuB,CAAC;IACxD,kBAAkB,EAAE,OAAO,kBAAkB,CAAC;IAC9C,cAAc,EAAE,OAAO,cAAc,CAAC;IACtC,sBAAsB,EAAE,OAAO,sBAAsB,CAAC;IACtD,sBAAsB,EAAE,OAAO,sBAAsB,CAAC;CACvD;AA8FD,wBAAgB,gBAAgB,CAC9B,SAAS,GAAE,OAAO,CAAC,sBAAsB,CAAM,GAC9C,OAAO,CA6MT"}
@@ -8,7 +8,7 @@ import { formatDoctorResults } from '../../ui/output.js';
8
8
  import { Command } from 'commander';
9
9
  import { resolvePjmAdoption } from './adoption.js';
10
10
  import { runPjmDoctorChecks } from './doctor.js';
11
- import { initializeRepoReference, INSTRUCTIONS_SYNC_HINT } from './init.js';
11
+ import { AGENTS_GUIDANCE_APPENDED_MESSAGE, AGENTS_GUIDANCE_MANUAL_MESSAGE, agentsGuidanceRefusalMessage, initializeRepoReference, INSTRUCTIONS_SYNC_HINT, } from './init.js';
12
12
  import { migratePjmRepo, readPjmMigrationPrompt } from './migrate.js';
13
13
  import { createPjmRemoteCommand } from './remote/index.js';
14
14
  const DEFAULT_DEPENDENCIES = {
@@ -134,10 +134,25 @@ export function createPjmCommand(overrides = {}) {
134
134
  context.logger.info(`Skipped existing: ${result.skipped.join(', ')}`);
135
135
  }
136
136
  context.logger.info(INSTRUCTIONS_SYNC_HINT);
137
+ const guidanceResults = Object.values(result.guidance ?? {});
138
+ if (guidanceResults.some(({ action }) => action === 'appended')) {
139
+ context.logger.info(AGENTS_GUIDANCE_APPENDED_MESSAGE);
140
+ }
137
141
  if (guidanceIncomplete) {
138
- context.logger.warn('PJM scaffold and adoption completed; AGENTS.md guidance requires manual action.');
139
- for (const guidance of Object.values(result.guidance ?? {})) {
140
- for (const line of formatAgentsMdGuidanceResult(guidance)) {
142
+ const refusedPatch = guidanceResults.find(({ manualPatch }) => manualPatch?.appendRefusal !== undefined)?.manualPatch;
143
+ context.logger.warn(refusedPatch?.appendRefusal
144
+ ? agentsGuidanceRefusalMessage(refusedPatch.target, refusedPatch.appendRefusal)
145
+ : AGENTS_GUIDANCE_MANUAL_MESSAGE);
146
+ // Both writers share one combined patch; print each distinct
147
+ // guidance result once per command, not once per writer.
148
+ const printed = new Set();
149
+ for (const guidance of guidanceResults) {
150
+ const lines = formatAgentsMdGuidanceResult(guidance);
151
+ const identity = lines.join('\n');
152
+ if (lines.length === 0 || printed.has(identity))
153
+ continue;
154
+ printed.add(identity);
155
+ for (const line of lines) {
141
156
  context.logger.info(line);
142
157
  }
143
158
  }
@@ -16,6 +16,9 @@ export interface RepoReferenceInitResult {
16
16
  };
17
17
  }
18
18
  export declare const INSTRUCTIONS_SYNC_HINT: string;
19
+ export declare const AGENTS_GUIDANCE_APPENDED_MESSAGE = "AGENTS.md guidance: appended the absent OAT managed blocks to the existing AGENTS.md.";
20
+ export declare const AGENTS_GUIDANCE_MANUAL_MESSAGE: string;
21
+ export declare function agentsGuidanceRefusalMessage(target: string, cause: string): string;
19
22
  export declare const CANONICAL_REPO_REFERENCE_PATHS: readonly [...("AGENTS.md" | "README.md" | "pjm/AGENTS.md" | "pjm/current-state.md" | "pjm/handoffs/README.md" | "pjm/roadmap.md" | "reference/AGENTS.md")[], "pjm/backlog/index.md", "pjm/backlog/completed.md", "pjm/backlog/items/.gitkeep", "pjm/backlog/archived/.gitkeep", "reference/decisions/AGENTS.md", "reference/decisions/index.md"];
20
23
  export declare const PJM_ADOPTION_SCHEMA_VERSION = 1;
21
24
  export declare function initializeRepoReference(options: InitializeRepoReferenceOptions): Promise<RepoReferenceInitResult>;
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/commands/pjm/init.ts"],"names":[],"mappings":"AAcA,OAAO,EACL,KAAK,mBAAmB,EAEzB,MAAM,4BAA4B,CAAC;AAMpC,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE;QACR,iBAAiB,EAAE,mBAAmB,CAAC;QACvC,SAAS,EAAE,mBAAmB,CAAC;KAChC,CAAC;CACH;AAoBD,eAAO,MAAM,sBAAsB,QAEiD,CAAC;AAerF,eAAO,MAAM,8BAA8B,kVAIjC,CAAC;AAEX,eAAO,MAAM,2BAA2B,IAAI,CAAC;AAiC7C,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,8BAA8B,GACtC,OAAO,CAAC,uBAAuB,CAAC,CAsHlC"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/commands/pjm/init.ts"],"names":[],"mappings":"AAcA,OAAO,EACL,KAAK,mBAAmB,EAEzB,MAAM,4BAA4B,CAAC;AAMpC,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE;QACR,iBAAiB,EAAE,mBAAmB,CAAC;QACvC,SAAS,EAAE,mBAAmB,CAAC;KAChC,CAAC;CACH;AAsBD,eAAO,MAAM,sBAAsB,QAIoB,CAAC;AAOxD,eAAO,MAAM,gCAAgC,0FAC4C,CAAC;AAC1F,eAAO,MAAM,8BAA8B,QAG4C,CAAC;AACxF,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GACZ,MAAM,CAMR;AAeD,eAAO,MAAM,8BAA8B,kVAIjC,CAAC;AAEX,eAAO,MAAM,2BAA2B,IAAI,CAAC;AAiC7C,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,8BAA8B,GACtC,OAAO,CAAC,uBAAuB,CAAC,CAsHlC"}
@@ -17,11 +17,29 @@ const TEMPLATE_TARGETS = [
17
17
  { template: 'repo-readme.md', target: 'README.md' },
18
18
  { template: 'pjm-handoffs-readme.md', target: 'pjm/handoffs/README.md' },
19
19
  ];
20
- // Next-step hint printed after init/backfill. `oat pjm init` never writes
21
- // CLAUDE.md shims itself — strategy ownership stays with `oat instructions
22
- // sync`, so we point the operator at it (with the `--dry-run` preview).
23
- export const INSTRUCTIONS_SYNC_HINT = 'Next step: run `oat instructions sync` to create CLAUDE.md shims for the ' +
24
- 'repo-reference AGENTS.md files (preview with `oat instructions sync --dry-run`).';
20
+ // Next-step hint printed after init/backfill. `oat pjm init` never writes or
21
+ // removes CLAUDE.md files itself — strategy ownership stays with
22
+ // `oat instructions sync`, so we point the operator at it (with the
23
+ // `--dry-run` preview). It must not promise shims: the default strategy is
24
+ // `none` (DR-260927-claude-md-shims-are-opt), so shims are opt-in.
25
+ export const INSTRUCTIONS_SYNC_HINT = 'Next step: run `oat instructions sync` to check the repo-reference AGENTS.md ' +
26
+ 'files against your CLAUDE.md strategy (preview with `oat instructions sync --dry-run`). ' +
27
+ 'No CLAUDE.md shims are created by default; opt in with ' +
28
+ '`oat config set instructions.claude.shims pointer`.';
29
+ // AGENTS.md guidance messages printed by `oat pjm init`. An absent managed
30
+ // block is appended to an existing AGENTS.md. The printed manual patch is
31
+ // needed when a block is present but differs from the managed version, or
32
+ // when OAT refuses to append at all (for example a hard-linked or unwritable
33
+ // AGENTS.md); the refusal gets its own header.
34
+ export const AGENTS_GUIDANCE_APPENDED_MESSAGE = 'AGENTS.md guidance: appended the absent OAT managed blocks to the existing AGENTS.md.';
35
+ export const AGENTS_GUIDANCE_MANUAL_MESSAGE = 'PJM scaffold and adoption completed; AGENTS.md guidance requires manual action. ' +
36
+ 'Absent managed blocks are appended automatically, but an existing block ' +
37
+ 'differs from the managed version: apply the patch below, then rerun `oat pjm init`.';
38
+ export function agentsGuidanceRefusalMessage(target, cause) {
39
+ return ('PJM scaffold and adoption completed; AGENTS.md guidance requires manual action. ' +
40
+ `OAT could not append the absent guidance blocks to ${target} (${cause}), ` +
41
+ 'so nothing was written: apply the patch below, then rerun `oat pjm init`.');
42
+ }
25
43
  const BACKLOG_PATHS = [
26
44
  'pjm/backlog/index.md',
27
45
  'pjm/backlog/completed.md',
@@ -0,0 +1,33 @@
1
+ import { type CanonicalRoleEvidence } from '../../../agents/canonical/index.js';
2
+ import type { CommandContext, GlobalOptions } from '../../../app/command-context.js';
3
+ import { Command } from 'commander';
4
+ /** The pack that ships the canonical OAT dispatch roles. */
5
+ export declare const CANONICAL_ROLE_DEPENDENCY = "workflows";
6
+ export interface CanonicalRoleCommandDependencies {
7
+ buildCommandContext: (options: GlobalOptions) => CommandContext;
8
+ resolveProjectRoot: (cwd: string) => Promise<string>;
9
+ }
10
+ export interface CanonicalRoleResolutionEvent {
11
+ kind: 'canonical-role-resolution';
12
+ requestId: string;
13
+ source: 'canonical-role-resolver';
14
+ evidence: CanonicalRoleEvidence;
15
+ }
16
+ /**
17
+ * Produce `canonical-role-resolution` evidence from the resolver itself, so a
18
+ * caller never hand-assembles redacted paths or a content digest. Read-only:
19
+ * it inspects the loaded, user, and project `.agents` roots and writes
20
+ * nothing. The emitted event is checked against the recorder's own event
21
+ * schema before it is printed, so `oat project dispatch record` accepts it
22
+ * unchanged.
23
+ */
24
+ export declare function produceCanonicalRoleEvent(input: {
25
+ role: string;
26
+ requestId: string;
27
+ skillDir: string;
28
+ cwd: string;
29
+ home: string;
30
+ repoRoot: string;
31
+ }): Promise<CanonicalRoleResolutionEvent>;
32
+ export declare function createCanonicalRoleCommand(dependencies: CanonicalRoleCommandDependencies): Command;
33
+ //# sourceMappingURL=canonical-role.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canonical-role.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/dispatch/canonical-role.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,qBAAqB,EAC3B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAI1E,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,4DAA4D;AAC5D,eAAO,MAAM,yBAAyB,cAAc,CAAC;AAKrD,MAAM,WAAW,gCAAgC;IAC/C,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CACtD;AAQD,MAAM,WAAW,4BAA4B;IAC3C,IAAI,EAAE,2BAA2B,CAAC;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,yBAAyB,CAAC;IAClC,QAAQ,EAAE,qBAAqB,CAAC;CACjC;AAeD;;;;;;;GAOG;AACH,wBAAsB,yBAAyB,CAAC,KAAK,EAAE;IACrD,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB,GAAG,OAAO,CAAC,4BAA4B,CAAC,CAiCxC;AAwDD,wBAAgB,0BAA0B,CACxC,YAAY,EAAE,gCAAgC,GAC7C,OAAO,CAyBT"}