@open-agent-toolkit/cli 0.3.21 → 0.3.22

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 (114) hide show
  1. package/assets/bundle-metadata.json +1 -1
  2. package/assets/docs/reference/cli-reference.md +8 -3
  3. package/assets/docs/reference/configuration.md +3 -0
  4. package/assets/docs/reference/oat-directory-structure.md +1 -1
  5. package/assets/docs/reference/project-artifacts.md +141 -2
  6. package/assets/docs/reference/project-state-machine.md +2 -2
  7. package/assets/docs/workflows/advanced/autonomy.md +29 -12
  8. package/assets/docs/workflows/advanced/cursor-cloud.md +20 -6
  9. package/assets/docs/workflows/advanced/workflow-gates.md +9 -0
  10. package/assets/docs/workflows/projects/closeout/closeout-skills.md +24 -5
  11. package/assets/docs/workflows/projects/closeout/retro.md +6 -2
  12. package/assets/docs/workflows/projects/execution/implementation-execution.md +18 -4
  13. package/assets/docs/workflows/projects/execution/index.md +1 -1
  14. package/assets/docs/workflows/projects/execution/picking-up-projects.md +3 -2
  15. package/assets/docs/workflows/projects/execution/project-log.md +100 -11
  16. package/assets/docs/workflows/projects/lifecycle.md +3 -3
  17. package/assets/docs/workflows/projects/reviews/index.md +18 -0
  18. package/assets/public-package-versions.json +4 -4
  19. package/assets/skills/oat-cursor-cloud-projects/SKILL.md +12 -8
  20. package/assets/skills/oat-cursor-cloud-projects/references/cursor-cloud-mechanics.md +63 -2
  21. package/assets/skills/oat-project-autonomous/SKILL.md +88 -26
  22. package/assets/skills/oat-project-autonomous/references/gate-inventory.md +1 -1
  23. package/assets/skills/oat-project-brief/SKILL.md +1 -1
  24. package/assets/skills/oat-project-brief/references/brief-contract.md +33 -27
  25. package/assets/skills/oat-project-brief/references/docs/autonomy-contract.md +1 -1
  26. package/assets/skills/oat-project-complete/SKILL.md +142 -25
  27. package/assets/skills/oat-project-complete-auto/SKILL.md +4 -4
  28. package/assets/skills/oat-project-dispatch-subagents/SKILL.md +10 -5
  29. package/assets/skills/oat-project-document/SKILL.md +1 -1
  30. package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +1 -1
  31. package/assets/skills/oat-project-goal/SKILL.md +63 -15
  32. package/assets/skills/oat-project-goal/references/docs/autonomy-contract.md +1 -1
  33. package/assets/skills/oat-project-implement/SKILL.md +6 -6
  34. package/assets/skills/oat-project-implement/references/completion-and-closeout.md +28 -7
  35. package/assets/skills/oat-project-implement/references/dispatch-and-dry-run.md +10 -5
  36. package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +1 -1
  37. package/assets/skills/oat-project-implement/references/phase-execution.md +23 -9
  38. package/assets/skills/oat-project-implement/references/plan-and-resume.md +4 -4
  39. package/assets/skills/oat-project-lite/SKILL.md +1 -1
  40. package/assets/skills/oat-project-lite/references/docs/autonomy-contract.md +1 -1
  41. package/assets/skills/oat-project-pr-final/SKILL.md +6 -1
  42. package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +1 -1
  43. package/assets/skills/oat-project-pr-progress/SKILL.md +6 -1
  44. package/assets/skills/oat-project-quick-start/SKILL.md +1 -1
  45. package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +1 -1
  46. package/assets/skills/oat-project-reconcile/SKILL.md +13 -19
  47. package/assets/skills/oat-project-retro/SKILL.md +5 -2
  48. package/assets/skills/oat-project-retro/references/evidence-and-lanes.md +9 -3
  49. package/assets/skills/oat-project-review-provide/SKILL.md +28 -3
  50. package/assets/skills/oat-project-review-receive/SKILL.md +32 -18
  51. package/assets/skills/oat-project-review-receive-remote/SKILL.md +10 -6
  52. package/assets/skills/oat-project-revise/SKILL.md +9 -2
  53. package/assets/skills/oat-project-summary/SKILL.md +166 -37
  54. package/assets/skills/oat-worktree-bootstrap-auto/SKILL.md +3 -3
  55. package/assets/templates/implementation-brief.md +5 -36
  56. package/assets/templates/implementation.md +11 -81
  57. package/assets/templates/project-log.md +2 -31
  58. package/assets/templates/project-retro.md +4 -1
  59. package/assets/templates/summary.md +13 -5
  60. package/dist/commands/config/index.d.ts.map +1 -1
  61. package/dist/commands/config/index.js +44 -1
  62. package/dist/commands/project/archive/archive-utils.d.ts +205 -8
  63. package/dist/commands/project/archive/archive-utils.d.ts.map +1 -1
  64. package/dist/commands/project/archive/archive-utils.js +708 -44
  65. package/dist/commands/project/archive/index.d.ts.map +1 -1
  66. package/dist/commands/project/archive/index.js +1 -0
  67. package/dist/commands/project/archive/push-runner.d.ts +9 -1
  68. package/dist/commands/project/archive/push-runner.d.ts.map +1 -1
  69. package/dist/commands/project/archive/push-runner.js +56 -18
  70. package/dist/commands/project/archive/sync-runner.d.ts +28 -0
  71. package/dist/commands/project/archive/sync-runner.d.ts.map +1 -1
  72. package/dist/commands/project/archive/sync-runner.js +44 -22
  73. package/dist/commands/project/complete-state/index.d.ts.map +1 -1
  74. package/dist/commands/project/complete-state/index.js +45 -0
  75. package/dist/commands/project/dispatch/index.d.ts.map +1 -1
  76. package/dist/commands/project/dispatch/index.js +24 -2
  77. package/dist/commands/project/dispatch/record.d.ts +54 -1
  78. package/dist/commands/project/dispatch/record.d.ts.map +1 -1
  79. package/dist/commands/project/dispatch/record.js +229 -1
  80. package/dist/commands/project/index.d.ts.map +1 -1
  81. package/dist/commands/project/index.js +2 -0
  82. package/dist/commands/project/journal-check/evaluator.d.ts +17 -0
  83. package/dist/commands/project/journal-check/evaluator.d.ts.map +1 -0
  84. package/dist/commands/project/journal-check/evaluator.js +140 -0
  85. package/dist/commands/project/journal-check/index.d.ts +34 -0
  86. package/dist/commands/project/journal-check/index.d.ts.map +1 -0
  87. package/dist/commands/project/journal-check/index.js +163 -0
  88. package/dist/commands/project/journal-check/rules.d.ts +68 -0
  89. package/dist/commands/project/journal-check/rules.d.ts.map +1 -0
  90. package/dist/commands/project/journal-check/rules.js +994 -0
  91. package/dist/commands/project/journal-check/types.d.ts +63 -0
  92. package/dist/commands/project/journal-check/types.d.ts.map +1 -0
  93. package/dist/commands/project/journal-check/types.js +26 -0
  94. package/dist/commands/project/log/append.d.ts +6 -0
  95. package/dist/commands/project/log/append.d.ts.map +1 -1
  96. package/dist/commands/project/log/append.js +114 -6
  97. package/dist/commands/project/log/check.d.ts +23 -1
  98. package/dist/commands/project/log/check.d.ts.map +1 -1
  99. package/dist/commands/project/log/check.js +20 -3
  100. package/dist/commands/project/log/grammar.d.ts +37 -0
  101. package/dist/commands/project/log/grammar.d.ts.map +1 -1
  102. package/dist/commands/project/log/grammar.js +72 -0
  103. package/dist/commands/project/log/rollup.d.ts +87 -1
  104. package/dist/commands/project/log/rollup.d.ts.map +1 -1
  105. package/dist/commands/project/log/rollup.js +257 -5
  106. package/dist/config/oat-config.d.ts +14 -0
  107. package/dist/config/oat-config.d.ts.map +1 -1
  108. package/dist/config/oat-config.js +17 -0
  109. package/dist/config/resolve.d.ts.map +1 -1
  110. package/dist/config/resolve.js +5 -1
  111. package/dist/providers/identity/generic-dispatch-record.d.ts +33 -0
  112. package/dist/providers/identity/generic-dispatch-record.d.ts.map +1 -1
  113. package/dist/providers/identity/generic-dispatch-record.js +60 -1
  114. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/archive/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAIL,KAAK,qCAAqC,EAC3C,MAAM,eAAe,CAAC;AACvB,OAAO,EAIL,KAAK,iCAAiC,EACvC,MAAM,eAAe,CAAC;AAEvB,YAAY,EACV,kBAAkB,EAClB,iCAAiC,GAClC,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,kBAAkB,EAClB,qCAAqC,GACtC,MAAM,eAAe,CAAC;AAEvB,KAAK,0BAA0B,GAAG,iCAAiC,GACjE,qCAAqC,CAAC;AAKxC,wBAAgB,2BAA2B,CACzC,SAAS,GAAE,OAAO,CAAC,0BAA0B,CAAM,GAClD,OAAO,CAiFT"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/archive/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAIL,KAAK,qCAAqC,EAC3C,MAAM,eAAe,CAAC;AACvB,OAAO,EAIL,KAAK,iCAAiC,EACvC,MAAM,eAAe,CAAC;AAEvB,YAAY,EACV,kBAAkB,EAClB,iCAAiC,GAClC,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,kBAAkB,EAClB,qCAAqC,GACtC,MAAM,eAAe,CAAC;AAEvB,KAAK,0BAA0B,GAAG,iCAAiC,GACjE,qCAAqC,CAAC;AAKxC,wBAAgB,2BAA2B,CACzC,SAAS,GAAE,OAAO,CAAC,0BAA0B,CAAM,GAClD,OAAO,CAqFT"}
@@ -15,6 +15,7 @@ export function createProjectArchiveCommand(overrides = {}) {
15
15
  .option('--dry-run', 'Preview archive without moving files or syncing S3')
16
16
  .option('--no-commit', 'Manual/library use only: omit the synced lifecycle commit receipt')
17
17
  .option('--project-recap-run <path>', 'Export the selected project-relative recap run before archiving')
18
+ .option('--new-generation <reason>', 'Archive reopened work as the next generation of an archived shared or local project (requires exactly one predecessor)')
18
19
  .addHelpText('afterAll', '\nPull archived project data with `oat repo archive sync [project-name]`; `oat project archive sync` is deprecated.')
19
20
  .action(async (projectPath, options, command) => {
20
21
  const context = dependencies.buildCommandContext(readGlobalOptions(command));
@@ -1,11 +1,13 @@
1
1
  import { buildCommandContext, type CommandContext } from '../../../app/command-context.js';
2
2
  import { readSyncedRecord } from '../../project/sync/record.js';
3
3
  import { type OatConfig, type OatLocalConfig } from '../../../config/oat-config.js';
4
- import { assertExactArchiveProjectRoot, resolveArchiveProjectTarget, resolvePrimaryRepoRoot, verifySelectedProjectRecapForArchive, type ArchiveProjectOnCompletionOptions, type ArchiveProjectOnCompletionResult } from './archive-utils.js';
4
+ import { assertExactArchiveProjectRoot, resolveArchiveProjectTarget, resolvePrimaryRepoRoot, verifySelectedProjectRecapForArchive, type RecordlessSyncedArchiveIdentity, type ArchiveProjectOnCompletionOptions, type ArchiveProjectOnCompletionResult } from './archive-utils.js';
5
5
  export interface ArchivePushOptions {
6
6
  dryRun?: boolean;
7
7
  projectRecapRun?: string;
8
8
  commit?: boolean;
9
+ /** `--new-generation <reason>`. */
10
+ newGeneration?: string;
9
11
  }
10
12
  export interface ProjectArchivePushCommandDependencies {
11
13
  buildCommandContext: (options: Parameters<typeof buildCommandContext>[0]) => CommandContext;
@@ -21,6 +23,12 @@ export interface ProjectArchivePushCommandDependencies {
21
23
  assertExactArchiveProjectRoot: typeof assertExactArchiveProjectRoot;
22
24
  processEnv: NodeJS.ProcessEnv;
23
25
  timestamp: () => string;
26
+ /** Recordless synced identity through the completed ref; defaults to the shared resolver. */
27
+ resolveRecordlessSyncedArchiveIdentity?: (options: {
28
+ repoRoot: string;
29
+ projectsRoot: string;
30
+ projectName: string;
31
+ }) => Promise<RecordlessSyncedArchiveIdentity>;
24
32
  }
25
33
  export declare function defaultProjectArchivePushCommandDependencies(): ProjectArchivePushCommandDependencies;
26
34
  export declare function runArchivePushCommand(dependencies: ProjectArchivePushCommandDependencies, projectPathArg: string | undefined, options: ArchivePushOptions, context: CommandContext): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"push-runner.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/archive/push-runner.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAChF,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAOjE,OAAO,EAGL,KAAK,SAAS,EACd,KAAK,cAAc,EACpB,MAAM,oBAAoB,CAAC;AAI5B,OAAO,EAEL,6BAA6B,EAI7B,2BAA2B,EAC3B,sBAAsB,EACtB,oCAAoC,EAEpC,KAAK,iCAAiC,EACtC,KAAK,gCAAgC,EAEtC,MAAM,iBAAiB,CAAC;AAEzB,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,qCAAqC;IACpD,mBAAmB,EAAE,CACnB,OAAO,EAAE,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC,CAAC,CAAC,KAC/C,cAAc,CAAC;IACpB,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;IACxD,kBAAkB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;IAClE,mBAAmB,EAAE,CACnB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,CAAC,UAAU,KACnB,OAAO,CAAC,MAAM,CAAC,CAAC;IACrB,sBAAsB,EAAE,OAAO,sBAAsB,CAAC;IACtD,2BAA2B,EAAE,OAAO,2BAA2B,CAAC;IAChE,gBAAgB,EAAE,OAAO,gBAAgB,CAAC;IAC1C,oCAAoC,EAAE,OAAO,oCAAoC,CAAC;IAClF,0BAA0B,EAAE,CAC1B,OAAO,EAAE,iCAAiC,KACvC,OAAO,CAAC,gCAAgC,CAAC,CAAC;IAC/C,6BAA6B,EAAE,OAAO,6BAA6B,CAAC;IACpE,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC;IAC9B,SAAS,EAAE,MAAM,MAAM,CAAC;CACzB;AA0BD,wBAAgB,4CAA4C,IAAI,qCAAqC,CAgBpG;AA8JD,wBAAsB,qBAAqB,CACzC,YAAY,EAAE,qCAAqC,EACnD,cAAc,EAAE,MAAM,GAAG,SAAS,EAClC,OAAO,EAAE,kBAAkB,EAC3B,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,IAAI,CAAC,CAmHf"}
1
+ {"version":3,"file":"push-runner.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/archive/push-runner.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEhF,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAQjE,OAAO,EAGL,KAAK,SAAS,EACd,KAAK,cAAc,EACpB,MAAM,oBAAoB,CAAC;AAI5B,OAAO,EAGL,6BAA6B,EAK7B,2BAA2B,EAE3B,sBAAsB,EACtB,oCAAoC,EAEpC,KAAK,+BAA+B,EACpC,KAAK,iCAAiC,EACtC,KAAK,gCAAgC,EAEtC,MAAM,iBAAiB,CAAC;AAEzB,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,mCAAmC;IACnC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,qCAAqC;IACpD,mBAAmB,EAAE,CACnB,OAAO,EAAE,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC,CAAC,CAAC,KAC/C,cAAc,CAAC;IACpB,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;IACxD,kBAAkB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;IAClE,mBAAmB,EAAE,CACnB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,CAAC,UAAU,KACnB,OAAO,CAAC,MAAM,CAAC,CAAC;IACrB,sBAAsB,EAAE,OAAO,sBAAsB,CAAC;IACtD,2BAA2B,EAAE,OAAO,2BAA2B,CAAC;IAChE,gBAAgB,EAAE,OAAO,gBAAgB,CAAC;IAC1C,oCAAoC,EAAE,OAAO,oCAAoC,CAAC;IAClF,0BAA0B,EAAE,CAC1B,OAAO,EAAE,iCAAiC,KACvC,OAAO,CAAC,gCAAgC,CAAC,CAAC;IAC/C,6BAA6B,EAAE,OAAO,6BAA6B,CAAC;IACpE,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC;IAC9B,SAAS,EAAE,MAAM,MAAM,CAAC;IACxB,6FAA6F;IAC7F,sCAAsC,CAAC,EAAE,CAAC,OAAO,EAAE;QACjD,QAAQ,EAAE,MAAM,CAAC;QACjB,YAAY,EAAE,MAAM,CAAC;QACrB,WAAW,EAAE,MAAM,CAAC;KACrB,KAAK,OAAO,CAAC,+BAA+B,CAAC,CAAC;CAChD;AA4BD,wBAAgB,4CAA4C,IAAI,qCAAqC,CAgBpG;AAiLD,wBAAsB,qBAAqB,CACzC,YAAY,EAAE,qCAAqC,EACnD,cAAc,EAAE,MAAM,GAAG,SAAS,EAClC,OAAO,EAAE,kBAAkB,EAC3B,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,IAAI,CAAC,CAoJf"}
@@ -1,12 +1,14 @@
1
1
  import { basename, isAbsolute, join } from 'node:path';
2
2
  import { buildCommandContext } from '../../../app/command-context.js';
3
+ import { defaultGitRunner } from '../../project/sync/git.js';
3
4
  import { readSyncedRecord } from '../../project/sync/record.js';
5
+ import { buildSyncTarget } from '../../project/sync/ref-sync.js';
4
6
  import { resolveProjectsRoot } from '../../shared/oat-paths.js';
5
7
  import { resolveScopeRoot, syncedRecordPath, } from '../../shared/project-scope.js';
6
8
  import { readOatConfig, readOatLocalConfig, } from '../../../config/oat-config.js';
7
9
  import { CliError } from '../../../errors/cli-error.js';
8
10
  import { resolveProjectRoot } from '../../../fs/paths.js';
9
- import { archiveProjectOnCompletion, assertExactArchiveProjectRoot, assertDurableArchiveProjectTarget, buildArchiveSnapshotName, buildProjectArchiveS3Uri, resolveArchiveProjectTarget, resolvePrimaryRepoRoot, verifySelectedProjectRecapForArchive, } from './archive-utils.js';
11
+ import { ArchiveIdentityError, archiveProjectOnCompletion, assertExactArchiveProjectRoot, assertDurableArchiveProjectTarget, buildProjectArchiveS3Uri, evaluateArchiveRetryIdentity, newGenerationReplayWarning, resolveArchiveProjectTarget, resolveRecordlessSyncedArchiveIdentity, resolvePrimaryRepoRoot, verifySelectedProjectRecapForArchive, } from './archive-utils.js';
10
12
  export function defaultProjectArchivePushCommandDependencies() {
11
13
  return {
12
14
  buildCommandContext,
@@ -58,9 +60,16 @@ function buildArchiveOptions(repoRoot, config, projectsRoot, target, options) {
58
60
  awsProfile: config.archive?.awsProfile,
59
61
  awsRegion: config.archive?.awsRegion,
60
62
  ...(options.commit === false ? { commit: false } : {}),
63
+ ...(options.newGeneration !== undefined
64
+ ? { newGenerationReason: options.newGeneration }
65
+ : {}),
61
66
  };
62
67
  }
63
- async function buildDryRunReport(dependencies, repoRoot, config, target, archiveTarget, snapshotName, projectScope) {
68
+ async function buildDryRunReport(dependencies, repoRoot, config, target, identity, projectScope, newGenerationReason) {
69
+ // Every reported destination comes from the shared retry-identity
70
+ // evaluator, so an identical retry previews the persisted snapshot it would
71
+ // reuse rather than a new identity derived from today's date.
72
+ const snapshotName = identity.snapshotName;
64
73
  const remoteRepoRoot = await dependencies.resolvePrimaryRepoRoot(repoRoot);
65
74
  const s3Path = config.archive?.s3Uri && config.archive.s3SyncOnComplete === true
66
75
  ? buildProjectArchiveS3Uri(config.archive.s3Uri, remoteRepoRoot, snapshotName)
@@ -73,19 +82,21 @@ async function buildDryRunReport(dependencies, repoRoot, config, target, archive
73
82
  mode: 'dry-run',
74
83
  projectName: target.projectName,
75
84
  projectPath: target.projectPath,
76
- archivePath: archiveTarget.archivePath,
85
+ archivePath: identity.archivePath,
77
86
  s3Path,
78
87
  summaryExportFile,
79
- warnings: [],
88
+ warnings: [
89
+ newGenerationReplayWarning(identity, newGenerationReason),
90
+ ].filter((warning) => warning !== null),
80
91
  lifecycleCommit: null,
81
92
  recapExportPaths: [],
82
- snapshotId: projectScope === 'synced'
83
- ? snapshotName
84
- : basename(archiveTarget.archivePath),
93
+ snapshotId: projectScope === 'synced' ? snapshotName : basename(identity.archivePath),
85
94
  completedRef: null,
86
95
  verifiedSourceSha: null,
87
96
  activeAliasDisposition: null,
88
97
  recordRetired: false,
98
+ generation: identity.generation,
99
+ predecessorSnapshot: identity.predecessor,
89
100
  };
90
101
  }
91
102
  function emitArchivePushText(report, summaryExportPath, logger) {
@@ -94,6 +105,9 @@ function emitArchivePushText(report, summaryExportPath, logger) {
94
105
  }
95
106
  if (report.mode === 'dry-run') {
96
107
  logger.info(`Dry-run: would archive project \`${report.projectName}\` from \`${report.projectPath}\` to \`${report.archivePath}\`.`);
108
+ if (report.predecessorSnapshot) {
109
+ logger.info(`Generation ${report.generation} after \`${report.predecessorSnapshot}\`.`);
110
+ }
97
111
  if (report.s3Path) {
98
112
  logger.info(`S3 archive: ${report.s3Path}`);
99
113
  }
@@ -103,6 +117,9 @@ function emitArchivePushText(report, summaryExportPath, logger) {
103
117
  return;
104
118
  }
105
119
  logger.info(`Archived project \`${report.projectName}\` to \`${report.archivePath}\`.`);
120
+ if (report.predecessorSnapshot) {
121
+ logger.info(`Generation ${report.generation} after \`${report.predecessorSnapshot}\`.`);
122
+ }
106
123
  if (report.s3Path) {
107
124
  logger.info(`S3 archive: ${report.s3Path}`);
108
125
  }
@@ -133,33 +150,44 @@ export async function runArchivePushCommand(dependencies, projectPathArg, option
133
150
  projectName: target.projectName,
134
151
  projectsRoot,
135
152
  });
136
- const defaultSnapshotName = buildArchiveSnapshotName(target.projectName, dependencies.timestamp());
137
153
  const syncedRecord = projectScope === 'synced'
138
154
  ? await dependencies.readSyncedRecord(syncedRecordPath(resolveScopeRoot(repoRoot, projectsRoot, 'synced'), target.projectName))
139
155
  : null;
140
- const snapshotName = syncedRecord?.archiveSnapshot ?? defaultSnapshotName;
141
- const archiveTarget = await dependencies.resolveArchiveProjectTarget({
156
+ // A recordless synced project binds its snapshot through the completed
157
+ // ref, in dry-run exactly as in apply.
158
+ const recordless = projectScope === 'synced' && syncedRecord === null
159
+ ? await (dependencies.resolveRecordlessSyncedArchiveIdentity ??
160
+ ((resolverOptions) => resolveRecordlessSyncedArchiveIdentity(resolverOptions, buildSyncTarget(resolverOptions.repoRoot, resolverOptions.projectsRoot, resolverOptions.projectName), defaultGitRunner, { env: dependencies.processEnv })))({ repoRoot, projectsRoot, projectName: target.projectName })
161
+ : null;
162
+ const persistedSnapshot = syncedRecord?.archiveSnapshot ?? recordless?.metadata.snapshotName;
163
+ const persistedSourceRefSha = syncedRecord?.archiveSourceRefSha ?? recordless?.metadata.sourceRefSha;
164
+ const identity = await evaluateArchiveRetryIdentity({
142
165
  repoRoot,
143
166
  projectsRoot,
144
167
  projectName: target.projectName,
145
- ...(syncedRecord?.archiveSnapshot
146
- ? {
147
- archiveSnapshot: syncedRecord.archiveSnapshot,
148
- archiveScope: projectScope ?? undefined,
149
- }
168
+ projectPath: target.projectPath,
169
+ scope: projectScope,
170
+ timestamp: dependencies.timestamp(),
171
+ ...(persistedSnapshot ? { persistedSnapshot } : {}),
172
+ ...(persistedSourceRefSha
173
+ ? { sourceRefSha: persistedSourceRefSha }
174
+ : {}),
175
+ ...(options.newGeneration !== undefined
176
+ ? { newGeneration: { reason: options.newGeneration } }
150
177
  : {}),
151
178
  }, {
179
+ resolveArchiveProjectTarget: dependencies.resolveArchiveProjectTarget,
152
180
  env: dependencies.processEnv,
153
181
  timestamp: dependencies.timestamp,
154
182
  });
155
- assertDurableArchiveProjectTarget(archiveTarget);
183
+ assertDurableArchiveProjectTarget(identity.target);
156
184
  const dryRun = options.dryRun === true || context.dryRun;
157
185
  const recordlessSyncedApply = projectScope === 'synced' && syncedRecord === null && !dryRun;
158
186
  if (options.projectRecapRun?.trim() && !recordlessSyncedApply) {
159
187
  await dependencies.verifySelectedProjectRecapForArchive(target.projectPath, options.projectRecapRun.trim());
160
188
  }
161
189
  if (dryRun) {
162
- const report = await buildDryRunReport(dependencies, repoRoot, config, target, archiveTarget, snapshotName, projectScope);
190
+ const report = await buildDryRunReport(dependencies, repoRoot, config, target, identity, projectScope, options.newGeneration);
163
191
  emitArchivePushReport(report, config.archive?.summaryExportPath, context);
164
192
  process.exitCode = 0;
165
193
  return;
@@ -188,6 +216,12 @@ export async function runArchivePushCommand(dependencies, projectPathArg, option
188
216
  : 'removed'
189
217
  : null,
190
218
  recordRetired: result.recordRetired,
219
+ ...(result.generation !== undefined
220
+ ? {
221
+ generation: result.generation,
222
+ predecessorSnapshot: result.predecessorSnapshot ?? null,
223
+ }
224
+ : {}),
191
225
  };
192
226
  emitArchivePushReport(report, config.archive?.summaryExportPath, context);
193
227
  process.exitCode = 0;
@@ -195,7 +229,11 @@ export async function runArchivePushCommand(dependencies, projectPathArg, option
195
229
  catch (error) {
196
230
  const message = error instanceof Error ? error.message : String(error);
197
231
  if (context.json) {
198
- context.logger.json({ status: 'error', message });
232
+ context.logger.json({
233
+ status: 'error',
234
+ ...(error instanceof ArchiveIdentityError ? { code: error.code } : {}),
235
+ message,
236
+ });
199
237
  }
200
238
  else {
201
239
  context.logger.error(message);
@@ -1,5 +1,6 @@
1
1
  import { rm } from 'node:fs/promises';
2
2
  import { buildCommandContext, type CommandContext } from '../../../app/command-context.js';
3
+ import type { ProjectScope } from '../../shared/project-scope.js';
3
4
  import { type OatConfig } from '../../../config/oat-config.js';
4
5
  import { buildProjectArchiveS3Uri, buildRepoArchiveS3Uri, ensureS3ArchiveAccess, type ExecFileLike, resolveLocalArchiveProjectPath, resolvePrimaryRepoRoot } from './archive-utils.js';
5
6
  export interface ArchiveSyncOptions {
@@ -33,14 +34,41 @@ export declare function buildArchiveSyncArgs(source: string, target: string, opt
33
34
  export declare function runArchiveSync(repoRoot: string, source: string, target: string, options: ArchiveSyncOptions, awsEnv: NodeJS.ProcessEnv, dependencies: ProjectArchiveCommandDependencies): Promise<void>;
34
35
  export interface ArchiveSnapshotEntry {
35
36
  dateStamp: string | null;
37
+ /** Base project name, without a `-gN` generation suffix. */
36
38
  projectName: string;
39
+ /** Full local archive name the snapshot hydrates to (`<project>-gN`). */
40
+ localName: string;
41
+ /** Generation family: the base name plus its scope qualifier, if any. */
42
+ familyName: string;
43
+ /** Scope qualifier carried by the snapshot name, or null. */
44
+ scope: ProjectScope | null;
45
+ /** Archive generation; 1 when the snapshot name carries no suffix. */
46
+ generation: number;
37
47
  snapshotName: string;
38
48
  source: string;
39
49
  target: string;
40
50
  }
41
51
  export declare function listArchiveSnapshots(repoRoot: string, projectsRoot: string, s3Uri: string, awsEnv: NodeJS.ProcessEnv, dependencies: ProjectArchiveCommandDependencies): Promise<ArchiveSnapshotEntry[]>;
52
+ /**
53
+ * Orders snapshots oldest to latest: a later generation is later regardless
54
+ * of date, then a later date, then the snapshot name.
55
+ */
42
56
  export declare function compareSnapshotEntries(left: ArchiveSnapshotEntry, right: ArchiveSnapshotEntry): number;
57
+ /**
58
+ * The latest snapshot for each local archive: every generation keeps its own
59
+ * local directory, so each one is hydrated from its own latest snapshot.
60
+ */
43
61
  export declare function selectLatestSnapshots(snapshots: ArchiveSnapshotEntry[]): ArchiveSnapshotEntry[];
62
+ /**
63
+ * The snapshots a by-name sync restores, in precedence order: an exact
64
+ * snapshot name; else a full generation name such as `demo-g2` or
65
+ * `demo-g2-local` (which also keeps a project literally named `demo-g2`
66
+ * reachable); else every generation family the name identifies, either as a
67
+ * family (`demo-local`: the local-scope `demo` archives) or as the base
68
+ * project (`demo`: `demo` and its scope-qualified families). Each family
69
+ * restores its latest generation, then its latest date.
70
+ */
71
+ export declare function selectNamedSnapshotCandidates(snapshots: ArchiveSnapshotEntry[], name: string): ArchiveSnapshotEntry[];
44
72
  export declare function readLocalSnapshotName(repoRoot: string, target: string): Promise<string | null>;
45
73
  export declare function syncArchiveSnapshot(repoRoot: string, snapshot: ArchiveSnapshotEntry, options: ArchiveSyncOptions, awsEnv: NodeJS.ProcessEnv, dependencies: ProjectArchiveCommandDependencies): Promise<boolean>;
46
74
  export declare function runArchiveSyncCommand(dependencies: ProjectArchiveCommandDependencies, projectName: string | undefined, options: ArchiveSyncOptions, context: CommandContext, commandLabel?: string): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"sync-runner.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/archive/sync-runner.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sync-runner.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/archive/sync-runner.ts"],"names":[],"mappings":"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"}
@@ -80,11 +80,18 @@ export async function listArchiveSnapshots(repoRoot, projectsRoot, s3Uri, awsEnv
80
80
  return {
81
81
  ...parsed,
82
82
  source: dependencies.buildProjectArchiveS3Uri(s3Uri, remoteRepoRoot, snapshotName),
83
- target: dependencies.resolveLocalArchiveProjectPath(projectsRoot, parsed.projectName),
83
+ target: dependencies.resolveLocalArchiveProjectPath(projectsRoot, parsed.localName),
84
84
  };
85
85
  });
86
86
  }
87
+ /**
88
+ * Orders snapshots oldest to latest: a later generation is later regardless
89
+ * of date, then a later date, then the snapshot name.
90
+ */
87
91
  export function compareSnapshotEntries(left, right) {
92
+ if (left.generation !== right.generation) {
93
+ return left.generation - right.generation;
94
+ }
88
95
  if (left.dateStamp && right.dateStamp && left.dateStamp !== right.dateStamp) {
89
96
  return left.dateStamp.localeCompare(right.dateStamp);
90
97
  }
@@ -96,15 +103,45 @@ export function compareSnapshotEntries(left, right) {
96
103
  }
97
104
  return left.snapshotName.localeCompare(right.snapshotName);
98
105
  }
106
+ /**
107
+ * The latest snapshot for each local archive: every generation keeps its own
108
+ * local directory, so each one is hydrated from its own latest snapshot.
109
+ */
99
110
  export function selectLatestSnapshots(snapshots) {
100
- const latestByProject = new Map();
111
+ const latestByLocalName = new Map();
101
112
  for (const snapshot of snapshots) {
102
- const current = latestByProject.get(snapshot.projectName);
113
+ const current = latestByLocalName.get(snapshot.localName);
114
+ if (!current || compareSnapshotEntries(snapshot, current) > 0) {
115
+ latestByLocalName.set(snapshot.localName, snapshot);
116
+ }
117
+ }
118
+ return [...latestByLocalName.values()];
119
+ }
120
+ /**
121
+ * The snapshots a by-name sync restores, in precedence order: an exact
122
+ * snapshot name; else a full generation name such as `demo-g2` or
123
+ * `demo-g2-local` (which also keeps a project literally named `demo-g2`
124
+ * reachable); else every generation family the name identifies, either as a
125
+ * family (`demo-local`: the local-scope `demo` archives) or as the base
126
+ * project (`demo`: `demo` and its scope-qualified families). Each family
127
+ * restores its latest generation, then its latest date.
128
+ */
129
+ export function selectNamedSnapshotCandidates(snapshots, name) {
130
+ const exactSnapshot = snapshots.filter((snapshot) => snapshot.snapshotName === name);
131
+ const fullName = snapshots.filter((snapshot) => snapshot.localName === name && snapshot.generation > 1);
132
+ const pool = exactSnapshot.length > 0
133
+ ? exactSnapshot
134
+ : fullName.length > 0
135
+ ? fullName
136
+ : snapshots.filter((snapshot) => snapshot.familyName === name || snapshot.projectName === name);
137
+ const latestByFamily = new Map();
138
+ for (const snapshot of pool) {
139
+ const current = latestByFamily.get(snapshot.familyName);
103
140
  if (!current || compareSnapshotEntries(snapshot, current) > 0) {
104
- latestByProject.set(snapshot.projectName, snapshot);
141
+ latestByFamily.set(snapshot.familyName, snapshot);
105
142
  }
106
143
  }
107
- return [...latestByProject.values()];
144
+ return [...latestByFamily.values()];
108
145
  }
109
146
  export async function readLocalSnapshotName(repoRoot, target) {
110
147
  try {
@@ -152,27 +189,12 @@ export async function runArchiveSyncCommand(dependencies, projectName, options,
152
189
  const projectsRoot = await dependencies.resolveProjectsRoot(repoRoot, dependencies.processEnv);
153
190
  const snapshots = await listArchiveSnapshots(repoRoot, projectsRoot, s3Uri, awsEnv, dependencies);
154
191
  const targets = projectName
155
- ? snapshots.filter((snapshot) => snapshot.projectName === projectName ||
156
- snapshot.snapshotName === projectName)
192
+ ? selectNamedSnapshotCandidates(snapshots, projectName)
157
193
  : selectLatestSnapshots(snapshots);
158
194
  if (projectName && targets.length === 0) {
159
195
  throw new CliError(`No archived snapshot found in S3 for project \`${projectName}\`.`);
160
196
  }
161
- const latestTarget = projectName
162
- ? targets.reduce((latest, snapshot) => {
163
- if (!latest) {
164
- return snapshot;
165
- }
166
- return compareSnapshotEntries(snapshot, latest) > 0
167
- ? snapshot
168
- : latest;
169
- }, null)
170
- : null;
171
- const snapshotsToSync = projectName
172
- ? latestTarget
173
- ? [latestTarget]
174
- : []
175
- : targets;
197
+ const snapshotsToSync = targets;
176
198
  const appliedTargets = [];
177
199
  const appliedSources = [];
178
200
  for (const snapshot of snapshotsToSync) {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/complete-state/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,IAAI,eAAe,EAC3B,SAAS,IAAI,gBAAgB,EAC9B,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,mBAAmB,EAAE,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAChF,OAAO,EAIL,KAAK,yBAAyB,EAC/B,MAAM,wCAAwC,CAAC;AAEhD,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAEzD,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAG/C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASpC,UAAU,gCAAiC,SAAQ,yBAAyB;IAC1E,mBAAmB,EAAE,CACnB,OAAO,EAAE,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC,CAAC,CAAC,KAC/C,cAAc,CAAC;IACpB,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,QAAQ,EAAE,OAAO,eAAe,CAAC;IACjC,SAAS,EAAE,OAAO,gBAAgB,CAAC;IACnC,SAAS,EAAE,OAAO,SAAS,CAAC;IAC5B,UAAU,EAAE,OAAO,UAAU,CAAC;IAC9B,sBAAsB,EAAE,OAAO,sBAAsB,CAAC;IACtD,mEAAmE;IACnE,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,GAAG,EAAE,MAAM,IAAI,CAAC;CACjB;AAkFD,wBAAgB,iCAAiC,CAC/C,SAAS,GAAE,OAAO,CAAC,gCAAgC,CAAM,GACxD,OAAO,CA+BT"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/complete-state/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,IAAI,eAAe,EAC3B,SAAS,IAAI,gBAAgB,EAC9B,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAE,mBAAmB,EAAE,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEhF,OAAO,EAIL,KAAK,yBAAyB,EAC/B,MAAM,wCAAwC,CAAC;AAMhD,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAEzD,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAG/C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASpC,UAAU,gCAAiC,SAAQ,yBAAyB;IAC1E,mBAAmB,EAAE,CACnB,OAAO,EAAE,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC,CAAC,CAAC,KAC/C,cAAc,CAAC;IACpB,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,QAAQ,EAAE,OAAO,eAAe,CAAC;IACjC,SAAS,EAAE,OAAO,gBAAgB,CAAC;IACnC,SAAS,EAAE,OAAO,SAAS,CAAC;IAC5B,UAAU,EAAE,OAAO,UAAU,CAAC;IAC9B,sBAAsB,EAAE,OAAO,sBAAsB,CAAC;IACtD,mEAAmE;IACnE,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,GAAG,EAAE,MAAM,IAAI,CAAC;CACjB;AAiID,wBAAgB,iCAAiC,CAC/C,SAAS,GAAE,OAAO,CAAC,gCAAgC,CAAM,GACxD,OAAO,CA+BT"}
@@ -1,6 +1,9 @@
1
1
  import { readFile as defaultReadFile, writeFile as defaultWriteFile, } from 'node:fs/promises';
2
+ import { join } from 'node:path';
2
3
  import { buildCommandContext } from '../../../app/command-context.js';
4
+ import { readStateWorkflowMode } from '../../project/closeout-check/closeout-invariant.js';
3
5
  import { checkProjectCloseout, DEFAULT_CLOSEOUT_CHECK_DEPENDENCIES, formatCloseoutRefusal, } from '../../project/closeout-check/index.js';
6
+ import { evaluateJournal, formatJournalRefusal, } from '../../project/journal-check/index.js';
4
7
  import { readGlobalOptions } from '../../shared/shared.utils.js';
5
8
  import { resolveEffectiveConfig } from '../../../config/resolve.js';
6
9
  import { CliError } from '../../../errors/cli-error.js';
@@ -35,6 +38,48 @@ async function runProjectCompleteState(projectPath, options, context, dependenci
35
38
  if (result.status === 'incomplete') {
36
39
  throw new CliError(formatCloseoutRefusal(projectPath, result), 1);
37
40
  }
41
+ // Immediately before the write, the final journal evaluator: a project
42
+ // that has a journal completes only when that journal holds its terminal
43
+ // shape. Both guards refuse before any write; no override bypasses the
44
+ // closeout invariant above.
45
+ const journalPath = join(targetProjectPath, 'implementation.md');
46
+ const planPath = join(targetProjectPath, 'plan.md');
47
+ const hasJournal = await dependencies.fileExists(journalPath);
48
+ if (!hasJournal && (await dependencies.fileExists(planPath))) {
49
+ // A planned project completes only through its journal: a missing
50
+ // journal must never silently turn the final evaluator off.
51
+ throw new CliError(formatJournalRefusal(projectPath, {
52
+ status: 'refused',
53
+ boundary: 'completion',
54
+ workflowMode: readStateWorkflowMode(content) ?? 'spec-driven',
55
+ scope: null,
56
+ reasons: [
57
+ {
58
+ code: 'journal-missing',
59
+ path: 'implementation.md',
60
+ line: null,
61
+ owner: 'oat-project-implement',
62
+ message: 'plan.md exists but implementation.md is missing; a planned project completes only with its journal.',
63
+ },
64
+ ],
65
+ warnings: [],
66
+ overrides: [],
67
+ }), 1);
68
+ }
69
+ if (hasJournal) {
70
+ const journal = evaluateJournal({
71
+ boundary: 'completion',
72
+ scope: null,
73
+ planContent: (await dependencies.fileExists(planPath))
74
+ ? await dependencies.readFile(planPath, 'utf8')
75
+ : '',
76
+ journalContent: await dependencies.readFile(journalPath, 'utf8'),
77
+ stateContent: content,
78
+ });
79
+ if (journal.status === 'refused') {
80
+ throw new CliError(formatJournalRefusal(projectPath, journal), 1);
81
+ }
82
+ }
38
83
  const now = dependencies.now();
39
84
  const updatedContent = renderCompletedProjectState(content, {
40
85
  archived: options.archived ?? false,
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/dispatch/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAapC,MAAM,WAAW,kCAAkC;IACjD,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5C,SAAS,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;CAClC;AAiHD,wBAAgB,4BAA4B,CAC1C,SAAS,GAAE,OAAO,CAAC,kCAAkC,CAAM,GAC1D,OAAO,CA0BT"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/dispatch/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmBpC,MAAM,WAAW,kCAAkC;IACjD,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5C,SAAS,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;CAClC;AAsID,wBAAgB,4BAA4B,CAC1C,SAAS,GAAE,OAAO,CAAC,kCAAkC,CAAM,GAC1D,OAAO,CAkCT"}
@@ -4,7 +4,8 @@ import { readGlobalOptions } from '../../shared/shared.utils.js';
4
4
  import { resolveProjectRoot } from '../../../fs/paths.js';
5
5
  import { Command } from 'commander';
6
6
  import { createCanonicalRoleCommand } from './canonical-role.js';
7
- import { recordProjectDispatch, redactDispatchMessage, } from './record.js';
7
+ import { assertFormalDispatchStamp, projectDispatchRunLine, recordProjectDispatch, redactDispatchMessage, } from './record.js';
8
+ const RECORD_FORMATS = ['text', 'line'];
8
9
  const DEFAULT_DEPENDENCIES = {
9
10
  buildCommandContext,
10
11
  resolveProjectRoot,
@@ -54,6 +55,10 @@ function runtimeIdentityLines(identity) {
54
55
  async function runRecordCommand(options, context, dependencies) {
55
56
  let repoRoot = null;
56
57
  try {
58
+ const format = options.format ?? 'text';
59
+ if (!RECORD_FORMATS.includes(format)) {
60
+ throw new Error(`Unknown --format ${format}; expected one of ${RECORD_FORMATS.join(', ')}.`);
61
+ }
57
62
  repoRoot = await dependencies.resolveProjectRoot(context.cwd);
58
63
  const content = options.eventFile === '-'
59
64
  ? await dependencies.readStdin()
@@ -77,8 +82,23 @@ async function runRecordCommand(options, context, dependencies) {
77
82
  }),
78
83
  },
79
84
  };
85
+ // The stamp is caller-supplied text, so it passes the same redaction
86
+ // boundary before it can reach the projection.
87
+ const dispatchStamp = options.dispatchStamp === undefined
88
+ ? null
89
+ : redactDispatchMessage(options.dispatchStamp, {
90
+ repo: repoRoot,
91
+ home: context.home,
92
+ });
93
+ if (dispatchStamp !== null) {
94
+ assertFormalDispatchStamp(dispatchStamp);
95
+ }
96
+ const runLine = projectDispatchRunLine(result, { dispatchStamp });
80
97
  if (context.json) {
81
- context.logger.json(result);
98
+ context.logger.json({ ...result, runLine });
99
+ }
100
+ else if (format === 'line') {
101
+ context.logger.info(runLine.line);
82
102
  }
83
103
  else {
84
104
  context.logger.info('Dispatch evidence is valid; nothing was written.');
@@ -107,6 +127,8 @@ export function createProjectDispatchCommand(overrides = {}) {
107
127
  .addCommand(new Command('record')
108
128
  .description('Validate one generic dispatch plus namespaced OAT evidence (writes nothing)')
109
129
  .requiredOption('--event-file <json-file-or-dash>', 'Complete record and event JSON file, or - for standard input')
130
+ .option('--format <format>', 'Text output: text (default) or line (one journal run line, run/v1)')
131
+ .option('--dispatch-stamp <line>', 'Formal "Dispatch:" stamp copied verbatim from the resolver into the run line')
110
132
  .action(async (options, command) => {
111
133
  const context = dependencies.buildCommandContext(readGlobalOptions(command));
112
134
  await runRecordCommand(options, context, dependencies);
@@ -1,4 +1,4 @@
1
- import { type GenericDispatchRecord } from '../../../providers/identity/generic-dispatch-record.js';
1
+ import { type DispatchTerminalClassification, type GenericDispatchRecord } from '../../../providers/identity/generic-dispatch-record.js';
2
2
  import { type OatDispatchEvidenceEvent, type PersistedOatDispatchRecordV1 } from '../../../providers/identity/oat-dispatch-record.js';
3
3
  /**
4
4
  * Hard redaction boundary. Producers redact their own messages, but this is the
@@ -67,6 +67,59 @@ export type ProjectDispatchRecordResult = {
67
67
  record: PersistedOatDispatchRecordV1;
68
68
  runtimeIdentity: DispatchRecordRuntimeIdentity;
69
69
  };
70
+ /**
71
+ * One-line journal run record, projection v1.
72
+ *
73
+ * An additive rendering of the same validated, redacted record and event: one
74
+ * line per request id, written by the owning skill under
75
+ * `## Orchestration Runs` and updated in place with the terminal outcome. The
76
+ * renderer writes nothing.
77
+ *
78
+ * Grammar: `run/v1` followed by named `key=value` fields in the fixed order of
79
+ * `DISPATCH_RUN_LINE_FIELDS`, joined by ` · `. Inside a value, `\\`, `\·`,
80
+ * `\~`, `\n` and `\r` escape a backslash, the delimiter, a literal tilde, a
81
+ * newline and a carriage return; a bare `~` value is null. The configured
82
+ * identity (`target`, `model`, `effort`) and the observed identity are
83
+ * separate fields: an observation never replaces the configured invocation.
84
+ */
85
+ export declare const DISPATCH_RUN_LINE_PREFIX = "run/v1";
86
+ export declare const DISPATCH_RUN_LINE_DELIMITER = " \u00B7 ";
87
+ export declare const DISPATCH_RUN_LINE_FIELDS: readonly ['request', 'scope', 'action', 'role', 'target', 'model', 'effort', 'stamp', 'launch', 'outcome', 'terminal', 'class', 'continuation', 'observed', 'match'];
88
+ export type DispatchRunLineField = (typeof DISPATCH_RUN_LINE_FIELDS)[number];
89
+ export type DispatchRunLineFields = Record<DispatchRunLineField, string | null>;
90
+ export interface DispatchRunLineProjection {
91
+ version: 1;
92
+ line: string;
93
+ fields: DispatchRunLineFields;
94
+ classification: DispatchTerminalClassification;
95
+ terminal: boolean;
96
+ }
97
+ export declare function renderDispatchRunLine(fields: DispatchRunLineFields): string;
98
+ export type ParsedDispatchRunLine = {
99
+ ok: true;
100
+ fields: DispatchRunLineFields;
101
+ } | {
102
+ ok: false;
103
+ reason: string;
104
+ };
105
+ /**
106
+ * Parse one journal run line (optionally written as a `- ` list item). Every
107
+ * field must be present exactly once, in order; anything else is malformed.
108
+ * Callers derive terminality from `launch` and `outcome` with
109
+ * `classifyDispatchOutcome`, never from the recorded `terminal` text alone.
110
+ */
111
+ export declare function parseDispatchRunLine(text: string): ParsedDispatchRunLine;
112
+ /**
113
+ * Validate a caller-supplied formal `Dispatch:` stamp: one line with the
114
+ * canonical prefix that parses as a modern stamp. The stamp comes from the
115
+ * resolver's `dispatchStamp` field; the projection carries it verbatim and
116
+ * never assembles one.
117
+ */
118
+ export declare function assertFormalDispatchStamp(stamp: string): void;
119
+ /** Project a validated record result onto the one-line run record. */
120
+ export declare function projectDispatchRunLine(result: ProjectDispatchRecordResult, options?: {
121
+ dispatchStamp?: string | null;
122
+ }): DispatchRunLineProjection;
70
123
  export declare function parseDispatchRecordInput(value: unknown): DispatchRecordInput;
71
124
  /**
72
125
  * Validate one dispatch record and event and return the augmented record. Parse
@@ -1 +1 @@
1
- {"version":3,"file":"record.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/dispatch/record.ts"],"names":[],"mappings":"AAYA,OAAO,EAKL,KAAK,qBAAqB,EAC3B,MAAM,6CAA6C,CAAC;AACrD,OAAO,EAOL,KAAK,wBAAwB,EAE7B,KAAK,4BAA4B,EAElC,MAAM,yCAAyC,CAAC;AASjD;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,EACf,KAAK,GAAE;IACL,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACjB,GACL,MAAM,CAgBR;AAeD,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,qBAAqB,CAAC;IAC9B,KAAK,EAAE,wBAAwB,CAAC;IAChC,uEAAuE;IACvE,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAED;;;;;GAKG;AACH,MAAM,WAAW,6BAA6B;IAC5C,UAAU,EAAE;QACV,QAAQ,EAAE,MAAM,CAAC;QACjB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;QAC5B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QACrB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QACtB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;KAC5B,CAAC;IACF,QAAQ,EAAE;QACR,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,EAAE,MAAM,CAAC;QACnB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;QAC5B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QACpB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QACrB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QACtB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;KAC5B,GAAG,IAAI,CAAC;IACT,KAAK,EAAE,UAAU,GAAG,aAAa,GAAG,gBAAgB,GAAG,IAAI,CAAC;IAC5D;;;OAGG;IACH,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC;;;;OAIG;IACH,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,UAAU,GAAG,cAAc,CAAC;CACrC;AAED;;;GAGG;AACH,MAAM,MAAM,2BAA2B,GAAG;IACxC,MAAM,EAAE,gBAAgB,CAAC;IACzB,MAAM,EAAE,4BAA4B,CAAC;IACrC,eAAe,EAAE,6BAA6B,CAAC;CAChD,CAAC;AA8NF,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,mBAAmB,CA6G5E;AAoCD;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CAAC,KAAK,EAAE;IACjD,KAAK,EAAE,OAAO,CAAC;CAChB,GAAG,OAAO,CAAC,2BAA2B,CAAC,CAWvC"}
1
+ {"version":3,"file":"record.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/dispatch/record.ts"],"names":[],"mappings":"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"}