@open-agent-toolkit/cli 0.3.21 → 0.3.23
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.
- package/assets/bundle-metadata.json +1 -1
- package/assets/docs/docs-tooling/add-docs-to-a-repo.md +3 -9
- package/assets/docs/reference/cli-reference.md +8 -3
- package/assets/docs/reference/configuration.md +3 -0
- package/assets/docs/reference/oat-directory-structure.md +1 -1
- package/assets/docs/reference/project-artifacts.md +141 -2
- package/assets/docs/reference/project-state-machine.md +2 -2
- package/assets/docs/workflows/advanced/autonomy.md +29 -12
- package/assets/docs/workflows/advanced/cursor-cloud.md +20 -6
- package/assets/docs/workflows/advanced/workflow-gates.md +9 -0
- package/assets/docs/workflows/projects/closeout/closeout-skills.md +24 -5
- package/assets/docs/workflows/projects/closeout/retro.md +6 -2
- package/assets/docs/workflows/projects/execution/implementation-execution.md +18 -4
- package/assets/docs/workflows/projects/execution/index.md +1 -1
- package/assets/docs/workflows/projects/execution/picking-up-projects.md +3 -2
- package/assets/docs/workflows/projects/execution/project-log.md +100 -11
- package/assets/docs/workflows/projects/lifecycle.md +3 -3
- package/assets/docs/workflows/projects/reviews/index.md +18 -0
- package/assets/public-package-versions.json +4 -4
- package/assets/skills/oat-cursor-cloud-projects/SKILL.md +12 -8
- package/assets/skills/oat-cursor-cloud-projects/references/cursor-cloud-mechanics.md +63 -2
- package/assets/skills/oat-docs/SKILL.md +14 -28
- package/assets/skills/oat-docs-analyze/SKILL.md +4 -2
- package/assets/skills/oat-docs-analyze/references/legacy-scaffold-checks.md +16 -0
- package/assets/skills/oat-docs-apply/SKILL.md +2 -2
- package/assets/skills/oat-docs-authoring/SKILL.md +2 -2
- package/assets/skills/oat-docs-authoring/references/lifecycle-boundaries.md +1 -2
- package/assets/skills/oat-docs-authoring/references/mkdocs-to-oat-fumadocs-refactor-guide.md +73 -0
- package/assets/skills/oat-docs-bootstrap/SKILL.md +44 -310
- package/assets/skills/oat-project-autonomous/SKILL.md +88 -26
- package/assets/skills/oat-project-autonomous/references/gate-inventory.md +1 -1
- package/assets/skills/oat-project-brief/SKILL.md +1 -1
- package/assets/skills/oat-project-brief/references/brief-contract.md +33 -27
- package/assets/skills/oat-project-brief/references/docs/autonomy-contract.md +1 -1
- package/assets/skills/oat-project-complete/SKILL.md +142 -25
- package/assets/skills/oat-project-complete-auto/SKILL.md +4 -4
- package/assets/skills/oat-project-dispatch-subagents/SKILL.md +10 -5
- package/assets/skills/oat-project-document/SKILL.md +1 -1
- package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +1 -1
- package/assets/skills/oat-project-goal/SKILL.md +63 -15
- package/assets/skills/oat-project-goal/references/docs/autonomy-contract.md +1 -1
- package/assets/skills/oat-project-implement/SKILL.md +6 -6
- package/assets/skills/oat-project-implement/references/completion-and-closeout.md +28 -7
- package/assets/skills/oat-project-implement/references/dispatch-and-dry-run.md +10 -5
- package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +1 -1
- package/assets/skills/oat-project-implement/references/phase-execution.md +23 -9
- package/assets/skills/oat-project-implement/references/plan-and-resume.md +4 -4
- package/assets/skills/oat-project-lite/SKILL.md +1 -1
- package/assets/skills/oat-project-lite/references/docs/autonomy-contract.md +1 -1
- package/assets/skills/oat-project-pr-final/SKILL.md +6 -1
- package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +1 -1
- package/assets/skills/oat-project-pr-progress/SKILL.md +6 -1
- package/assets/skills/oat-project-quick-start/SKILL.md +1 -1
- package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +1 -1
- package/assets/skills/oat-project-reconcile/SKILL.md +13 -19
- package/assets/skills/oat-project-retro/SKILL.md +5 -2
- package/assets/skills/oat-project-retro/references/evidence-and-lanes.md +9 -3
- package/assets/skills/oat-project-review-provide/SKILL.md +28 -3
- package/assets/skills/oat-project-review-receive/SKILL.md +32 -18
- package/assets/skills/oat-project-review-receive-remote/SKILL.md +10 -6
- package/assets/skills/oat-project-revise/SKILL.md +9 -2
- package/assets/skills/oat-project-summary/SKILL.md +166 -37
- package/assets/skills/oat-worktree-bootstrap-auto/SKILL.md +3 -3
- package/assets/templates/docs-app-fuma/docs/contributing.md +6 -0
- package/assets/templates/docs-app-fuma/docs/getting-started.md +1 -1
- package/assets/templates/docs-app-fuma/next.config.js +5 -1
- package/assets/templates/implementation-brief.md +5 -36
- package/assets/templates/implementation.md +11 -81
- package/assets/templates/project-log.md +2 -31
- package/assets/templates/project-retro.md +4 -1
- package/assets/templates/summary.md +13 -5
- package/dist/commands/config/index.d.ts.map +1 -1
- package/dist/commands/config/index.js +44 -1
- package/dist/commands/docs/analyze.js +1 -1
- package/dist/commands/docs/apply.js +1 -1
- package/dist/commands/docs/init/scaffold.d.ts.map +1 -1
- package/dist/commands/docs/init/scaffold.js +35 -2
- package/dist/commands/project/archive/archive-utils.d.ts +205 -8
- package/dist/commands/project/archive/archive-utils.d.ts.map +1 -1
- package/dist/commands/project/archive/archive-utils.js +708 -44
- package/dist/commands/project/archive/index.d.ts.map +1 -1
- package/dist/commands/project/archive/index.js +1 -0
- package/dist/commands/project/archive/push-runner.d.ts +9 -1
- package/dist/commands/project/archive/push-runner.d.ts.map +1 -1
- package/dist/commands/project/archive/push-runner.js +56 -18
- package/dist/commands/project/archive/sync-runner.d.ts +28 -0
- package/dist/commands/project/archive/sync-runner.d.ts.map +1 -1
- package/dist/commands/project/archive/sync-runner.js +44 -22
- package/dist/commands/project/complete-state/index.d.ts.map +1 -1
- package/dist/commands/project/complete-state/index.js +45 -0
- package/dist/commands/project/dispatch/index.d.ts.map +1 -1
- package/dist/commands/project/dispatch/index.js +24 -2
- package/dist/commands/project/dispatch/record.d.ts +54 -1
- package/dist/commands/project/dispatch/record.d.ts.map +1 -1
- package/dist/commands/project/dispatch/record.js +229 -1
- package/dist/commands/project/index.d.ts.map +1 -1
- package/dist/commands/project/index.js +2 -0
- package/dist/commands/project/journal-check/evaluator.d.ts +17 -0
- package/dist/commands/project/journal-check/evaluator.d.ts.map +1 -0
- package/dist/commands/project/journal-check/evaluator.js +140 -0
- package/dist/commands/project/journal-check/index.d.ts +34 -0
- package/dist/commands/project/journal-check/index.d.ts.map +1 -0
- package/dist/commands/project/journal-check/index.js +163 -0
- package/dist/commands/project/journal-check/rules.d.ts +68 -0
- package/dist/commands/project/journal-check/rules.d.ts.map +1 -0
- package/dist/commands/project/journal-check/rules.js +994 -0
- package/dist/commands/project/journal-check/types.d.ts +63 -0
- package/dist/commands/project/journal-check/types.d.ts.map +1 -0
- package/dist/commands/project/journal-check/types.js +26 -0
- package/dist/commands/project/log/append.d.ts +6 -0
- package/dist/commands/project/log/append.d.ts.map +1 -1
- package/dist/commands/project/log/append.js +114 -6
- package/dist/commands/project/log/check.d.ts +23 -1
- package/dist/commands/project/log/check.d.ts.map +1 -1
- package/dist/commands/project/log/check.js +20 -3
- package/dist/commands/project/log/grammar.d.ts +37 -0
- package/dist/commands/project/log/grammar.d.ts.map +1 -1
- package/dist/commands/project/log/grammar.js +72 -0
- package/dist/commands/project/log/rollup.d.ts +87 -1
- package/dist/commands/project/log/rollup.d.ts.map +1 -1
- package/dist/commands/project/log/rollup.js +257 -5
- package/dist/config/oat-config.d.ts +14 -0
- package/dist/config/oat-config.d.ts.map +1 -1
- package/dist/config/oat-config.js +17 -0
- package/dist/config/resolve.d.ts.map +1 -1
- package/dist/config/resolve.js +5 -1
- package/dist/providers/identity/generic-dispatch-record.d.ts +33 -0
- package/dist/providers/identity/generic-dispatch-record.d.ts.map +1 -1
- package/dist/providers/identity/generic-dispatch-record.js +60 -1
- 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,
|
|
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;
|
|
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,
|
|
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,
|
|
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:
|
|
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
|
-
|
|
141
|
-
|
|
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
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
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(
|
|
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,
|
|
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({
|
|
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.
|
|
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
|
|
111
|
+
const latestByLocalName = new Map();
|
|
101
112
|
for (const snapshot of snapshots) {
|
|
102
|
-
const current =
|
|
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
|
-
|
|
141
|
+
latestByFamily.set(snapshot.familyName, snapshot);
|
|
105
142
|
}
|
|
106
143
|
}
|
|
107
|
-
return [...
|
|
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
|
|
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
|
|
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;
|
|
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;
|
|
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,
|
|
1
|
+
{"version":3,"file":"record.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/dispatch/record.ts"],"names":[],"mappings":"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"}
|