@open-agent-toolkit/cli 0.2.49 → 0.2.51
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/cli-utilities/tool-packs.md +35 -24
- package/assets/docs/reference/cli-reference.md +20 -5
- package/assets/docs/reference/file-locations.md +8 -2
- package/assets/docs/reference/oat-directory-structure.md +14 -5
- package/assets/docs/reference/troubleshooting.md +22 -4
- package/assets/docs/workflows/projects/artifacts.md +9 -4
- package/assets/docs/workflows/projects/lifecycle.md +17 -5
- package/assets/docs/workflows/projects/picking-up-projects.md +26 -9
- package/assets/docs/workflows/projects/pr-flow.md +5 -3
- package/assets/docs/workflows/projects/reviewing-oat-prs.md +12 -8
- package/assets/public-package-versions.json +4 -4
- package/assets/skills/oat-project-autonomous/references/gate-inventory.md +2 -2
- package/assets/skills/oat-project-complete/SKILL.md +193 -26
- package/assets/skills/oat-project-complete/scripts/execute-synced-archive-entry.mjs +306 -0
- package/assets/skills/oat-project-complete/scripts/finalize-synced-archive.mjs +125 -0
- package/assets/skills/oat-project-complete/scripts/parse-synced-archive-resume-fields.mjs +106 -0
- package/assets/skills/oat-project-complete/scripts/recover-completion-receipts.mjs +110 -0
- package/assets/skills/oat-project-complete/scripts/resolve-synced-archive-entry.mjs +164 -0
- package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +2 -2
- package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +2 -2
- package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +2 -2
- package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +2 -2
- package/dist/commands/doctor/index.d.ts +7 -0
- package/dist/commands/doctor/index.d.ts.map +1 -1
- package/dist/commands/doctor/index.js +44 -23
- package/dist/commands/pjm/index.d.ts +0 -2
- package/dist/commands/pjm/index.d.ts.map +1 -1
- package/dist/commands/pjm/index.js +5 -4
- package/dist/commands/pjm/migrate.d.ts +2 -1
- package/dist/commands/pjm/migrate.d.ts.map +1 -1
- package/dist/commands/pjm/migrate.js +23 -17
- package/dist/commands/project/archive/archive-utils.d.ts +8 -1
- package/dist/commands/project/archive/archive-utils.d.ts.map +1 -1
- package/dist/commands/project/archive/archive-utils.js +147 -50
- package/dist/commands/project/archive/push-runner.d.ts.map +1 -1
- package/dist/commands/project/archive/push-runner.js +15 -2
- package/dist/commands/project/links/compute.d.ts +1 -0
- package/dist/commands/project/links/compute.d.ts.map +1 -1
- package/dist/commands/project/links/compute.js +5 -4
- package/dist/commands/project/links/index.d.ts +9 -0
- package/dist/commands/project/links/index.d.ts.map +1 -1
- package/dist/commands/project/links/index.js +71 -2
- package/dist/commands/project/list.d.ts +10 -2
- package/dist/commands/project/list.d.ts.map +1 -1
- package/dist/commands/project/list.js +205 -29
- package/dist/commands/project/open/index.d.ts +2 -0
- package/dist/commands/project/open/index.d.ts.map +1 -1
- package/dist/commands/project/open/index.js +16 -1
- package/dist/commands/project/prune/index.d.ts +10 -4
- package/dist/commands/project/prune/index.d.ts.map +1 -1
- package/dist/commands/project/prune/index.js +85 -15
- package/dist/commands/project/pull/index.d.ts +4 -0
- package/dist/commands/project/pull/index.d.ts.map +1 -1
- package/dist/commands/project/pull/index.js +82 -3
- package/dist/commands/project/sync/git.d.ts +9 -0
- package/dist/commands/project/sync/git.d.ts.map +1 -1
- package/dist/commands/project/sync/git.js +18 -0
- package/dist/commands/project/sync/ref-sync.d.ts +16 -1
- package/dist/commands/project/sync/ref-sync.d.ts.map +1 -1
- package/dist/commands/project/sync/ref-sync.js +288 -17
- package/dist/commands/project/sync/resolve-target.d.ts +10 -0
- package/dist/commands/project/sync/resolve-target.d.ts.map +1 -1
- package/dist/commands/project/sync/resolve-target.js +56 -1
- package/dist/commands/shared/project-scope.d.ts +2 -0
- package/dist/commands/shared/project-scope.d.ts.map +1 -1
- package/dist/commands/shared/project-scope.js +5 -0
- package/dist/commands/state/generate.d.ts +2 -0
- package/dist/commands/state/generate.d.ts.map +1 -1
- package/dist/commands/state/generate.js +93 -28
- package/dist/commands/status/index.d.ts +3 -1
- package/dist/commands/status/index.d.ts.map +1 -1
- package/dist/commands/status/index.js +77 -10
- package/dist/commands/tools/shared/pack-inventory.d.ts +10 -0
- package/dist/commands/tools/shared/pack-inventory.d.ts.map +1 -1
- package/dist/commands/tools/shared/pack-inventory.js +71 -21
- package/package.json +2 -2
|
@@ -7,7 +7,7 @@ import { initializeDecisionRecords } from '../decision/init.js';
|
|
|
7
7
|
import { migrateDecisionRecords, } from '../decision/migrate.js';
|
|
8
8
|
import { stripTemplateFrontmatter } from '../shared/strip-template-frontmatter.js';
|
|
9
9
|
import YAML from 'yaml';
|
|
10
|
-
import { initializeRepoReference } from './init.js';
|
|
10
|
+
import { CANONICAL_REPO_REFERENCE_PATHS, initializeRepoReference, } from './init.js';
|
|
11
11
|
const ACTIVE_MOVES = [
|
|
12
12
|
{ source: 'reference/current-state.md', target: 'pjm/current-state.md' },
|
|
13
13
|
{ source: 'reference/roadmap.md', target: 'pjm/roadmap.md' },
|
|
@@ -17,6 +17,10 @@ const JUDGMENT_TARGETS = [
|
|
|
17
17
|
'reference/backlog.md',
|
|
18
18
|
'reference/backlog-completed.md',
|
|
19
19
|
];
|
|
20
|
+
const LEGACY_MIGRATION_PATHS = [
|
|
21
|
+
...ACTIVE_MOVES.map((move) => move.source),
|
|
22
|
+
'reference/decision-record.md',
|
|
23
|
+
];
|
|
20
24
|
async function pathExists(path) {
|
|
21
25
|
try {
|
|
22
26
|
await access(path);
|
|
@@ -228,19 +232,17 @@ async function collectJudgmentProposals(repoRoot) {
|
|
|
228
232
|
}
|
|
229
233
|
return actions;
|
|
230
234
|
}
|
|
231
|
-
async function
|
|
232
|
-
const
|
|
233
|
-
const hasDecisions = await pathExists(join(repoRoot, 'reference', 'decisions'));
|
|
234
|
-
if (!hasPjm || !hasDecisions) {
|
|
235
|
-
return false;
|
|
236
|
-
}
|
|
237
|
-
for (const legacyPath of [
|
|
238
|
-
'reference/current-state.md',
|
|
239
|
-
'reference/roadmap.md',
|
|
240
|
-
'reference/backlog',
|
|
241
|
-
'reference/decision-record.md',
|
|
242
|
-
]) {
|
|
235
|
+
async function hasRecognizedLegacySources(repoRoot) {
|
|
236
|
+
for (const legacyPath of LEGACY_MIGRATION_PATHS) {
|
|
243
237
|
if (await pathExists(join(repoRoot, legacyPath))) {
|
|
238
|
+
return true;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
async function isAlreadyMigrated(repoRoot) {
|
|
244
|
+
for (const relativePath of CANONICAL_REPO_REFERENCE_PATHS) {
|
|
245
|
+
if (!(await pathExists(join(repoRoot, relativePath)))) {
|
|
244
246
|
return false;
|
|
245
247
|
}
|
|
246
248
|
}
|
|
@@ -305,12 +307,16 @@ function buildEmptyResult(options, status, reason) {
|
|
|
305
307
|
};
|
|
306
308
|
}
|
|
307
309
|
export async function migratePjmRepo(options) {
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
}
|
|
311
|
-
if (await isAlreadyMigrated(options.repoRoot)) {
|
|
310
|
+
const hasLegacySources = await hasRecognizedLegacySources(options.repoRoot);
|
|
311
|
+
if (!hasLegacySources && (await isAlreadyMigrated(options.repoRoot))) {
|
|
312
312
|
return buildEmptyResult(options, 'already-migrated');
|
|
313
313
|
}
|
|
314
|
+
if (!hasLegacySources) {
|
|
315
|
+
const reason = options.adoption.state === 'partial-initialization'
|
|
316
|
+
? 'PJM initialization is partial and no recognized legacy migration input was found; run oat pjm init to complete initialization'
|
|
317
|
+
: 'No recognized PJM migration input was found; run oat pjm init to initialize this repository';
|
|
318
|
+
return buildEmptyResult(options, 'skipped', reason);
|
|
319
|
+
}
|
|
314
320
|
const apply = options.apply ?? false;
|
|
315
321
|
const activeMoves = await planActiveMoves(options.repoRoot);
|
|
316
322
|
const judgmentProposals = await collectJudgmentProposals(options.repoRoot);
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { rename } from 'node:fs/promises';
|
|
2
2
|
import { type GitRunner } from '../../project/sync/git.js';
|
|
3
3
|
import { readSyncedRecord, writeSyncedRecord } from '../../project/sync/record.js';
|
|
4
|
-
import { commitRecordChange, preflightSyncedCheckout, removeSyncedCheckout } from '../../project/sync/ref-sync.js';
|
|
4
|
+
import { commitRecordChange, preflightSyncedCheckout, removeSyncedCheckout, retireSyncedRef, type SyncedRefRetirementReceipt } from '../../project/sync/ref-sync.js';
|
|
5
|
+
import { probeSyncedTerminalRefs } from '../../project/sync/resolve-target.js';
|
|
5
6
|
import { type ProjectScope } from '../../shared/project-scope.js';
|
|
6
7
|
import { copyDirectory, copySingleFile, dirExists, ensureDir, fileExists } from '../../../fs/io.js';
|
|
7
8
|
export type ExecFileResult = {
|
|
@@ -104,7 +105,11 @@ interface ArchiveProjectOnCompletionDependencies extends EnsureS3ArchiveAccessDe
|
|
|
104
105
|
writeSyncedRecord?: typeof writeSyncedRecord;
|
|
105
106
|
preflightSyncedCheckout?: typeof preflightSyncedCheckout;
|
|
106
107
|
removeSyncedCheckout?: typeof removeSyncedCheckout;
|
|
108
|
+
retireSyncedRef?: typeof retireSyncedRef;
|
|
107
109
|
commitRecordChange?: typeof commitRecordChange;
|
|
110
|
+
removeSyncedRecord?: (recordPath: string) => Promise<void>;
|
|
111
|
+
afterLifecycleCommit?: () => Promise<void>;
|
|
112
|
+
probeSyncedTerminalRefs?: typeof probeSyncedTerminalRefs;
|
|
108
113
|
}
|
|
109
114
|
export interface ArchiveProjectRecapExportV1 {
|
|
110
115
|
sourceRunRoot: string;
|
|
@@ -124,6 +129,8 @@ export interface ArchiveProjectOnCompletionResult {
|
|
|
124
129
|
lifecycleCommit: string | null;
|
|
125
130
|
recapExportPaths: string[];
|
|
126
131
|
snapshotId: string;
|
|
132
|
+
terminalReceipt: SyncedRefRetirementReceipt | null;
|
|
133
|
+
recordRetired: boolean;
|
|
127
134
|
}
|
|
128
135
|
export declare const ARCHIVE_SNAPSHOT_METADATA_FILENAME = ".oat-archive-source.json";
|
|
129
136
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"archive-utils.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/archive/archive-utils.ts"],"names":[],"mappings":"AAEA,OAAO,EAKL,MAAM,EAGP,MAAM,kBAAkB,CAAC;AAa1B,OAAO,EAAoB,KAAK,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EACL,gBAAgB,EAEhB,iBAAiB,EAClB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAEL,kBAAkB,EAClB,uBAAuB,EACvB,oBAAoB,
|
|
1
|
+
{"version":3,"file":"archive-utils.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/archive/archive-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,7 +5,8 @@ import { basename, dirname, isAbsolute, join, posix as path, relative, resolve,
|
|
|
5
5
|
import { promisify } from 'node:util';
|
|
6
6
|
import { defaultGitRunner } from '../../project/sync/git.js';
|
|
7
7
|
import { readSyncedRecord, writeSyncedRecord, } from '../../project/sync/record.js';
|
|
8
|
-
import { buildSyncTarget, commitRecordChange, preflightSyncedCheckout, removeSyncedCheckout, } from '../../project/sync/ref-sync.js';
|
|
8
|
+
import { buildSyncTarget, commitRecordChange, preflightSyncedCheckout, removeSyncedCheckout, retireSyncedRef, } from '../../project/sync/ref-sync.js';
|
|
9
|
+
import { probeSyncedTerminalRefs } from '../../project/sync/resolve-target.js';
|
|
9
10
|
import { canonicalizePath, resolveProjectScope, resolveScopeRoot, syncedRecordPath, } from '../../shared/project-scope.js';
|
|
10
11
|
import { CliError } from '../../../errors/cli-error.js';
|
|
11
12
|
import { copyDirectory, copySingleFile, dirExists, ensureDir, fileExists, } from '../../../fs/io.js';
|
|
@@ -356,6 +357,66 @@ async function verifyArchiveSnapshotMetadata(archivePath, expected) {
|
|
|
356
357
|
throw new CliError(`Existing archive \`${archivePath}\` does not match persisted snapshot \`${expected.snapshotName}\`; refusing to overwrite it.`);
|
|
357
358
|
}
|
|
358
359
|
}
|
|
360
|
+
async function resolveRecordlessSyncedArchiveIdentity(options, target, git, dependencies) {
|
|
361
|
+
const tentativeTarget = await resolveArchiveProjectTarget(options, dependencies);
|
|
362
|
+
assertDurableArchiveProjectTarget(tentativeTarget);
|
|
363
|
+
const archiveRoot = dirname(tentativeTarget.archivePath);
|
|
364
|
+
const candidates = [];
|
|
365
|
+
let entries;
|
|
366
|
+
try {
|
|
367
|
+
entries = await readdir(archiveRoot, { withFileTypes: true });
|
|
368
|
+
}
|
|
369
|
+
catch {
|
|
370
|
+
entries = [];
|
|
371
|
+
}
|
|
372
|
+
for (const entry of entries) {
|
|
373
|
+
if (!entry.isDirectory())
|
|
374
|
+
continue;
|
|
375
|
+
const archivePath = join(archiveRoot, entry.name);
|
|
376
|
+
let metadata;
|
|
377
|
+
try {
|
|
378
|
+
metadata = JSON.parse(await readFile(join(archivePath, ARCHIVE_SNAPSHOT_METADATA_FILENAME), 'utf8'));
|
|
379
|
+
}
|
|
380
|
+
catch {
|
|
381
|
+
continue;
|
|
382
|
+
}
|
|
383
|
+
if (isRecord(metadata) &&
|
|
384
|
+
metadata.projectName === options.projectName &&
|
|
385
|
+
metadata.scope === 'synced' &&
|
|
386
|
+
typeof metadata.snapshotName === 'string' &&
|
|
387
|
+
typeof metadata.sourceRefSha === 'string' &&
|
|
388
|
+
/^[0-9a-f]{40}$/.test(metadata.sourceRefSha)) {
|
|
389
|
+
candidates.push({
|
|
390
|
+
archivePath,
|
|
391
|
+
metadata: {
|
|
392
|
+
projectName: options.projectName,
|
|
393
|
+
snapshotName: metadata.snapshotName,
|
|
394
|
+
scope: 'synced',
|
|
395
|
+
sourceRefSha: metadata.sourceRefSha,
|
|
396
|
+
},
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
if (candidates.length === 0) {
|
|
401
|
+
throw new CliError(`Synced project ${options.projectName} has no active record and no persisted synced archive identity; refusing to create a replacement active record or a new snapshot.`, 2);
|
|
402
|
+
}
|
|
403
|
+
const probe = dependencies.probeSyncedTerminalRefs ?? probeSyncedTerminalRefs;
|
|
404
|
+
const matches = [];
|
|
405
|
+
for (const candidate of candidates) {
|
|
406
|
+
const terminal = await probe(target, candidate.metadata.sourceRefSha, git);
|
|
407
|
+
if (terminal.completedSha === candidate.metadata.sourceRefSha &&
|
|
408
|
+
(terminal.activeSha === null ||
|
|
409
|
+
terminal.activeSha === candidate.metadata.sourceRefSha)) {
|
|
410
|
+
matches.push(candidate);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
if (matches.length !== 1) {
|
|
414
|
+
throw new CliError(matches.length === 0
|
|
415
|
+
? `Synced project ${options.projectName} has no active record, but no persisted archive identity matches its authoritative completed ref; refusing terminal retry before export or S3 mutation.`
|
|
416
|
+
: `Synced project ${options.projectName} has no active record and multiple persisted archives match its authoritative completed ref; refusing an ambiguous terminal retry.`, 2);
|
|
417
|
+
}
|
|
418
|
+
return matches[0];
|
|
419
|
+
}
|
|
359
420
|
async function exportProjectSummary(archivePath, snapshotName, summaryExportPath, repoRoot, dependencies) {
|
|
360
421
|
const summarySource = join(archivePath, 'summary.md');
|
|
361
422
|
const exists = dependencies.fileExists ?? fileExists;
|
|
@@ -850,29 +911,42 @@ export async function archiveProjectOnCompletion(options, dependencies = {}) {
|
|
|
850
911
|
const syncTarget = isSynced
|
|
851
912
|
? buildSyncTarget(options.repoRoot, options.projectsRoot, options.projectName)
|
|
852
913
|
: null;
|
|
853
|
-
const git = dependencies.gitRunner ?? defaultGitRunner;
|
|
854
914
|
let activeRecord = record;
|
|
915
|
+
const git = dependencies.gitRunner ?? defaultGitRunner;
|
|
916
|
+
const recordlessIdentity = syncTarget && !activeRecord
|
|
917
|
+
? await resolveRecordlessSyncedArchiveIdentity(options, syncTarget, git, dependencies)
|
|
918
|
+
: null;
|
|
855
919
|
let sourceRefSha;
|
|
856
920
|
if (syncTarget) {
|
|
857
|
-
if (
|
|
858
|
-
|
|
921
|
+
if (recordlessIdentity) {
|
|
922
|
+
sourceRefSha = recordlessIdentity.metadata.sourceRefSha;
|
|
859
923
|
}
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
924
|
+
else {
|
|
925
|
+
const preflight = await (dependencies.preflightSyncedCheckout ?? preflightSyncedCheckout)(syncTarget, git);
|
|
926
|
+
const isBoundTerminalRetry = Boolean(preflight.sha &&
|
|
927
|
+
activeRecord?.archiveSourceRefSha === preflight.sha &&
|
|
928
|
+
preflight.status === 'unpushed');
|
|
929
|
+
if (preflight.status !== 'clean' &&
|
|
930
|
+
!(preflight.status === 'absent' &&
|
|
931
|
+
(activeRecord?.status === 'complete' ||
|
|
932
|
+
Boolean(activeRecord?.archiveSourceRefSha))) &&
|
|
933
|
+
!isBoundTerminalRetry) {
|
|
934
|
+
const recoveryCommand = preflight.status === 'absent'
|
|
935
|
+
? `oat project pull ${options.projectName}`
|
|
936
|
+
: `oat project push ${options.projectName}`;
|
|
937
|
+
throw new CliError(`Synced project ${options.projectName} is ${preflight.status}; run ${recoveryCommand} before archiving.`, 1);
|
|
938
|
+
}
|
|
939
|
+
sourceRefSha =
|
|
940
|
+
preflight.sha ??
|
|
941
|
+
activeRecord?.archiveSourceRefSha ??
|
|
942
|
+
(await git.run(['rev-parse', syncTarget.ref], {
|
|
943
|
+
cwd: options.repoRoot,
|
|
944
|
+
})).stdout;
|
|
867
945
|
}
|
|
868
|
-
sourceRefSha =
|
|
869
|
-
preflight.sha ??
|
|
870
|
-
(await git.run(['rev-parse', syncTarget.ref], { cwd: options.repoRoot }))
|
|
871
|
-
.stdout;
|
|
872
946
|
if (!/^[0-9a-f]{40}$/.test(sourceRefSha)) {
|
|
873
947
|
throw new CliError(`Unable to bind archive retry identity for ${options.projectName} to ${syncTarget.ref}.`, 2);
|
|
874
948
|
}
|
|
875
|
-
if (activeRecord
|
|
949
|
+
if (activeRecord?.archiveSourceRefSha &&
|
|
876
950
|
activeRecord.archiveSourceRefSha !== sourceRefSha) {
|
|
877
951
|
throw new CliError(`Archive retry for ${options.projectName} is bound to source ref ${activeRecord.archiveSourceRefSha}, but ${syncTarget.ref} is now ${sourceRefSha}. Restore the retained ref to the recorded commit to finish this archive transaction, or preserve the existing snapshot and start a separately reviewed recovery; refusing to accept stale archive content.`, 1);
|
|
878
952
|
}
|
|
@@ -881,9 +955,11 @@ export async function archiveProjectOnCompletion(options, dependencies = {}) {
|
|
|
881
955
|
repoRoot: options.repoRoot,
|
|
882
956
|
projectsRoot: options.projectsRoot,
|
|
883
957
|
projectName: options.projectName,
|
|
884
|
-
...(activeRecord?.archiveSnapshot
|
|
958
|
+
...((activeRecord?.archiveSnapshot ??
|
|
959
|
+
recordlessIdentity?.metadata.snapshotName)
|
|
885
960
|
? {
|
|
886
|
-
archiveSnapshot: activeRecord
|
|
961
|
+
archiveSnapshot: activeRecord?.archiveSnapshot ??
|
|
962
|
+
recordlessIdentity?.metadata.snapshotName,
|
|
887
963
|
archiveScope: projectScope,
|
|
888
964
|
}
|
|
889
965
|
: {}),
|
|
@@ -902,7 +978,9 @@ export async function archiveProjectOnCompletion(options, dependencies = {}) {
|
|
|
902
978
|
}
|
|
903
979
|
const archivePath = archiveTarget.archivePath;
|
|
904
980
|
const exportIdentity = syncTarget
|
|
905
|
-
? (activeRecord?.archiveSnapshot ??
|
|
981
|
+
? (activeRecord?.archiveSnapshot ??
|
|
982
|
+
recordlessIdentity?.metadata.snapshotName ??
|
|
983
|
+
snapshotName)
|
|
906
984
|
: snapshotName;
|
|
907
985
|
const snapshotId = syncTarget ? exportIdentity : basename(archivePath);
|
|
908
986
|
const shouldPersistArchiveSnapshot = Boolean(syncTarget &&
|
|
@@ -1000,6 +1078,9 @@ export async function archiveProjectOnCompletion(options, dependencies = {}) {
|
|
|
1000
1078
|
env: dependencies.env,
|
|
1001
1079
|
});
|
|
1002
1080
|
warnings.push(...access.warnings);
|
|
1081
|
+
if (syncTarget && !access.ok) {
|
|
1082
|
+
throw new CliError(`Synced archive durability for ${options.projectName} requires the configured S3 upload to succeed before terminal cleanup. ${access.warnings.join(' ') || 'Archive S3 access could not be verified.'}`, 1);
|
|
1083
|
+
}
|
|
1003
1084
|
if (access.ok) {
|
|
1004
1085
|
const remoteRepoRoot = await resolvePrimaryRepoRoot(options.repoRoot, dependencies);
|
|
1005
1086
|
s3Path = buildProjectArchiveS3Uri(options.s3Uri, remoteRepoRoot, exportIdentity);
|
|
@@ -1018,6 +1099,9 @@ export async function archiveProjectOnCompletion(options, dependencies = {}) {
|
|
|
1018
1099
|
}
|
|
1019
1100
|
catch (error) {
|
|
1020
1101
|
const message = error instanceof Error ? error.message : String(error);
|
|
1102
|
+
if (syncTarget) {
|
|
1103
|
+
throw new CliError(`Synced archive durability for ${options.projectName} requires the configured S3 upload to succeed before terminal cleanup: ${message}`, 1);
|
|
1104
|
+
}
|
|
1021
1105
|
warnings.push(`Archive S3 sync to \`${s3Path}\` failed: ${message}`);
|
|
1022
1106
|
s3Path = null;
|
|
1023
1107
|
}
|
|
@@ -1025,38 +1109,53 @@ export async function archiveProjectOnCompletion(options, dependencies = {}) {
|
|
|
1025
1109
|
}
|
|
1026
1110
|
let lifecycleCommit = null;
|
|
1027
1111
|
let recapExportPaths = [];
|
|
1112
|
+
let terminalReceipt = null;
|
|
1113
|
+
let recordRetired = false;
|
|
1028
1114
|
if (syncTarget) {
|
|
1029
|
-
if (!
|
|
1030
|
-
throw new CliError(`Synced project ${options.projectName}
|
|
1115
|
+
if (!sourceRefSha) {
|
|
1116
|
+
throw new CliError(`Synced project ${options.projectName} has no verified source SHA for terminal sealing.`, 2);
|
|
1117
|
+
}
|
|
1118
|
+
terminalReceipt = await (dependencies.retireSyncedRef ?? retireSyncedRef)(syncTarget, sourceRefSha, git);
|
|
1119
|
+
if (terminalReceipt.state !== 'completed-only' &&
|
|
1120
|
+
terminalReceipt.state !== 'matching-aliases') {
|
|
1121
|
+
throw new CliError(`Synced project ${options.projectName} did not reach a verified terminal ref state.`, 2);
|
|
1122
|
+
}
|
|
1123
|
+
const removed = await (dependencies.removeSyncedCheckout ?? removeSyncedCheckout)(syncTarget, git, { force: true });
|
|
1124
|
+
if (removed.status !== 'removed' && removed.status !== 'absent') {
|
|
1125
|
+
throw new CliError(`Synced checkout became ${removed.status} during archive; run oat project push ${options.projectName} and retry.`, 1);
|
|
1031
1126
|
}
|
|
1032
1127
|
if (projectRecapExport) {
|
|
1033
1128
|
recapExportPaths = (await listArchiveExportFiles(projectRecapExport.exportRoot)).filter((filePath) => basename(filePath) !== 'manifest.json' &&
|
|
1034
1129
|
basename(filePath) !== 'build-record.json');
|
|
1035
1130
|
}
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
};
|
|
1041
|
-
await writeRecord(recordPath, activeRecord);
|
|
1131
|
+
await (dependencies.removeSyncedRecord
|
|
1132
|
+
? dependencies.removeSyncedRecord(recordPath)
|
|
1133
|
+
: removePath(recordPath, { recursive: true, force: true }));
|
|
1134
|
+
recordRetired = true;
|
|
1042
1135
|
if (options.commit !== false) {
|
|
1043
1136
|
const pathspecs = [
|
|
1044
1137
|
recordPath,
|
|
1045
1138
|
...(summaryExportFile ? [summaryExportFile] : []),
|
|
1046
1139
|
...recapExportPaths,
|
|
1047
1140
|
];
|
|
1048
|
-
const
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1141
|
+
const lifecycleStatus = await git.run([
|
|
1142
|
+
'status',
|
|
1143
|
+
'--porcelain=v1',
|
|
1144
|
+
'--untracked-files=all',
|
|
1145
|
+
'--',
|
|
1146
|
+
...pathspecs.map((pathspec) => relative(canonicalizePath(resolve(options.repoRoot)), canonicalizePath(resolve(pathspec)))),
|
|
1147
|
+
], { cwd: options.repoRoot });
|
|
1148
|
+
const committed = lifecycleStatus.stdout === ''
|
|
1149
|
+
? null
|
|
1150
|
+
: await (dependencies.commitRecordChange ?? commitRecordChange)(options.repoRoot, pathspecs, `chore(oat): complete synced project ${options.projectName}`, git, {
|
|
1151
|
+
summaryExportPath: options.summaryExportPath,
|
|
1152
|
+
projectRoots: syncTarget,
|
|
1153
|
+
recapExportRoot: projectRecapExport?.exportRoot,
|
|
1154
|
+
});
|
|
1053
1155
|
lifecycleCommit =
|
|
1054
1156
|
committed?.sha ??
|
|
1055
|
-
(await recoverSyncedLifecycleCommit(options.repoRoot, pathspecs,
|
|
1056
|
-
|
|
1057
|
-
const removed = await (dependencies.removeSyncedCheckout ?? removeSyncedCheckout)(syncTarget, git);
|
|
1058
|
-
if (removed.status !== 'removed' && removed.status !== 'absent') {
|
|
1059
|
-
throw new CliError(`Synced checkout became ${removed.status} during archive; run oat project push ${options.projectName} and retry.`, 1);
|
|
1157
|
+
(await recoverSyncedLifecycleCommit(options.repoRoot, pathspecs, options.projectName, `chore(oat): complete synced project ${options.projectName}`, git));
|
|
1158
|
+
await dependencies.afterLifecycleCommit?.();
|
|
1060
1159
|
}
|
|
1061
1160
|
}
|
|
1062
1161
|
return {
|
|
@@ -1068,12 +1167,14 @@ export async function archiveProjectOnCompletion(options, dependencies = {}) {
|
|
|
1068
1167
|
lifecycleCommit,
|
|
1069
1168
|
recapExportPaths,
|
|
1070
1169
|
snapshotId,
|
|
1170
|
+
terminalReceipt,
|
|
1171
|
+
recordRetired,
|
|
1071
1172
|
};
|
|
1072
1173
|
}
|
|
1073
|
-
async function recoverSyncedLifecycleCommit(repoRoot, pathspecs,
|
|
1174
|
+
async function recoverSyncedLifecycleCommit(repoRoot, pathspecs, projectName, expectedSubject, git) {
|
|
1074
1175
|
const [recordPathspec] = pathspecs;
|
|
1075
1176
|
if (!recordPathspec) {
|
|
1076
|
-
throw new CliError(`Unable to recover the prior lifecycle commit for ${
|
|
1177
|
+
throw new CliError(`Unable to recover the prior lifecycle commit for ${projectName}: no lifecycle paths were supplied.`, 2);
|
|
1077
1178
|
}
|
|
1078
1179
|
const recordPath = relative(resolve(repoRoot), resolve(recordPathspec))
|
|
1079
1180
|
.split(sep)
|
|
@@ -1086,7 +1187,7 @@ async function recoverSyncedLifecycleCommit(repoRoot, pathspecs, record, expecte
|
|
|
1086
1187
|
cwd: repoRoot,
|
|
1087
1188
|
})).stdout;
|
|
1088
1189
|
if (!/^[0-9a-f]{40}$/.test(candidate)) {
|
|
1089
|
-
throw new CliError(`Unable to recover the prior lifecycle commit for ${
|
|
1190
|
+
throw new CliError(`Unable to recover the prior lifecycle commit for ${projectName}.`, 2);
|
|
1090
1191
|
}
|
|
1091
1192
|
const subject = (await git.run(['show', '-s', '--format=%s', candidate], { cwd: repoRoot })).stdout;
|
|
1092
1193
|
const ancestor = await git.run(['merge-base', '--is-ancestor', candidate, 'HEAD'], { cwd: repoRoot, allowFailure: true });
|
|
@@ -1095,20 +1196,16 @@ async function recoverSyncedLifecycleCommit(repoRoot, pathspecs, record, expecte
|
|
|
1095
1196
|
.filter(Boolean)
|
|
1096
1197
|
.sort();
|
|
1097
1198
|
const contentsMatch = await git.run(['diff', '--quiet', candidate, '--', ...normalizedPathspecs], { cwd: repoRoot, allowFailure: true });
|
|
1098
|
-
const committedRecord = await git.run(['show', `${candidate}:${recordPath}`], {
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
}
|
|
1103
|
-
catch {
|
|
1104
|
-
parsedRecord = null;
|
|
1105
|
-
}
|
|
1199
|
+
const committedRecord = await git.run(['show', `${candidate}:${recordPath}`], {
|
|
1200
|
+
cwd: repoRoot,
|
|
1201
|
+
allowFailure: true,
|
|
1202
|
+
});
|
|
1106
1203
|
if (subject !== expectedSubject ||
|
|
1107
1204
|
ancestor.code !== 0 ||
|
|
1108
1205
|
contentsMatch.code !== 0 ||
|
|
1109
1206
|
JSON.stringify(changedPaths) !== JSON.stringify(normalizedPathspecs) ||
|
|
1110
|
-
|
|
1111
|
-
throw new CliError(`Unable to recover lifecycle commit ${candidate} for ${
|
|
1207
|
+
committedRecord.code === 0) {
|
|
1208
|
+
throw new CliError(`Unable to recover lifecycle commit ${candidate} for ${projectName}: subject, path set, record deletion, contents, or branch relationship did not match the completed archive transaction.`, 2);
|
|
1112
1209
|
}
|
|
1113
1210
|
return candidate;
|
|
1114
1211
|
}
|
|
@@ -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;
|
|
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;AA2JD,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"}
|
|
@@ -82,6 +82,10 @@ async function buildDryRunReport(dependencies, repoRoot, config, target, archive
|
|
|
82
82
|
snapshotId: projectScope === 'synced'
|
|
83
83
|
? snapshotName
|
|
84
84
|
: basename(archiveTarget.archivePath),
|
|
85
|
+
completedRef: null,
|
|
86
|
+
verifiedSourceSha: null,
|
|
87
|
+
activeAliasDisposition: null,
|
|
88
|
+
recordRetired: false,
|
|
85
89
|
};
|
|
86
90
|
}
|
|
87
91
|
function emitArchivePushText(report, summaryExportPath, logger) {
|
|
@@ -148,10 +152,11 @@ export async function runArchivePushCommand(dependencies, projectPathArg, option
|
|
|
148
152
|
timestamp: dependencies.timestamp,
|
|
149
153
|
});
|
|
150
154
|
assertDurableArchiveProjectTarget(archiveTarget);
|
|
151
|
-
|
|
155
|
+
const dryRun = options.dryRun === true || context.dryRun;
|
|
156
|
+
const recordlessSyncedApply = projectScope === 'synced' && syncedRecord === null && !dryRun;
|
|
157
|
+
if (options.projectRecapRun?.trim() && !recordlessSyncedApply) {
|
|
152
158
|
await dependencies.verifySelectedProjectRecapForArchive(target.projectPath, options.projectRecapRun.trim());
|
|
153
159
|
}
|
|
154
|
-
const dryRun = options.dryRun === true || context.dryRun;
|
|
155
160
|
if (dryRun) {
|
|
156
161
|
const report = await buildDryRunReport(dependencies, repoRoot, config, target, archiveTarget, snapshotName, projectScope);
|
|
157
162
|
emitArchivePushReport(report, config.archive?.summaryExportPath, context);
|
|
@@ -174,6 +179,14 @@ export async function runArchivePushCommand(dependencies, projectPathArg, option
|
|
|
174
179
|
lifecycleCommit: result.lifecycleCommit,
|
|
175
180
|
recapExportPaths: result.recapExportPaths,
|
|
176
181
|
snapshotId: result.snapshotId,
|
|
182
|
+
completedRef: result.terminalReceipt?.completedRef ?? null,
|
|
183
|
+
verifiedSourceSha: result.terminalReceipt?.verifiedSha ?? null,
|
|
184
|
+
activeAliasDisposition: result.terminalReceipt
|
|
185
|
+
? result.terminalReceipt.activeAliasRetained
|
|
186
|
+
? 'retained'
|
|
187
|
+
: 'removed'
|
|
188
|
+
: null,
|
|
189
|
+
recordRetired: result.recordRetired,
|
|
177
190
|
};
|
|
178
191
|
emitArchivePushReport(report, config.archive?.summaryExportPath, context);
|
|
179
192
|
process.exitCode = 0;
|
|
@@ -4,6 +4,7 @@ import { type LinksInput } from './render.js';
|
|
|
4
4
|
export interface ComputeLinksOptions {
|
|
5
5
|
durableSummaryPath?: string;
|
|
6
6
|
now: Date;
|
|
7
|
+
ref?: string;
|
|
7
8
|
}
|
|
8
9
|
export declare function computeLinksInput(target: SyncTarget, git: GitRunner, options: ComputeLinksOptions): Promise<LinksInput>;
|
|
9
10
|
//# sourceMappingURL=compute.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compute.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/links/compute.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAElE,OAAO,EAGL,KAAK,UAAU,EAChB,MAAM,UAAU,CAAC;AAElB,MAAM,WAAW,mBAAmB;IAClC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,GAAG,EAAE,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"compute.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/links/compute.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAElE,OAAO,EAGL,KAAK,UAAU,EAChB,MAAM,UAAU,CAAC;AAElB,MAAM,WAAW,mBAAmB;IAClC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,GAAG,EAAE,IAAI,CAAC;IACV,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,UAAU,EAClB,GAAG,EAAE,SAAS,EACd,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,UAAU,CAAC,CA8BrB"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { LINKABLE_ARTIFACTS, } from './render.js';
|
|
2
2
|
export async function computeLinksInput(target, git, options) {
|
|
3
|
-
|
|
3
|
+
const selectedRef = options.ref ?? target.ref;
|
|
4
|
+
await git.run(['fetch', target.remote, `+${selectedRef}:${selectedRef}`], {
|
|
4
5
|
cwd: target.repoRoot,
|
|
5
6
|
});
|
|
6
7
|
const [sha, tree, origin] = await Promise.all([
|
|
7
|
-
git.run(['rev-parse',
|
|
8
|
-
git.run(['ls-tree', '--name-only',
|
|
8
|
+
git.run(['rev-parse', selectedRef], { cwd: target.repoRoot }),
|
|
9
|
+
git.run(['ls-tree', '--name-only', selectedRef], { cwd: target.repoRoot }),
|
|
9
10
|
git.run(['remote', 'get-url', target.remote], { cwd: target.repoRoot }),
|
|
10
11
|
]);
|
|
11
12
|
const treeNames = new Set(tree.stdout
|
|
@@ -16,7 +17,7 @@ export async function computeLinksInput(target, git, options) {
|
|
|
16
17
|
return {
|
|
17
18
|
slug: target.slug,
|
|
18
19
|
sha: sha.stdout,
|
|
19
|
-
ref:
|
|
20
|
+
ref: selectedRef,
|
|
20
21
|
originUrl: origin.stdout,
|
|
21
22
|
present,
|
|
22
23
|
...(options.durableSummaryPath
|
|
@@ -1,17 +1,26 @@
|
|
|
1
1
|
import { type CommandContext, type GlobalOptions } from '../../../app/command-context.js';
|
|
2
2
|
import { type GitRunner } from '../../project/sync/git.js';
|
|
3
|
+
import { type SyncTarget } from '../../project/sync/ref-sync.js';
|
|
3
4
|
import { resolveSyncedTarget } from '../../project/sync/resolve-target.js';
|
|
5
|
+
import { resolveProjectsRoot } from '../../shared/oat-paths.js';
|
|
4
6
|
import { Command } from 'commander';
|
|
5
7
|
import { computeLinksInput } from './compute.js';
|
|
6
8
|
interface ProjectLinksDependencies {
|
|
7
9
|
buildCommandContext: (options: GlobalOptions) => CommandContext;
|
|
8
10
|
resolveProjectRoot: (cwd: string) => Promise<string>;
|
|
11
|
+
resolveProjectsRoot: typeof resolveProjectsRoot;
|
|
9
12
|
resolveSyncedTarget: typeof resolveSyncedTarget;
|
|
13
|
+
resolveLinksTarget: typeof resolveLinksTarget;
|
|
10
14
|
computeLinksInput: typeof computeLinksInput;
|
|
11
15
|
gitRunner: GitRunner;
|
|
12
16
|
processEnv: NodeJS.ProcessEnv;
|
|
13
17
|
now: () => Date;
|
|
14
18
|
}
|
|
19
|
+
interface ResolvedLinksTarget {
|
|
20
|
+
target: SyncTarget;
|
|
21
|
+
ref: string;
|
|
22
|
+
}
|
|
23
|
+
export declare function resolveLinksTarget(repoRoot: string, projectsRoot: string, pathOrSlug: string | undefined, env: NodeJS.ProcessEnv, git: GitRunner, resolveTarget: typeof resolveSyncedTarget): Promise<ResolvedLinksTarget>;
|
|
15
24
|
export declare function createProjectLinksCommand(overrides?: Partial<ProjectLinksDependencies>): Command;
|
|
16
25
|
export {};
|
|
17
26
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/links/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAoB,KAAK,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EAAE,mBAAmB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/links/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAoB,KAAK,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EAGL,KAAK,UAAU,EAChB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAEL,mBAAmB,EACpB,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AASjE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAQ9C,UAAU,wBAAwB;IAChC,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,mBAAmB,EAAE,OAAO,mBAAmB,CAAC;IAChD,mBAAmB,EAAE,OAAO,mBAAmB,CAAC;IAChD,kBAAkB,EAAE,OAAO,kBAAkB,CAAC;IAC9C,iBAAiB,EAAE,OAAO,iBAAiB,CAAC;IAC5C,SAAS,EAAE,SAAS,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC;IAC9B,GAAG,EAAE,MAAM,IAAI,CAAC;CACjB;AAmCD,UAAU,mBAAmB;IAC3B,MAAM,EAAE,UAAU,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;CACb;AAwBD,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,GAAG,EAAE,MAAM,CAAC,UAAU,EACtB,GAAG,EAAE,SAAS,EACd,aAAa,EAAE,OAAO,mBAAmB,GACxC,OAAO,CAAC,mBAAmB,CAAC,CAgE9B;AAoDD,wBAAgB,yBAAyB,CACvC,SAAS,GAAE,OAAO,CAAC,wBAAwB,CAAM,GAChD,OAAO,CAsBT"}
|