@open-agent-toolkit/cli 0.2.59 → 0.2.63

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 (120) hide show
  1. package/assets/agents/oat-phase-implementer.md +27 -4
  2. package/assets/agents/oat-reviewer.md +25 -14
  3. package/assets/bundle-metadata.json +1 -1
  4. package/assets/docs/cli-utilities/config-and-local-state.md +1 -0
  5. package/assets/docs/cli-utilities/configuration.md +10 -8
  6. package/assets/docs/cli-utilities/project-log.md +16 -0
  7. package/assets/docs/cli-utilities/workflow-gates.md +127 -19
  8. package/assets/docs/provider-sync/commands.md +3 -0
  9. package/assets/docs/provider-sync/instruction-sync.md +107 -0
  10. package/assets/docs/reference/cli-reference.md +26 -9
  11. package/assets/docs/reference/oat-directory-structure.md +33 -31
  12. package/assets/docs/workflows/ideas/index.md +1 -1
  13. package/assets/docs/workflows/index.md +1 -0
  14. package/assets/docs/workflows/projects/artifacts.md +24 -3
  15. package/assets/docs/workflows/projects/hill-checkpoints.md +21 -0
  16. package/assets/docs/workflows/projects/implementation-execution.md +5 -0
  17. package/assets/docs/workflows/projects/lifecycle.md +169 -7
  18. package/assets/docs/workflows/projects/picking-up-projects.md +14 -0
  19. package/assets/docs/workflows/projects/pr-flow.md +2 -0
  20. package/assets/docs/workflows/projects/reviews.md +1 -1
  21. package/assets/docs/workflows/projects/state-machine.md +20 -0
  22. package/assets/docs/workflows/skills/explainer-kit.md +10 -4
  23. package/assets/docs/workflows/skills/index.md +2 -1
  24. package/assets/docs/workflows/skills/repo-improve.md +15 -1
  25. package/assets/public-package-versions.json +4 -4
  26. package/assets/skills/oat-brainstorm/SKILL.md +61 -12
  27. package/assets/skills/oat-docs/SKILL.md +13 -8
  28. package/assets/skills/oat-doctor/SKILL.md +3 -3
  29. package/assets/skills/oat-explainer-kit/SKILL.md +14 -1
  30. package/assets/skills/oat-explainer-kit/references/config-contract.md +12 -0
  31. package/assets/skills/oat-explainer-kit/references/lifecycle-contract.md +57 -10
  32. package/assets/skills/oat-explainer-kit/scripts/check-terminal-outcome.mjs +28 -5
  33. package/assets/skills/oat-explainer-kit/scripts/probe-recap-seams.mjs +371 -0
  34. package/assets/skills/oat-explainer-kit/scripts/resolve-intent.mjs +123 -1
  35. package/assets/skills/oat-pjm-review-backlog/SKILL.md +2 -2
  36. package/assets/skills/oat-project-autonomous/SKILL.md +23 -9
  37. package/assets/skills/oat-project-autonomous/references/gate-inventory.md +164 -150
  38. package/assets/skills/oat-project-capture/SKILL.md +2 -2
  39. package/assets/skills/oat-project-complete/SKILL.md +134 -4
  40. package/assets/skills/oat-project-discover/SKILL.md +6 -5
  41. package/assets/skills/oat-project-document/SKILL.md +11 -1
  42. package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +164 -150
  43. package/assets/skills/oat-project-implement/SKILL.md +3 -3
  44. package/assets/skills/oat-project-implement/references/completion-and-closeout.md +144 -21
  45. package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +164 -150
  46. package/assets/skills/oat-project-implement/references/phase-execution.md +16 -1
  47. package/assets/skills/oat-project-implement/references/plan-and-resume.md +19 -1
  48. package/assets/skills/oat-project-import-plan/SKILL.md +47 -3
  49. package/assets/skills/oat-project-lite/SKILL.md +467 -0
  50. package/assets/skills/oat-project-lite/references/docs/autonomy-contract.md +331 -0
  51. package/assets/skills/oat-project-next/SKILL.md +75 -16
  52. package/assets/skills/oat-project-plan/SKILL.md +44 -6
  53. package/assets/skills/oat-project-plan-writing/SKILL.md +6 -3
  54. package/assets/skills/oat-project-pr-final/SKILL.md +33 -7
  55. package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +164 -150
  56. package/assets/skills/oat-project-pr-progress/SKILL.md +3 -3
  57. package/assets/skills/oat-project-progress/SKILL.md +27 -5
  58. package/assets/skills/oat-project-promote-spec-driven/SKILL.md +3 -1
  59. package/assets/skills/oat-project-quick-start/SKILL.md +264 -4
  60. package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +164 -150
  61. package/assets/skills/oat-project-review-provide/SKILL.md +25 -6
  62. package/assets/skills/oat-project-summary/SKILL.md +61 -26
  63. package/assets/skills/oat-repo-improve/SKILL.md +40 -5
  64. package/assets/skills/oat-repo-improve/references/plan-template.md +84 -7
  65. package/assets/templates/plan-lite.md +165 -0
  66. package/assets/templates/plan.md +1 -1
  67. package/assets/templates/state.md +1 -1
  68. package/dist/commands/config/index.d.ts +1 -0
  69. package/dist/commands/config/index.d.ts.map +1 -1
  70. package/dist/commands/config/index.js +401 -18
  71. package/dist/commands/gate/index.d.ts +3 -1
  72. package/dist/commands/gate/index.d.ts.map +1 -1
  73. package/dist/commands/gate/index.js +699 -211
  74. package/dist/commands/init/tools/shared/skill-script-references.d.ts +126 -0
  75. package/dist/commands/init/tools/shared/skill-script-references.d.ts.map +1 -0
  76. package/dist/commands/init/tools/shared/skill-script-references.js +311 -0
  77. package/dist/commands/instructions/instructions.types.d.ts +63 -0
  78. package/dist/commands/instructions/instructions.types.d.ts.map +1 -1
  79. package/dist/commands/instructions/instructions.utils.d.ts +51 -2
  80. package/dist/commands/instructions/instructions.utils.d.ts.map +1 -1
  81. package/dist/commands/instructions/instructions.utils.js +201 -4
  82. package/dist/commands/instructions/sync/sync.d.ts.map +1 -1
  83. package/dist/commands/instructions/sync/sync.js +12 -1
  84. package/dist/commands/instructions/validate/validate.d.ts.map +1 -1
  85. package/dist/commands/instructions/validate/validate.js +12 -1
  86. package/dist/commands/project/index.d.ts.map +1 -1
  87. package/dist/commands/project/index.js +2 -0
  88. package/dist/commands/project/log/append.d.ts +195 -0
  89. package/dist/commands/project/log/append.d.ts.map +1 -1
  90. package/dist/commands/project/log/append.js +1034 -11
  91. package/dist/commands/project/new/index.d.ts +3 -2
  92. package/dist/commands/project/new/index.d.ts.map +1 -1
  93. package/dist/commands/project/new/index.js +2 -1
  94. package/dist/commands/project/new/scaffold.d.ts +5 -3
  95. package/dist/commands/project/new/scaffold.d.ts.map +1 -1
  96. package/dist/commands/project/new/scaffold.js +38 -10
  97. package/dist/commands/project/promote/index.d.ts +2 -0
  98. package/dist/commands/project/promote/index.d.ts.map +1 -0
  99. package/dist/commands/project/promote/index.js +1 -0
  100. package/dist/commands/project/promote/promote.d.ts +47 -0
  101. package/dist/commands/project/promote/promote.d.ts.map +1 -0
  102. package/dist/commands/project/promote/promote.js +322 -0
  103. package/dist/commands/project/split/run.d.ts.map +1 -1
  104. package/dist/commands/project/split/run.js +8 -1
  105. package/dist/commands/project/validate-plan/index.d.ts.map +1 -1
  106. package/dist/commands/project/validate-plan/index.js +25 -1
  107. package/dist/commands/project/validate-plan/validate-plan.d.ts +8 -0
  108. package/dist/commands/project/validate-plan/validate-plan.d.ts.map +1 -1
  109. package/dist/commands/project/validate-plan/validate-plan.js +49 -0
  110. package/dist/commands/shared/frontmatter.d.ts +1 -1
  111. package/dist/commands/shared/frontmatter.d.ts.map +1 -1
  112. package/dist/commands/shared/frontmatter.js +1 -0
  113. package/dist/commands/state/generate.d.ts.map +1 -1
  114. package/dist/commands/state/generate.js +23 -0
  115. package/dist/commands/tools/shared/pack-manifest.d.ts.map +1 -1
  116. package/dist/commands/tools/shared/pack-manifest.js +2 -0
  117. package/dist/config/oat-config.d.ts +41 -0
  118. package/dist/config/oat-config.d.ts.map +1 -1
  119. package/dist/config/oat-config.js +111 -0
  120. package/package.json +2 -2
@@ -1,5 +1,6 @@
1
1
  import { lstat, readdir, readFile, readlink, realpath, stat, } from 'node:fs/promises';
2
- import { dirname, join, relative, resolve } from 'node:path';
2
+ import { dirname, join, posix, relative, resolve } from 'node:path';
3
+ import { readOatConfig, resolveDocumentationContentRoot, } from '../../config/oat-config.js';
3
4
  export const EXPECTED_CLAUDE_CONTENT = '@AGENTS.md\n';
4
5
  export const DEFAULT_INSTRUCTION_SYNC_STRATEGY = 'pointer';
5
6
  const ROOT_EXCLUDED_DIRECTORIES = new Set(['.git', '.oat', '.worktrees']);
@@ -87,7 +88,171 @@ function recordInstructionFile(directoryEntries, directoryPath, entryName, entry
87
88
  }
88
89
  directoryEntries.set(directoryPath, current);
89
90
  }
90
- async function scanInstructionDirectories(repoRoot, dependencies, debug) {
91
+ /**
92
+ * Canonicalize repo-relative exclusion entries into the exact form the scan
93
+ * compares against: POSIX separators, collapsed `.` and `..` segments and
94
+ * duplicate slashes, no trailing slash, de-duplicated, order-preserving.
95
+ *
96
+ * Full normalization is what makes the comparison trustworthy. The scan tests
97
+ * an exclusion against `relative(repoRoot, entryPath)`, which is always
98
+ * already-normalized, so an un-normalized entry like `apps/./docs` or
99
+ * `apps//docs` would silently never match and quietly fail open.
100
+ *
101
+ * Two classes of entry are dropped rather than normalized:
102
+ *
103
+ * - anything resolving to the repository root (`.`, `` , `./`), because
104
+ * excluding the root would silence the entire scan — including the
105
+ * `.oat/repo` carve-in — from one stray config value; and
106
+ * - absolute paths and entries escaping the repository (`..`, `../x`), which
107
+ * can never name a directory inside the tree being scanned. Dropping them
108
+ * keeps a malformed value from masquerading as a matchable exclusion.
109
+ */
110
+ export function normalizeExcludedPaths(excludedPaths = []) {
111
+ const normalized = [];
112
+ for (const candidate of excludedPaths) {
113
+ const trimmed = toPosixPath(candidate.trim());
114
+ if (!trimmed || posix.isAbsolute(trimmed)) {
115
+ continue;
116
+ }
117
+ const posixPath = posix.normalize(trimmed).replace(/\/+$/, '');
118
+ if (!posixPath ||
119
+ posixPath === '.' ||
120
+ posixPath === '..' ||
121
+ posixPath.startsWith('../')) {
122
+ continue;
123
+ }
124
+ if (!normalized.includes(posixPath)) {
125
+ normalized.push(posixPath);
126
+ }
127
+ }
128
+ return normalized;
129
+ }
130
+ /**
131
+ * Paths the carve-in queues directly, which therefore never reach the exclusion
132
+ * predicate and can never be excluded however the config asks. An opt-out
133
+ * naming one of these is inert and must be reported as such rather than
134
+ * silently listed as protection.
135
+ *
136
+ * Matched exactly, never by prefix: only the carve-in root itself bypasses the
137
+ * predicate. Its *descendants* are reached by ordinary traversal out of the
138
+ * queued directory, so `.oat/repo/pjm` is excludable even though `.oat/repo`
139
+ * is not, and treating it as inert would be a false warning about an exclusion
140
+ * that really does protect its tree.
141
+ */
142
+ const UNEXCLUDABLE_PATHS = new Set([...ROOT_EXCLUDED_DIRECTORY_CARVE_INS].map(([directory, carveIn]) => `${directory}/${carveIn}`));
143
+ /**
144
+ * Whether `relativePath` names a real directory whose on-disk spelling matches
145
+ * exactly.
146
+ *
147
+ * The case check is the point. On a case-insensitive filesystem (APFS, NTFS) a
148
+ * plain existence test accepts `Apps/Docsapp/docs` for a directory really named
149
+ * `apps/docsapp/docs`, but the scan compares against `relative(repoRoot, ...)`,
150
+ * which always yields the true on-disk case. The exclusion would then be
151
+ * reported as applied while matching nothing — issue #238 recurring silently on
152
+ * the default developer platform. Resolving through `realpath` and comparing
153
+ * the result to the requested spelling catches that, and returns false for a
154
+ * path that does not exist at all.
155
+ *
156
+ * `repoRoot` is realpath'd too, so a symlinked checkout (`/tmp` on macOS) does
157
+ * not make every entry look like a mismatch.
158
+ */
159
+ async function isCaseExactDirectory(dependencies, repoRoot, relativePath) {
160
+ try {
161
+ const realRoot = await dependencies.realpath(repoRoot);
162
+ const candidate = join(realRoot, relativePath);
163
+ if (!(await directoryExists(dependencies, candidate))) {
164
+ return false;
165
+ }
166
+ const realCandidate = await dependencies.realpath(candidate);
167
+ return toPosixPath(relative(realRoot, realCandidate)) === relativePath;
168
+ }
169
+ catch {
170
+ return false;
171
+ }
172
+ }
173
+ /**
174
+ * The directories `oat instructions sync` and `oat instructions validate` skip:
175
+ * the derived documentation content root first, then the explicit
176
+ * `documentation.instructionPointerExcludes` opt-outs.
177
+ *
178
+ * Both commands resolve exclusions through this one function. That is the
179
+ * property that matters: if they computed exclusions separately, validate
180
+ * could report drift in a directory sync refuses to touch, and the repository
181
+ * would have no clean state to reach.
182
+ *
183
+ * Every configured entry is classified rather than trusted. An entry that is
184
+ * dropped during normalization, names an unexcludable carve-in root, or does
185
+ * not resolve to a real case-exact directory is reported as a warning and kept
186
+ * out of `effective`, so no caller can mistake a typo for protection.
187
+ *
188
+ * `effective` answers "is this tree protected from pointer writes?", not "did
189
+ * the exclusion predicate fire for it". An entry that names an already-skipped
190
+ * built-in root (`.git`, `node_modules`) or sits beneath another exclusion is
191
+ * still effective, because the operator's intent holds; warning about those
192
+ * would be a false alarm about exclusions that do work.
193
+ *
194
+ * Nothing here deletes or rewrites an existing pointer. Excluding a directory
195
+ * only stops it being reported and written; a `CLAUDE.md` already inside an
196
+ * excluded tree is left exactly as it is.
197
+ */
198
+ export async function resolveInstructionPointerExcludes(repoRoot, overrides = {}) {
199
+ const dependencies = {
200
+ lstat,
201
+ realpath,
202
+ readdir,
203
+ readFile,
204
+ readlink,
205
+ stat,
206
+ ...overrides,
207
+ };
208
+ const config = await readOatConfig(repoRoot);
209
+ const contentRoot = await resolveDocumentationContentRoot(repoRoot, config, {
210
+ // Probe through the injected `stat` so a simulated filesystem (tests) and
211
+ // the real one agree on whether `<root>/docs` exists.
212
+ dirExists: async (path) => {
213
+ try {
214
+ return (await dependencies.stat(path)).isDirectory();
215
+ }
216
+ catch {
217
+ return false;
218
+ }
219
+ },
220
+ });
221
+ const requested = [
222
+ ...(contentRoot === null
223
+ ? []
224
+ : [{ raw: contentRoot, source: 'documentation.root' }]),
225
+ ...(config.documentation?.instructionPointerExcludes ?? []).map((raw) => ({
226
+ raw,
227
+ source: 'documentation.instructionPointerExcludes',
228
+ })),
229
+ ];
230
+ const configured = [];
231
+ const effective = [];
232
+ const warnings = [];
233
+ for (const { raw, source } of requested) {
234
+ const [normalizedPath] = normalizeExcludedPaths([raw]);
235
+ if (!normalizedPath) {
236
+ warnings.push(`Ignoring ${source} entry ${JSON.stringify(raw)}: exclusions must be repository-relative paths inside the repository.`);
237
+ continue;
238
+ }
239
+ if (configured.includes(normalizedPath)) {
240
+ continue;
241
+ }
242
+ configured.push(normalizedPath);
243
+ if (UNEXCLUDABLE_PATHS.has(normalizedPath)) {
244
+ warnings.push(`${source} entry ${JSON.stringify(normalizedPath)} has no effect: ${normalizedPath} is always scanned.`);
245
+ continue;
246
+ }
247
+ if (!(await isCaseExactDirectory(dependencies, repoRoot, normalizedPath))) {
248
+ warnings.push(`${source} entry ${JSON.stringify(normalizedPath)} matches no directory in this repository (matching is case-sensitive), so it excludes nothing.`);
249
+ continue;
250
+ }
251
+ effective.push(normalizedPath);
252
+ }
253
+ return { configured, effective, warnings };
254
+ }
255
+ async function scanInstructionDirectories(repoRoot, dependencies, debug, excludedPaths = new Set()) {
91
256
  const queue = [repoRoot];
92
257
  const directoryEntries = new Map();
93
258
  while (queue.length > 0) {
@@ -123,6 +288,19 @@ async function scanInstructionDirectories(repoRoot, dependencies, debug) {
123
288
  }
124
289
  continue;
125
290
  }
291
+ // Deliberately after the carve-in above, never before it: the carve-in
292
+ // path is already queued by the time a configured exclusion is tested,
293
+ // so excluding `.oat` (or any documentation root that happens to
294
+ // contain one) still leaves `.oat/repo/**` scanned. Skipping the
295
+ // directory here also skips its whole subtree, because a directory
296
+ // that is never queued is never read.
297
+ if (excludedPaths.size > 0) {
298
+ const relativePath = toPosixPath(relative(repoRoot, entryPath));
299
+ if (excludedPaths.has(relativePath)) {
300
+ debug?.(`Skipping excluded directory ${relativePath}`);
301
+ continue;
302
+ }
303
+ }
126
304
  queue.push(entryPath);
127
305
  continue;
128
306
  }
@@ -181,7 +359,7 @@ export async function scanInstructionFiles(repoRoot, options = {}, overrides = {
181
359
  stat,
182
360
  ...overrides,
183
361
  };
184
- const instructionDirectories = await scanInstructionDirectories(repoRoot, dependencies, options.debug);
362
+ const instructionDirectories = await scanInstructionDirectories(repoRoot, dependencies, options.debug, new Set(normalizeExcludedPaths(options.excludedPaths)));
185
363
  const entries = [];
186
364
  for (const [directoryPath, directoryEntry] of instructionDirectories) {
187
365
  const agentsPath = directoryEntry.agentsPath ?? null;
@@ -402,15 +580,34 @@ function deriveInstructionsStatus(entries, actions) {
402
580
  }
403
581
  return 'ok';
404
582
  }
405
- export function buildInstructionsPayload({ mode, entries, actions, }) {
583
+ export function buildInstructionsPayload({ mode, entries, actions, excludedPaths, effectiveExcludedPaths, exclusionWarnings, }) {
406
584
  const normalizedEntries = normalizeEntries(entries);
407
585
  const normalizedActions = normalizeActions(actions);
586
+ const normalizedExcludedPaths = normalizeExcludedPaths(excludedPaths);
587
+ const normalizedEffectivePaths = normalizeExcludedPaths(effectiveExcludedPaths);
408
588
  return {
409
589
  mode,
410
590
  status: deriveInstructionsStatus(normalizedEntries, normalizedActions),
411
591
  summary: buildInstructionsSummary(normalizedEntries, normalizedActions),
412
592
  entries: normalizedEntries,
413
593
  actions: normalizedActions,
594
+ // Both omitted when nothing is configured, so a repository with no
595
+ // documentation root keeps its existing payload shape exactly. Once
596
+ // `excludedPaths` is present its effective counterpart always is too, even
597
+ // when empty: "configured three, protected none" is precisely the state a
598
+ // consumer must be able to see, and omitting the field would hide it.
599
+ ...(normalizedExcludedPaths.length > 0
600
+ ? {
601
+ excludedPaths: normalizedExcludedPaths,
602
+ effectiveExcludedPaths: normalizedEffectivePaths,
603
+ }
604
+ : {}),
605
+ // Independent of the two fields above: an entry rejected during
606
+ // normalization produces a warning but no configured path, and that is
607
+ // exactly the case a JSON consumer must still be able to see.
608
+ ...(exclusionWarnings !== undefined && exclusionWarnings.length > 0
609
+ ? { exclusionWarnings }
610
+ : {}),
414
611
  };
415
612
  }
416
613
  export function formatInstructionsReport(payload, repoRoot) {
@@ -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;AAYnD,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;AA+SD,wBAAgB,6BAA6B,CAC3C,SAAS,GAAE,OAAO,CAAC,mCAAmC,CAAM,GAC3D,OAAO,CA6FT"}
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"}
@@ -2,7 +2,7 @@ import { lstat, readFile, 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, resolveInstructionSyncStrategy, scanInstructionFiles, } from '../../instructions/instructions.utils.js';
5
+ import { buildInstructionsPayload, DEFAULT_INSTRUCTION_SYNC_STRATEGY, EXPECTED_CLAUDE_CONTENT, formatInstructionsReport, resolveInstructionPointerExcludes, resolveInstructionSyncStrategy, scanInstructionFiles, } 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';
@@ -16,6 +16,7 @@ function defaultDependencies() {
16
16
  lstat,
17
17
  readFile,
18
18
  removeFile: removeInstructionFile,
19
+ resolveInstructionPointerExcludes,
19
20
  resolveProjectRoot,
20
21
  scanInstructionFiles,
21
22
  symlinkFile: async (target, path) => {
@@ -249,7 +250,14 @@ export function createInstructionsSyncCommand(overrides = {}) {
249
250
  try {
250
251
  const repoRoot = await dependencies.resolveProjectRoot(context.cwd);
251
252
  const strategy = resolveInstructionSyncStrategy(options.strategy);
253
+ const exclusions = await dependencies.resolveInstructionPointerExcludes(repoRoot);
254
+ // Warned before any work: an operator whose opt-out silently matches
255
+ // nothing must hear about it even when the sync then succeeds.
256
+ for (const warning of exclusions.warnings) {
257
+ context.logger.warn(warning);
258
+ }
252
259
  const entries = await dependencies.scanInstructionFiles(repoRoot, {
260
+ excludedPaths: exclusions.configured,
253
261
  strategy,
254
262
  });
255
263
  const plannedActions = planSyncActions({
@@ -267,6 +275,9 @@ export function createInstructionsSyncCommand(overrides = {}) {
267
275
  ? entries
268
276
  : getPostSyncEntries(entries, actions, strategy),
269
277
  actions,
278
+ excludedPaths: exclusions.configured,
279
+ effectiveExcludedPaths: exclusions.effective,
280
+ exclusionWarnings: exclusions.warnings,
270
281
  });
271
282
  if (context.json) {
272
283
  context.logger.json(payload);
@@ -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;AAWnD,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAU5C,wBAAgB,iCAAiC,CAC/C,SAAS,GAAE,OAAO,CAAC,uCAAuC,CAAM,GAC/D,OAAO,CA2DT"}
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,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, resolveInstructionSyncStrategy, scanInstructionFiles, } from '../../instructions/instructions.utils.js';
3
+ import { buildInstructionsPayload, DEFAULT_INSTRUCTION_SYNC_STRATEGY, formatInstructionsReport, 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,7 @@ import { Command, Option } from 'commander';
8
8
  function defaultDependencies() {
9
9
  return {
10
10
  buildCommandContext,
11
+ resolveInstructionPointerExcludes,
11
12
  resolveProjectRoot,
12
13
  scanInstructionFiles,
13
14
  };
@@ -27,13 +28,23 @@ export function createInstructionsValidateCommand(overrides = {}) {
27
28
  const strategy = resolveInstructionSyncStrategy(options.strategy);
28
29
  try {
29
30
  const repoRoot = await dependencies.resolveProjectRoot(context.cwd);
31
+ const exclusions = await dependencies.resolveInstructionPointerExcludes(repoRoot);
32
+ // Warned before any work: an operator whose opt-out silently matches
33
+ // nothing must hear about it even when validate then reports `ok`.
34
+ for (const warning of exclusions.warnings) {
35
+ context.logger.warn(warning);
36
+ }
30
37
  const entries = await dependencies.scanInstructionFiles(repoRoot, {
38
+ excludedPaths: exclusions.configured,
31
39
  strategy,
32
40
  });
33
41
  const payload = buildInstructionsPayload({
34
42
  mode: 'validate',
35
43
  entries,
36
44
  actions: [],
45
+ excludedPaths: exclusions.configured,
46
+ effectiveExcludedPaths: exclusions.effective,
47
+ exclusionWarnings: exclusions.warnings,
37
48
  });
38
49
  if (context.json) {
39
50
  context.logger.json(payload);
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/project/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAuBpC,wBAAgB,oBAAoB,IAAI,OAAO,CAuB9C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/project/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAwBpC,wBAAgB,oBAAoB,IAAI,OAAO,CAwB9C"}
@@ -11,6 +11,7 @@ import { createProjectMigrateCommand } from './migrate/index.js';
11
11
  import { createProjectNewCommand } from './new/index.js';
12
12
  import { createProjectOpenCommand } from './open/index.js';
13
13
  import { createProjectPauseCommand } from './pause/index.js';
14
+ import { createProjectPromoteCommand } from './promote/index.js';
14
15
  import { createProjectPruneCommand } from './prune/index.js';
15
16
  import { createProjectPullCommand } from './pull/index.js';
16
17
  import { createProjectPushCommand } from './push/index.js';
@@ -34,6 +35,7 @@ export function createProjectCommand() {
34
35
  .addCommand(createProjectNewCommand())
35
36
  .addCommand(createProjectOpenCommand())
36
37
  .addCommand(createProjectPauseCommand())
38
+ .addCommand(createProjectPromoteCommand())
37
39
  .addCommand(createProjectPruneCommand())
38
40
  .addCommand(createProjectPushCommand())
39
41
  .addCommand(createProjectPullCommand())
@@ -2,6 +2,176 @@ import { type CommandContext, type GlobalOptions } from '../../../app/command-co
2
2
  import { type ActiveProjectResolution } from '../../../config/oat-config.js';
3
3
  import { type ResolvedConfig } from '../../../config/resolve.js';
4
4
  import { Command } from 'commander';
5
+ export declare const PROJECT_LOG_FILENAME = "project-log.md";
6
+ /**
7
+ * Directory, relative to a project, that holds gate partial-finalization
8
+ * receipts. Ignored by the repository so a receipt never dirties the tree.
9
+ */
10
+ export declare const GATE_RECEIPTS_DIRNAME = "gate-receipts";
11
+ /**
12
+ * Bounded attempt budget for committing the project log across a transient
13
+ * `.git/index.lock`. Three attempts means exactly two waits, so the delays
14
+ * below are the whole window the persistent-versus-transient mtime comparison
15
+ * spans. Declared here rather than inline so the bound is reviewable and the
16
+ * gate and the recovery entry point share one budget.
17
+ */
18
+ export declare const PROJECT_LOG_COMMIT_ATTEMPTS = 3;
19
+ export declare const PROJECT_LOG_COMMIT_RETRY_DELAYS_MS: readonly number[];
20
+ /**
21
+ * Bounded wait for the advisory lock. Declared rather than inline so the bound
22
+ * is reviewable: a writer waits at most `WAIT_MS`, polling every `POLL_MS`, and
23
+ * treats a lock whose owner is gone — or that is older than `STALE_MS` — as
24
+ * abandoned.
25
+ */
26
+ export declare const PROJECT_LOG_LOCK_WAIT_MS = 5000;
27
+ export declare const PROJECT_LOG_LOCK_POLL_MS = 25;
28
+ export declare const PROJECT_LOG_LOCK_STALE_MS = 30000;
29
+ export interface ProjectLogLockDependencies {
30
+ waitMs: number;
31
+ pollMs: number;
32
+ staleMs: number;
33
+ sleep: (ms: number) => Promise<void>;
34
+ now: () => number;
35
+ }
36
+ export declare function projectLogLockPath(logPath: string): string;
37
+ export type GitLockFailureClass = 'transient-index-lock' | 'persistent-index-lock' | 'other';
38
+ export type ProjectLogCommitOutcome = 'committed' | 'already-committed' | 'nothing-to-commit' | 'not-a-repo' | 'blocked-by-index-lock' | 'entry-missing-after-commit' | 'commit-unverified' | 'failed';
39
+ export interface ProjectLogCommitResult {
40
+ outcome: ProjectLogCommitOutcome;
41
+ committed: boolean;
42
+ attempts: number;
43
+ error?: string;
44
+ lockClass?: GitLockFailureClass;
45
+ }
46
+ export interface CommitProjectLogInput {
47
+ repoRoot: string;
48
+ logPath: string;
49
+ message?: string;
50
+ /**
51
+ * Identity of the entry this commit is finalizing: the idempotency key plus
52
+ * the body it was written in, which together name the exact token to look
53
+ * for. Supplied so a settled outcome is proven rather than inferred — a clean
54
+ * log whose content still carries this entry is a log whose HEAD content
55
+ * carries it too.
56
+ */
57
+ identity?: {
58
+ key: string;
59
+ body: string;
60
+ };
61
+ }
62
+ export interface CommitProjectLogDependencies {
63
+ attempts: number;
64
+ retryDelaysMs: readonly number[];
65
+ sleep: (ms: number) => Promise<void>;
66
+ /**
67
+ * Advisory-lock overrides. Kept separate from `sleep` above, which is the
68
+ * index-lock retry delay: the two waits are different bounds and a caller
69
+ * that observes one must not be told about the other.
70
+ */
71
+ lock: Partial<ProjectLogLockDependencies>;
72
+ /**
73
+ * Git runner for this path. Injectable so a control can make one command
74
+ * fail — the committed-log read back is allowed to be unavailable, and what
75
+ * happens then has to be provable rather than asserted.
76
+ */
77
+ runGit: (repoRoot: string, args: string[]) => string;
78
+ }
79
+ /**
80
+ * Classifies a failed git invocation as an index-lock contention or a real
81
+ * failure.
82
+ *
83
+ * Only a stderr that actually names `index.lock` is lock contention; every
84
+ * other failure (hook, signing, identity, pathspec) stays `other` so it is
85
+ * reported rather than retried and swallowed. A lock is `persistent` only when
86
+ * its mtime is unchanged across the whole retry window, which is why the
87
+ * caller passes the mtime it observed on the first lock failure.
88
+ */
89
+ export declare function classifyGitLockFailure(stderr: string, lockPath: string, firstObservedMtimeMs?: number): GitLockFailureClass;
90
+ /**
91
+ * Whether the log *as committed at HEAD* carries a given entry identity.
92
+ *
93
+ * `unknown` is a first-class answer, and it is never read as `absent`: a
94
+ * repository with no HEAD, a log that has never been committed, or a git
95
+ * invocation that fails for an environmental reason all say nothing about the
96
+ * entry, and turning that silence into "the entry is gone" would manufacture
97
+ * failures out of missing evidence.
98
+ */
99
+ export type CommittedLogIdentityState = 'present' | 'absent' | 'unknown';
100
+ /**
101
+ * Whether the committed log carries `key`.
102
+ *
103
+ * Exported for callers that must distinguish finished finalization from
104
+ * unfinished finalization — the gate's receipt classifier among them — so that
105
+ * question is answered by this module rather than by a caller opening
106
+ * `project-log.md` itself (DR-260718).
107
+ */
108
+ export declare function committedProjectLogIdentityState(repoRoot: string, logPath: string, key: string, body?: string): Promise<CommittedLogIdentityState>;
109
+ /**
110
+ * Stages and commits `project-log.md`, retrying a bounded number of times when
111
+ * the failure is a transient `.git/index.lock`.
112
+ *
113
+ * The log is tracked, so an uncommitted append leaves the worktree dirty for
114
+ * whatever runs next — including a dispatched subagent whose preflight requires
115
+ * a clean tree. The commit is pathspec-scoped to the log alone so unrelated
116
+ * working-tree changes are never swept in.
117
+ *
118
+ * Scope note: this commits the whole log file, so a log that was already dirty
119
+ * before the caller ran is committed along with this entry. That is deliberate
120
+ * — leaving the earlier append uncommitted would reproduce the dirty tree this
121
+ * exists to prevent — but it does mean the commit is not always exactly one
122
+ * entry.
123
+ *
124
+ * Never throws, and never deletes, moves, or forces an index lock: a lock this
125
+ * process did not take is another process's, and only its owner may clear it.
126
+ * Git failures are reported to the caller, which degrades to a diagnostic
127
+ * rather than altering any exit status. On failure the index is restored so a
128
+ * partially staged log is not left behind.
129
+ *
130
+ * Exactly one outcome is derived from a single pre-action snapshot (entry HEAD
131
+ * plus entry dirtiness) rather than from eligibility re-sampled after the
132
+ * action, so a log another writer committed mid-retry reads as
133
+ * `already-committed` instead of a spurious failure.
134
+ */
135
+ export declare function commitProjectLog(input: CommitProjectLogInput, overrides?: Partial<CommitProjectLogDependencies>): Promise<ProjectLogCommitResult>;
136
+ /**
137
+ * Returns the heading of the first existing entry whose body already carries
138
+ * this idempotency identity, or undefined when the log has no such entry.
139
+ *
140
+ * With `body` supplied the match is the exact whole-word token derived from it;
141
+ * without one — the advisory staleness check, which has only a run id — any
142
+ * word containing `key` counts. Callers that must not duplicate an entry always
143
+ * pass the body.
144
+ *
145
+ * The scan lives here, in the log module, because log reads and mutations are
146
+ * CLI-owned (DR-260718); callers such as the gate never open `project-log.md`
147
+ * themselves.
148
+ */
149
+ export declare function findProjectLogEntryByIdempotencyKey(content: string, key: string, body?: string): string | undefined;
150
+ /**
151
+ * Durable record of a gate project-log append that was written but could not be
152
+ * committed. It carries everything the recovery command needs to finish the
153
+ * finalization from a later process, and enough identity to refuse when the
154
+ * tree it describes is no longer the tree it is replayed against.
155
+ */
156
+ export interface GateProjectLogReceipt {
157
+ runId: string;
158
+ project: string;
159
+ projectPath: string;
160
+ worktreeRoot: string;
161
+ logPath: string;
162
+ artifactPath: string | null;
163
+ artifactSignature: string | null;
164
+ appendStatus: 'appended' | 'already-appended';
165
+ commitStatus: ProjectLogCommitOutcome;
166
+ lockClass: GitLockFailureClass | null;
167
+ attempts: number;
168
+ producer: string;
169
+ ref: string;
170
+ body: string;
171
+ recovery: {
172
+ command: string;
173
+ };
174
+ }
5
175
  export interface AppendProjectLogInput {
6
176
  repoRoot: string;
7
177
  home?: string;
@@ -14,12 +184,18 @@ export interface AppendProjectLogInput {
14
184
  ref?: string;
15
185
  body?: string;
16
186
  versionNote?: string;
187
+ idempotencyKey?: string;
17
188
  }
18
189
  export type ProjectLogAppendResult = {
19
190
  status: 'appended';
20
191
  logPath: string;
21
192
  heading: string;
22
193
  created: boolean;
194
+ } | {
195
+ status: 'already-appended';
196
+ logPath: string;
197
+ heading: string;
198
+ created: false;
23
199
  } | {
24
200
  status: 'skipped';
25
201
  reason: 'projectLog=false';
@@ -29,6 +205,16 @@ export interface AppendProjectLogDependencies {
29
205
  resolveEffectiveConfig: (repoRoot: string, userConfigDir: string, env?: NodeJS.ProcessEnv) => Promise<ResolvedConfig>;
30
206
  resolveAssetsRoot: () => Promise<string>;
31
207
  now: () => Date;
208
+ /**
209
+ * The log's own read/modify/write primitives. Injectable so a test can hold
210
+ * one writer inside the window while another enters it, which is the only way
211
+ * to prove the serialization rather than assert it.
212
+ */
213
+ readLog: (path: string) => Promise<string>;
214
+ writeLog: (path: string, content: string) => Promise<void>;
215
+ appendLog: (path: string, content: string) => Promise<void>;
216
+ /** Advisory-lock overrides for the append window. */
217
+ lock: Partial<ProjectLogLockDependencies>;
32
218
  }
33
219
  export interface ProjectLogAppendCommandDependencies extends AppendProjectLogDependencies {
34
220
  buildCommandContext: (options: GlobalOptions) => CommandContext;
@@ -36,6 +222,15 @@ export interface ProjectLogAppendCommandDependencies extends AppendProjectLogDep
36
222
  readStdin: () => Promise<string>;
37
223
  }
38
224
  export declare function instantiateProjectLogTemplate(template: string, projectName: string, date: string): string;
225
+ /**
226
+ * Appends one entry to the project log, at most once per idempotency key.
227
+ *
228
+ * The existence check, the idempotency scan, the template instantiation, and
229
+ * the write are one critical section under the log's advisory lock. Separating
230
+ * the scan from the mutation is what let two overlapping writers both pass the
231
+ * scan and then lose one entry to the other's stale rewrite, so they are not
232
+ * separable here.
233
+ */
39
234
  export declare function appendProjectLog(input: AppendProjectLogInput, overrides?: Partial<AppendProjectLogDependencies>): Promise<ProjectLogAppendResult>;
40
235
  export declare function createProjectLogAppendCommand(overrides?: Partial<ProjectLogAppendCommandDependencies>): Command;
41
236
  //# sourceMappingURL=append.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"append.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/log/append.ts"],"names":[],"mappings":"AAIA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAEL,KAAK,uBAAuB,EAC7B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAA0B,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAI9E,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkBpC,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,MAAM,sBAAsB,GAC9B;IACE,MAAM,EAAE,UAAU,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;CAClB,GACD;IACE,MAAM,EAAE,SAAS,CAAC;IAClB,MAAM,EAAE,kBAAkB,CAAC;CAC5B,CAAC;AAEN,MAAM,WAAW,4BAA4B;IAC3C,oBAAoB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,uBAAuB,CAAC,CAAC;IAC7E,sBAAsB,EAAE,CACtB,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,KACpB,OAAO,CAAC,cAAc,CAAC,CAAC;IAC7B,iBAAiB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACzC,GAAG,EAAE,MAAM,IAAI,CAAC;CACjB;AAqBD,MAAM,WAAW,mCAAoC,SAAQ,4BAA4B;IACvF,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,SAAS,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;CAClC;AA4LD,wBAAgB,6BAA6B,CAC3C,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,GACX,MAAM,CAOR;AAiCD,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,qBAAqB,EAC5B,SAAS,GAAE,OAAO,CAAC,4BAA4B,CAAM,GACpD,OAAO,CAAC,sBAAsB,CAAC,CAoCjC;AAsCD,wBAAgB,6BAA6B,CAC3C,SAAS,GAAE,OAAO,CAAC,mCAAmC,CAAM,GAC3D,OAAO,CA8CT"}
1
+ {"version":3,"file":"append.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/log/append.ts"],"names":[],"mappings":"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"}