@open-agent-toolkit/cli 0.2.40 → 0.2.45
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/agents/oat-codebase-mapper.md +15 -3
- package/assets/agents/oat-phase-implementer.md +34 -9
- package/assets/agents/oat-reviewer.md +2 -2
- package/assets/bundle-metadata.json +1 -1
- package/assets/docs/cli-utilities/configuration.md +11 -1
- package/assets/docs/cli-utilities/tool-packs.md +8 -0
- package/assets/docs/contributing/skills.md +67 -14
- package/assets/docs/quickstart.md +9 -0
- package/assets/docs/reference/cli-reference.md +56 -1
- package/assets/docs/reference/file-locations.md +18 -1
- package/assets/docs/reference/oat-directory-structure.md +20 -4
- package/assets/docs/workflows/projects/artifacts.md +27 -1
- package/assets/docs/workflows/projects/implementation-execution.md +22 -0
- package/assets/docs/workflows/projects/index.md +6 -0
- package/assets/docs/workflows/projects/lifecycle.md +19 -5
- package/assets/docs/workflows/projects/picking-up-projects.md +75 -0
- package/assets/docs/workflows/projects/pr-flow.md +22 -1
- package/assets/docs/workflows/projects/reviewing-oat-prs.md +60 -0
- package/assets/public-package-versions.json +4 -4
- package/assets/skills/analyze/SKILL.md +13 -5
- package/assets/skills/compare/SKILL.md +11 -2
- package/assets/skills/oat-brainstorm/SKILL.md +135 -32
- package/assets/skills/oat-brainstorm/references/destinations.md +9 -6
- package/assets/skills/oat-cursor-cloud-projects/SKILL.md +11 -1
- package/assets/skills/oat-dispatch-subagents/SKILL.md +19 -6
- package/assets/skills/oat-doctor/SKILL.md +8 -1
- package/assets/skills/oat-project-autonomous/SKILL.md +45 -1
- package/assets/skills/oat-project-autonomous/references/gate-inventory.md +8 -8
- package/assets/skills/oat-project-capture/SKILL.md +29 -9
- package/assets/skills/oat-project-complete/SKILL.md +610 -38
- package/assets/skills/oat-project-complete/scripts/parse-completion-retry-fields.mjs +265 -0
- package/assets/skills/oat-project-complete/scripts/recover-completion-receipts.mjs +764 -0
- package/assets/skills/oat-project-complete/scripts/resolve-completion-retry.mjs +134 -0
- package/assets/skills/oat-project-complete/scripts/validate-nonarchive-lifecycle-receipt.mjs +160 -0
- package/assets/skills/oat-project-design/SKILL.md +33 -9
- package/assets/skills/oat-project-discover/SKILL.md +16 -3
- package/assets/skills/oat-project-document/SKILL.md +10 -4
- package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +8 -8
- package/assets/skills/oat-project-implement/SKILL.md +14 -3
- package/assets/skills/oat-project-implement/references/completion-and-closeout.md +18 -6
- package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +8 -8
- package/assets/skills/oat-project-implement/references/phase-execution.md +9 -3
- package/assets/skills/oat-project-implement/references/plan-and-resume.md +3 -0
- package/assets/skills/oat-project-import-plan/SKILL.md +15 -9
- package/assets/skills/oat-project-new/SKILL.md +7 -5
- package/assets/skills/oat-project-next/SKILL.md +32 -10
- package/assets/skills/oat-project-plan/SKILL.md +18 -3
- package/assets/skills/oat-project-pr-final/SKILL.md +23 -2
- package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +8 -8
- package/assets/skills/oat-project-pr-progress/SKILL.md +23 -2
- package/assets/skills/oat-project-progress/SKILL.md +23 -9
- package/assets/skills/oat-project-promote-spec-driven/SKILL.md +20 -2
- package/assets/skills/oat-project-quick-start/SKILL.md +48 -18
- package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +8 -8
- package/assets/skills/oat-project-reconcile/SKILL.md +14 -10
- package/assets/skills/oat-project-retro/SKILL.md +3 -3
- package/assets/skills/oat-project-retro/references/apply-procedure.md +102 -6
- package/assets/skills/oat-project-retro-file/SKILL.md +57 -6
- package/assets/skills/oat-project-review-provide/SKILL.md +56 -6
- package/assets/skills/oat-project-review-receive/SKILL.md +16 -7
- package/assets/skills/oat-project-review-receive-remote/SKILL.md +9 -3
- package/assets/skills/oat-project-revise/SKILL.md +12 -3
- package/assets/skills/oat-project-spec/SKILL.md +16 -3
- package/assets/skills/oat-project-summary/SKILL.md +113 -13
- package/assets/skills/oat-repo-improve/SKILL.md +18 -7
- package/assets/skills/oat-review-provide-remote/SKILL.md +11 -2
- package/assets/skills/oat-wave-execute/SKILL.md +34 -2
- package/assets/skills/oat-worktree-bootstrap/SKILL.md +13 -1
- package/assets/skills/oat-worktree-bootstrap-auto/SKILL.md +13 -1
- package/dist/commands/config/index.d.ts +1 -0
- package/dist/commands/config/index.d.ts.map +1 -1
- package/dist/commands/config/index.js +30 -2
- package/dist/commands/doctor/index.d.ts +2 -0
- package/dist/commands/doctor/index.d.ts.map +1 -1
- package/dist/commands/doctor/index.js +27 -3
- package/dist/commands/doctor/synced-projects.d.ts +12 -0
- package/dist/commands/doctor/synced-projects.d.ts.map +1 -0
- package/dist/commands/doctor/synced-projects.js +208 -0
- package/dist/commands/init/gitattributes.d.ts +4 -0
- package/dist/commands/init/gitattributes.d.ts.map +1 -0
- package/dist/commands/init/gitattributes.js +12 -0
- package/dist/commands/init/gitignore.d.ts +8 -1
- package/dist/commands/init/gitignore.d.ts.map +1 -1
- package/dist/commands/init/gitignore.js +146 -41
- package/dist/commands/init/index.d.ts +2 -0
- package/dist/commands/init/index.d.ts.map +1 -1
- package/dist/commands/init/index.js +3 -0
- package/dist/commands/init/managed-block.d.ts +10 -0
- package/dist/commands/init/managed-block.d.ts.map +1 -0
- package/dist/commands/init/managed-block.js +40 -0
- package/dist/commands/init/tools/workflows/install-workflows.js +1 -1
- package/dist/commands/local/index.d.ts.map +1 -1
- package/dist/commands/local/index.js +5 -1
- package/dist/commands/local/sync.d.ts +4 -0
- package/dist/commands/local/sync.d.ts.map +1 -1
- package/dist/commands/local/sync.js +123 -2
- package/dist/commands/pjm/adoption.d.ts +2 -0
- package/dist/commands/pjm/adoption.d.ts.map +1 -1
- package/dist/commands/pjm/adoption.js +1 -1
- package/dist/commands/project/archive/archive-utils.d.ts +24 -0
- package/dist/commands/project/archive/archive-utils.d.ts.map +1 -1
- package/dist/commands/project/archive/archive-utils.js +349 -22
- 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 +5 -1
- package/dist/commands/project/archive/push-runner.d.ts.map +1 -1
- package/dist/commands/project/archive/push-runner.js +33 -4
- package/dist/commands/project/complete-state/index.d.ts.map +1 -1
- package/dist/commands/project/complete-state/index.js +3 -1
- package/dist/commands/project/index.d.ts.map +1 -1
- package/dist/commands/project/index.js +12 -0
- package/dist/commands/project/links/compute.d.ts +9 -0
- package/dist/commands/project/links/compute.d.ts.map +1 -0
- package/dist/commands/project/links/compute.js +27 -0
- package/dist/commands/project/links/index.d.ts +17 -0
- package/dist/commands/project/links/index.d.ts.map +1 -0
- package/dist/commands/project/links/index.js +72 -0
- package/dist/commands/project/links/refresh.d.ts +26 -0
- package/dist/commands/project/links/refresh.d.ts.map +1 -0
- package/dist/commands/project/links/refresh.js +92 -0
- package/dist/commands/project/links/render.d.ts +24 -0
- package/dist/commands/project/links/render.d.ts.map +1 -0
- package/dist/commands/project/links/render.js +68 -0
- package/dist/commands/project/list.d.ts +5 -0
- package/dist/commands/project/list.d.ts.map +1 -1
- package/dist/commands/project/list.js +182 -9
- package/dist/commands/project/migrate/index.d.ts +22 -0
- package/dist/commands/project/migrate/index.d.ts.map +1 -0
- package/dist/commands/project/migrate/index.js +79 -0
- package/dist/commands/project/new/index.d.ts +2 -0
- package/dist/commands/project/new/index.d.ts.map +1 -1
- package/dist/commands/project/new/index.js +14 -2
- package/dist/commands/project/new/scaffold.d.ts +22 -1
- package/dist/commands/project/new/scaffold.d.ts.map +1 -1
- package/dist/commands/project/new/scaffold.js +287 -69
- package/dist/commands/project/open/index.d.ts +16 -0
- package/dist/commands/project/open/index.d.ts.map +1 -1
- package/dist/commands/project/open/index.js +151 -19
- package/dist/commands/project/pause/index.d.ts +8 -0
- package/dist/commands/project/pause/index.d.ts.map +1 -1
- package/dist/commands/project/pause/index.js +129 -19
- package/dist/commands/project/prune/index.d.ts +21 -0
- package/dist/commands/project/prune/index.d.ts.map +1 -0
- package/dist/commands/project/prune/index.js +95 -0
- package/dist/commands/project/pull/index.d.ts +28 -0
- package/dist/commands/project/pull/index.d.ts.map +1 -0
- package/dist/commands/project/pull/index.js +157 -0
- package/dist/commands/project/push/index.d.ts +22 -0
- package/dist/commands/project/push/index.d.ts.map +1 -0
- package/dist/commands/project/push/index.js +100 -0
- package/dist/commands/project/scope/index.d.ts +17 -0
- package/dist/commands/project/scope/index.d.ts.map +1 -0
- package/dist/commands/project/scope/index.js +107 -0
- package/dist/commands/project/split/run.d.ts +4 -0
- package/dist/commands/project/split/run.d.ts.map +1 -1
- package/dist/commands/project/split/run.js +48 -10
- package/dist/commands/project/sync/git.d.ts +18 -0
- package/dist/commands/project/sync/git.d.ts.map +1 -0
- package/dist/commands/project/sync/git.js +60 -0
- package/dist/commands/project/sync/record.d.ts +22 -0
- package/dist/commands/project/sync/record.d.ts.map +1 -0
- package/dist/commands/project/sync/record.js +133 -0
- package/dist/commands/project/sync/ref-sync.d.ts +120 -0
- package/dist/commands/project/sync/ref-sync.d.ts.map +1 -0
- package/dist/commands/project/sync/ref-sync.js +962 -0
- package/dist/commands/project/sync/resolve-target.d.ts +27 -0
- package/dist/commands/project/sync/resolve-target.d.ts.map +1 -0
- package/dist/commands/project/sync/resolve-target.js +159 -0
- package/dist/commands/shared/oat-paths.d.ts +4 -1
- package/dist/commands/shared/oat-paths.d.ts.map +1 -1
- package/dist/commands/shared/oat-paths.js +2 -2
- package/dist/commands/shared/project-scope.d.ts +23 -0
- package/dist/commands/shared/project-scope.d.ts.map +1 -0
- package/dist/commands/shared/project-scope.js +106 -0
- package/dist/commands/tools/migrate/index.js +1 -1
- package/dist/commands/tools/shared/pack-inventory.d.ts.map +1 -1
- package/dist/commands/tools/shared/pack-inventory.js +11 -0
- package/dist/commands/tools/shared/pack-lifecycle.js +1 -1
- package/dist/commands/tools/shared/pack-reconcile.d.ts.map +1 -1
- package/dist/commands/tools/shared/pack-reconcile.js +4 -1
- package/dist/commands/tools/update/index.d.ts.map +1 -1
- package/dist/commands/tools/update/index.js +20 -10
- package/dist/commands/tools/update/update-tools.d.ts +2 -0
- package/dist/commands/tools/update/update-tools.d.ts.map +1 -1
- package/dist/config/oat-config.d.ts +6 -3
- package/dist/config/oat-config.d.ts.map +1 -1
- package/dist/config/oat-config.js +41 -7
- package/dist/config/resolve.d.ts.map +1 -1
- package/dist/config/resolve.js +2 -1
- package/dist/fs/io.d.ts +2 -1
- package/dist/fs/io.d.ts.map +1 -1
- package/dist/fs/io.js +5 -2
- package/dist/projects/split/finalize.d.ts.map +1 -1
- package/dist/projects/split/finalize.js +55 -2
- package/dist/projects/split/resume.d.ts +3 -0
- package/dist/projects/split/resume.d.ts.map +1 -1
- package/dist/projects/split/resume.js +34 -7
- package/dist/projects/split/seed-children.d.ts.map +1 -1
- package/dist/projects/split/seed-children.js +6 -0
- package/dist/projects/split/write-parent.d.ts +7 -0
- package/dist/projects/split/write-parent.d.ts.map +1 -1
- package/dist/projects/split/write-parent.js +7 -4
- package/dist/release/public-package-contract.d.ts.map +1 -1
- package/dist/release/public-package-contract.js +1 -0
- package/dist/validation/skills.d.ts.map +1 -1
- package/dist/validation/skills.js +434 -0
- package/package.json +4 -4
- package/dist/__tests__/skills/split-flow-fixtures.d.ts +0 -50
- package/dist/__tests__/skills/split-flow-fixtures.d.ts.map +0 -1
- package/dist/__tests__/skills/split-flow-fixtures.js +0 -161
- package/dist/commands/__tests__/helpers.d.ts +0 -12
- package/dist/commands/__tests__/helpers.d.ts.map +0 -1
- package/dist/commands/__tests__/helpers.js +0 -36
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { execFile } from 'node:child_process';
|
|
2
|
-
import { readFile, writeFile } from 'node:fs/promises';
|
|
3
|
-
import { join } from 'node:path';
|
|
2
|
+
import { readFile, rm, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { dirname, isAbsolute, join, relative } from 'node:path';
|
|
4
4
|
import { promisify } from 'node:util';
|
|
5
|
-
import {
|
|
5
|
+
import { canonicalizePath } from '../shared/project-scope.js';
|
|
6
|
+
import { CliError } from '../../errors/cli-error.js';
|
|
7
|
+
import { applyManagedBlock } from './managed-block.js';
|
|
6
8
|
const SECTION_START = '# OAT core';
|
|
7
9
|
const SECTION_END = '# END OAT core';
|
|
8
10
|
const OAT_STATE_DASHBOARD_PATH = '.oat/state.md';
|
|
@@ -12,53 +14,156 @@ const CORE_ENTRIES = [
|
|
|
12
14
|
'.oat/state.md',
|
|
13
15
|
'.oat/projects/local/**',
|
|
14
16
|
'.oat/projects/archived/**',
|
|
17
|
+
'.oat/projects/synced/*/',
|
|
15
18
|
'!.oat/projects/local/.gitkeep',
|
|
16
19
|
'!.oat/projects/archived/.gitkeep',
|
|
17
20
|
];
|
|
18
|
-
function
|
|
19
|
-
|
|
21
|
+
function managedScopedRules(content) {
|
|
22
|
+
if (content === null)
|
|
23
|
+
return [];
|
|
24
|
+
const startIndex = content.indexOf(SECTION_START);
|
|
25
|
+
const endIndex = content.indexOf(SECTION_END);
|
|
26
|
+
if (startIndex === -1 || endIndex < startIndex)
|
|
27
|
+
return [];
|
|
28
|
+
return content
|
|
29
|
+
.slice(startIndex + SECTION_START.length, endIndex)
|
|
30
|
+
.split('\n')
|
|
31
|
+
.filter((line) => /^\/(?:.+\/)?(?:local\/\*\*|synced\/\*\/|archived\/\*\*)$/.test(line));
|
|
20
32
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
action: 'created',
|
|
29
|
-
entries: CORE_ENTRIES,
|
|
30
|
-
stateDashboardIndexAction: await untrackOatStateDashboard(repoRoot),
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
const content = await readFile(gitignorePath, 'utf8');
|
|
34
|
-
const startIdx = content.indexOf(SECTION_START);
|
|
35
|
-
const endIdx = content.indexOf(SECTION_END);
|
|
36
|
-
if (startIdx !== -1 && endIdx !== -1) {
|
|
37
|
-
const existingSection = content.slice(startIdx, endIdx + SECTION_END.length);
|
|
38
|
-
if (existingSection === section) {
|
|
39
|
-
return {
|
|
40
|
-
action: 'no-change',
|
|
41
|
-
entries: CORE_ENTRIES,
|
|
42
|
-
stateDashboardIndexAction: await untrackOatStateDashboard(repoRoot),
|
|
43
|
-
};
|
|
33
|
+
async function readOptionalFile(path) {
|
|
34
|
+
try {
|
|
35
|
+
return await readFile(path, 'utf8');
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {
|
|
39
|
+
return null;
|
|
44
40
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
41
|
+
throw error;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function removeUnmanagedRule(content, rule) {
|
|
45
|
+
let inManagedBlock = false;
|
|
46
|
+
return content
|
|
47
|
+
.split('\n')
|
|
48
|
+
.filter((line) => {
|
|
49
|
+
if (line === SECTION_START)
|
|
50
|
+
inManagedBlock = true;
|
|
51
|
+
const keep = line !== rule || inManagedBlock;
|
|
52
|
+
if (line === SECTION_END)
|
|
53
|
+
inManagedBlock = false;
|
|
54
|
+
return keep;
|
|
55
|
+
})
|
|
56
|
+
.join('\n');
|
|
57
|
+
}
|
|
58
|
+
export async function isSyncedRuleApplied(repoRoot) {
|
|
59
|
+
try {
|
|
60
|
+
await execFileAsync('git', [
|
|
61
|
+
'check-ignore',
|
|
62
|
+
'--quiet',
|
|
63
|
+
'--no-index',
|
|
64
|
+
'.oat/projects/synced/__probe__/',
|
|
65
|
+
], { cwd: repoRoot });
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
export async function applyOatCoreGitignore(repoRoot, additionalEntries = []) {
|
|
73
|
+
const gitignorePath = join(repoRoot, '.gitignore');
|
|
74
|
+
const existingScopedRules = managedScopedRules(await readOptionalFile(gitignorePath));
|
|
75
|
+
const result = await applyManagedBlock(gitignorePath, {
|
|
76
|
+
start: SECTION_START,
|
|
77
|
+
end: SECTION_END,
|
|
78
|
+
entries: [
|
|
79
|
+
...new Set([
|
|
80
|
+
...CORE_ENTRIES,
|
|
81
|
+
...existingScopedRules,
|
|
82
|
+
...additionalEntries,
|
|
83
|
+
]),
|
|
84
|
+
],
|
|
85
|
+
});
|
|
56
86
|
return {
|
|
57
|
-
|
|
58
|
-
entries: CORE_ENTRIES,
|
|
87
|
+
...result,
|
|
59
88
|
stateDashboardIndexAction: await untrackOatStateDashboard(repoRoot),
|
|
60
89
|
};
|
|
61
90
|
}
|
|
91
|
+
export async function ensureScopedRootGitignore(repoRoot, scopeRoot, scope, git, dirtyMessage = 'Cannot repair the configured project-root rule because .gitignore has staged or unstaged changes; commit or stash those changes, then retry.') {
|
|
92
|
+
const canonicalRepoRoot = canonicalizePath(repoRoot);
|
|
93
|
+
const canonicalScopeRoot = canonicalizePath(scopeRoot);
|
|
94
|
+
const scopeRelative = relative(canonicalRepoRoot, canonicalScopeRoot);
|
|
95
|
+
if (scopeRelative === '..' ||
|
|
96
|
+
scopeRelative.startsWith('../') ||
|
|
97
|
+
scopeRelative.startsWith('..\\') ||
|
|
98
|
+
isAbsolute(scopeRelative)) {
|
|
99
|
+
return { changed: false, before: undefined };
|
|
100
|
+
}
|
|
101
|
+
const normalizedRoot = scopeRelative.split('\\').join('/');
|
|
102
|
+
const scopeRule = scope === 'local' ? `/${normalizedRoot}/**` : `/${normalizedRoot}/*/`;
|
|
103
|
+
const defaultRoot = `.oat/projects/${scope}`;
|
|
104
|
+
const customRules = normalizedRoot === defaultRoot ? [] : [scopeRule];
|
|
105
|
+
if (scope === 'synced') {
|
|
106
|
+
const archiveRoot = `${normalizedRoot.slice(0, normalizedRoot.lastIndexOf('/') + 1)}archived`;
|
|
107
|
+
if (archiveRoot !== '.oat/projects/archived') {
|
|
108
|
+
customRules.push(`/${archiveRoot}/**`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
const gitignorePath = join(repoRoot, '.gitignore');
|
|
112
|
+
const current = await readOptionalFile(gitignorePath);
|
|
113
|
+
const sectionStart = current?.indexOf(SECTION_START) ?? -1;
|
|
114
|
+
const sectionEnd = current?.indexOf(SECTION_END) ?? -1;
|
|
115
|
+
const managedSection = current && sectionStart !== -1 && sectionEnd >= sectionStart
|
|
116
|
+
? current.slice(sectionStart, sectionEnd)
|
|
117
|
+
: '';
|
|
118
|
+
const managedLines = managedSection.split('\n');
|
|
119
|
+
const customRulesManaged = customRules.every((rule) => managedLines.includes(rule));
|
|
120
|
+
const probes = [join(canonicalScopeRoot, '__probe__', 'artifact.md')];
|
|
121
|
+
if (scope === 'synced') {
|
|
122
|
+
probes.push(join(dirname(canonicalScopeRoot), 'archived', '__probe__', 'artifact.md'));
|
|
123
|
+
}
|
|
124
|
+
const ignoredResults = await Promise.all(probes.map((probe) => git.run(['check-ignore', '--quiet', '--no-index', probe], {
|
|
125
|
+
cwd: repoRoot,
|
|
126
|
+
allowFailure: true,
|
|
127
|
+
})));
|
|
128
|
+
if (ignoredResults.every((result) => result.code === 0) &&
|
|
129
|
+
customRulesManaged) {
|
|
130
|
+
return { changed: false, before: undefined };
|
|
131
|
+
}
|
|
132
|
+
const failedProbe = ignoredResults.find((result) => result.code !== 0 && result.code !== 1);
|
|
133
|
+
if (failedProbe) {
|
|
134
|
+
throw new CliError(`git check-ignore failed (exit ${failedProbe.code}): ${failedProbe.stderr || failedProbe.stdout || 'unknown Git error'}`, 2);
|
|
135
|
+
}
|
|
136
|
+
if (dirtyMessage !== null) {
|
|
137
|
+
const gitignoreStatus = await git.run(['status', '--porcelain=v1', '--', '.gitignore'], { cwd: repoRoot });
|
|
138
|
+
if (gitignoreStatus.stdout !== '')
|
|
139
|
+
throw new CliError(dirtyMessage, 1);
|
|
140
|
+
}
|
|
141
|
+
const before = await readOptionalFile(gitignorePath);
|
|
142
|
+
if (before !== null && customRules.length > 0) {
|
|
143
|
+
const cleaned = customRules.reduce(removeUnmanagedRule, before);
|
|
144
|
+
if (cleaned !== before)
|
|
145
|
+
await writeFile(gitignorePath, cleaned, 'utf8');
|
|
146
|
+
}
|
|
147
|
+
await applyOatCoreGitignore(repoRoot, customRules);
|
|
148
|
+
const verifiedResults = await Promise.all(probes.map((probe) => git.run(['check-ignore', '--quiet', '--no-index', probe], {
|
|
149
|
+
cwd: repoRoot,
|
|
150
|
+
allowFailure: true,
|
|
151
|
+
})));
|
|
152
|
+
const unverified = verifiedResults.find((result) => result.code !== 0);
|
|
153
|
+
if (unverified) {
|
|
154
|
+
if (before === null) {
|
|
155
|
+
await rm(gitignorePath, { force: true });
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
await writeFile(gitignorePath, before, 'utf8');
|
|
159
|
+
}
|
|
160
|
+
throw new CliError(`git check-ignore failed after applying the managed block (exit ${unverified.code}): ${unverified.stderr || unverified.stdout || 'configured rule did not match'}`, 2);
|
|
161
|
+
}
|
|
162
|
+
return {
|
|
163
|
+
before,
|
|
164
|
+
changed: (await readOptionalFile(gitignorePath)) !== before,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
62
167
|
/**
|
|
63
168
|
* Removes the generated repo dashboard from the git index once the OAT core
|
|
64
169
|
* ignore rule is present, while leaving the working-tree file intact.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type CommandContext, type GlobalOptions } from '../../app/command-context.js';
|
|
2
|
+
import { type ApplyOatCoreGitattributesResult } from '../init/gitattributes.js';
|
|
2
3
|
import { type ApplyOatCoreResult } from '../init/gitignore.js';
|
|
3
4
|
import { type NativeSkillDisposition } from '../shared/native-skill-disposition.js';
|
|
4
5
|
import { type MultiSelectChoice, type PromptContext, type SelectChoice } from '../shared/shared.prompts.js';
|
|
@@ -47,6 +48,7 @@ interface InitDependencies {
|
|
|
47
48
|
saveSyncConfig: (configPath: string, config: SyncConfig) => Promise<SyncConfig>;
|
|
48
49
|
getConfigAwareAdapters: (adapters: ProviderAdapter[], scopeRoot: string, config: SyncConfig) => Promise<ConfigAwareAdaptersResult>;
|
|
49
50
|
applyOatCoreGitignore: (repoRoot: string) => Promise<ApplyOatCoreResult>;
|
|
51
|
+
applyOatCoreGitattributes: (repoRoot: string) => Promise<ApplyOatCoreGitattributesResult>;
|
|
50
52
|
dirExists: (dirPath: string) => Promise<boolean>;
|
|
51
53
|
readOatConfig: (repoRoot: string) => Promise<OatConfig>;
|
|
52
54
|
resolveLocalPaths: (config: OatConfig) => string[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/init/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/init/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,6 +2,7 @@ import { execSync } from 'node:child_process';
|
|
|
2
2
|
import { mkdir } from 'node:fs/promises';
|
|
3
3
|
import { basename, isAbsolute, join, relative, resolve, sep } from 'node:path';
|
|
4
4
|
import { buildCommandContext, } from '../../app/command-context.js';
|
|
5
|
+
import { applyOatCoreGitattributes, } from '../init/gitattributes.js';
|
|
5
6
|
import { applyOatCoreGitignore, } from '../init/gitignore.js';
|
|
6
7
|
import { applyGitignore } from '../local/apply.js';
|
|
7
8
|
import { addLocalPaths } from '../local/manage.js';
|
|
@@ -165,6 +166,7 @@ function createDependencies() {
|
|
|
165
166
|
saveSyncConfig,
|
|
166
167
|
getConfigAwareAdapters,
|
|
167
168
|
applyOatCoreGitignore,
|
|
169
|
+
applyOatCoreGitattributes,
|
|
168
170
|
dirExists,
|
|
169
171
|
readOatConfig,
|
|
170
172
|
resolveLocalPaths,
|
|
@@ -506,6 +508,7 @@ async function runInitCommand(context, dependencies, hookFlag, setupFlag) {
|
|
|
506
508
|
await dependencies.ensureCanonicalDirs(scopeRoot, scope);
|
|
507
509
|
if (scope === 'project') {
|
|
508
510
|
await dependencies.applyOatCoreGitignore(scopeRoot);
|
|
511
|
+
await dependencies.applyOatCoreGitattributes(scopeRoot);
|
|
509
512
|
}
|
|
510
513
|
const manifestPath = join(scopeRoot, '.oat', 'sync', 'manifest.json');
|
|
511
514
|
let manifest = await dependencies.loadManifest(manifestPath);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface ApplyManagedBlockResult {
|
|
2
|
+
action: 'created' | 'updated' | 'no-change';
|
|
3
|
+
entries: string[];
|
|
4
|
+
}
|
|
5
|
+
export declare function applyManagedBlock(filePath: string, options: {
|
|
6
|
+
start: string;
|
|
7
|
+
end: string;
|
|
8
|
+
entries: string[];
|
|
9
|
+
}): Promise<ApplyManagedBlockResult>;
|
|
10
|
+
//# sourceMappingURL=managed-block.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"managed-block.d.ts","sourceRoot":"","sources":["../../../src/commands/init/managed-block.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,CAAC;IAC5C,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAaD,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,GACzD,OAAO,CAAC,uBAAuB,CAAC,CA8ClC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { readFile, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { fileExists } from '../../fs/io.js';
|
|
3
|
+
function preserveUnmanagedTail(tail, entries) {
|
|
4
|
+
const managedEntries = new Set(entries);
|
|
5
|
+
const lines = tail.startsWith('\n')
|
|
6
|
+
? tail.slice(1).split('\n')
|
|
7
|
+
: tail.split('\n');
|
|
8
|
+
return lines.filter((line) => !managedEntries.has(line)).join('\n');
|
|
9
|
+
}
|
|
10
|
+
export async function applyManagedBlock(filePath, options) {
|
|
11
|
+
const section = `${options.start}\n${options.entries.join('\n')}\n${options.end}`;
|
|
12
|
+
if (!(await fileExists(filePath))) {
|
|
13
|
+
await writeFile(filePath, `${section}\n`, 'utf8');
|
|
14
|
+
return { action: 'created', entries: options.entries };
|
|
15
|
+
}
|
|
16
|
+
const content = await readFile(filePath, 'utf8');
|
|
17
|
+
const startIndex = content.indexOf(options.start);
|
|
18
|
+
const endIndex = content.indexOf(options.end);
|
|
19
|
+
if (startIndex !== -1 && endIndex !== -1 && endIndex >= startIndex) {
|
|
20
|
+
const existing = content.slice(startIndex, endIndex + options.end.length);
|
|
21
|
+
if (existing === section) {
|
|
22
|
+
return { action: 'no-change', entries: options.entries };
|
|
23
|
+
}
|
|
24
|
+
await writeFile(filePath, `${content.slice(0, startIndex)}${section}${content.slice(endIndex + options.end.length)}`, 'utf8');
|
|
25
|
+
return { action: 'updated', entries: options.entries };
|
|
26
|
+
}
|
|
27
|
+
if (startIndex !== -1) {
|
|
28
|
+
const prefix = content.slice(0, startIndex);
|
|
29
|
+
const preservedTail = preserveUnmanagedTail(content.slice(startIndex + options.start.length), options.entries);
|
|
30
|
+
const prefixSeparator = prefix.length === 0 || prefix.endsWith('\n') ? '' : '\n';
|
|
31
|
+
const preservedSuffix = preservedTail.length === 0
|
|
32
|
+
? '\n'
|
|
33
|
+
: `\n${preservedTail.replace(/^\n+/, '')}`;
|
|
34
|
+
await writeFile(filePath, `${prefix}${prefixSeparator}${section}${preservedSuffix}`, 'utf8');
|
|
35
|
+
return { action: 'updated', entries: options.entries };
|
|
36
|
+
}
|
|
37
|
+
const separator = content.endsWith('\n') ? '\n' : '\n\n';
|
|
38
|
+
await writeFile(filePath, `${content}${separator}${section}\n`, 'utf8');
|
|
39
|
+
return { action: 'updated', entries: options.entries };
|
|
40
|
+
}
|
|
@@ -110,7 +110,7 @@ export async function installWorkflows(options) {
|
|
|
110
110
|
if (!config.projects?.root?.trim()) {
|
|
111
111
|
await writeOatConfig(options.targetRoot, {
|
|
112
112
|
...config,
|
|
113
|
-
projects: { root: '.oat/projects/shared' },
|
|
113
|
+
projects: { ...config.projects, root: '.oat/projects/shared' },
|
|
114
114
|
});
|
|
115
115
|
result.projectsRootConfigInitialized = true;
|
|
116
116
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/local/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,wBAAgB,kBAAkB,IAAI,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/local/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,wBAAgB,kBAAkB,IAAI,OAAO,CAwS5C"}
|
|
@@ -144,6 +144,7 @@ export function createLocalCommand() {
|
|
|
144
144
|
}
|
|
145
145
|
const direction = options.from ? 'from' : 'to';
|
|
146
146
|
const result = await syncLocalPaths({
|
|
147
|
+
repoRoot,
|
|
147
148
|
sourceRoot: repoRoot,
|
|
148
149
|
targetRoot: worktreePath,
|
|
149
150
|
localPaths,
|
|
@@ -155,7 +156,10 @@ export function createLocalCommand() {
|
|
|
155
156
|
}
|
|
156
157
|
else {
|
|
157
158
|
for (const entry of result.entries) {
|
|
158
|
-
|
|
159
|
+
const reason = entry.status === 'skipped' && entry.reason
|
|
160
|
+
? ` (${entry.reason})`
|
|
161
|
+
: '';
|
|
162
|
+
context.logger.info(` ${entry.status.padEnd(8)} ${entry.path}${reason}`);
|
|
159
163
|
}
|
|
160
164
|
context.logger.info(`\nSync complete: ${result.copied} copied, ${result.skipped} skipped, ${result.missing} missing`);
|
|
161
165
|
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import { type GitRunner } from '../project/sync/git.js';
|
|
1
2
|
export type SyncStatus = 'copied' | 'skipped' | 'missing';
|
|
2
3
|
export interface SyncEntry {
|
|
3
4
|
path: string;
|
|
4
5
|
status: SyncStatus;
|
|
6
|
+
reason?: 'nested-worktree';
|
|
5
7
|
}
|
|
6
8
|
export interface SyncResult {
|
|
7
9
|
entries: SyncEntry[];
|
|
@@ -10,11 +12,13 @@ export interface SyncResult {
|
|
|
10
12
|
missing: number;
|
|
11
13
|
}
|
|
12
14
|
export interface SyncOptions {
|
|
15
|
+
repoRoot?: string;
|
|
13
16
|
sourceRoot: string;
|
|
14
17
|
targetRoot: string;
|
|
15
18
|
localPaths: string[];
|
|
16
19
|
direction: 'to' | 'from';
|
|
17
20
|
force: boolean;
|
|
21
|
+
gitRunner?: GitRunner;
|
|
18
22
|
}
|
|
19
23
|
export declare function syncLocalPaths(options: SyncOptions): Promise<SyncResult>;
|
|
20
24
|
//# sourceMappingURL=sync.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../../src/commands/local/sync.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../../src/commands/local/sync.ts"],"names":[],"mappings":"AAGA,OAAO,EAAoB,KAAK,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAM9E,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;AAE1D,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,CAAC;IACnB,MAAM,CAAC,EAAE,iBAAiB,CAAC;CAC5B;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,EAAE,IAAI,GAAG,MAAM,CAAC;IACzB,KAAK,EAAE,OAAO,CAAC;IACf,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAuID,wBAAsB,cAAc,CAClC,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,CAAC,CAoFrB"}
|
|
@@ -1,13 +1,116 @@
|
|
|
1
|
-
import { rm } from 'node:fs/promises';
|
|
2
|
-
import { join } from 'node:path';
|
|
1
|
+
import { lstat, readdir, realpath, rm } from 'node:fs/promises';
|
|
2
|
+
import { dirname, isAbsolute, join, relative, resolve, sep } from 'node:path';
|
|
3
|
+
import { defaultGitRunner } from '../project/sync/git.js';
|
|
4
|
+
import { CliError } from '../../errors/cli-error.js';
|
|
3
5
|
import { copyDirectory, dirExists, fileExists } from '../../fs/io.js';
|
|
4
6
|
import { expandLocalPaths } from './expand.js';
|
|
7
|
+
async function canonicalizeLocalSyncPath(path) {
|
|
8
|
+
const absolute = resolve(path);
|
|
9
|
+
try {
|
|
10
|
+
return await realpath(absolute);
|
|
11
|
+
}
|
|
12
|
+
catch (error) {
|
|
13
|
+
if (!(error instanceof Error && 'code' in error && error.code === 'ENOENT')) {
|
|
14
|
+
throw error;
|
|
15
|
+
}
|
|
16
|
+
const parent = dirname(absolute);
|
|
17
|
+
if (parent === absolute)
|
|
18
|
+
return absolute;
|
|
19
|
+
return join(await canonicalizeLocalSyncPath(parent), relative(parent, absolute));
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function pathsOverlap(left, right) {
|
|
23
|
+
const leftToRight = relative(left, right);
|
|
24
|
+
const rightToLeft = relative(right, left);
|
|
25
|
+
const isWithin = (candidate) => candidate === '' ||
|
|
26
|
+
(candidate !== '..' &&
|
|
27
|
+
!candidate.startsWith(`..${sep}`) &&
|
|
28
|
+
!isAbsolute(candidate));
|
|
29
|
+
return isWithin(leftToRight) || isWithin(rightToLeft);
|
|
30
|
+
}
|
|
31
|
+
function worktreeOwnsRoot(worktreePath, rootPath) {
|
|
32
|
+
const relativeRoot = relative(worktreePath, rootPath);
|
|
33
|
+
return (relativeRoot === '' ||
|
|
34
|
+
(relativeRoot !== '..' &&
|
|
35
|
+
!relativeRoot.startsWith(`..${sep}`) &&
|
|
36
|
+
!isAbsolute(relativeRoot)));
|
|
37
|
+
}
|
|
38
|
+
async function registeredNestedWorktrees(repoRoot, sourceRoot, targetRoot, git) {
|
|
39
|
+
const result = await git.run(['worktree', 'list', '--porcelain'], {
|
|
40
|
+
cwd: repoRoot,
|
|
41
|
+
allowFailure: true,
|
|
42
|
+
});
|
|
43
|
+
if (result.code !== 0) {
|
|
44
|
+
throw new CliError(`Unable to inspect registered worktrees before local sync: ${result.stderr || result.stdout || `git worktree list failed with exit ${result.code}`}`, 2);
|
|
45
|
+
}
|
|
46
|
+
const records = result.stdout ? result.stdout.split(/\n\n+/) : [];
|
|
47
|
+
const registered = [];
|
|
48
|
+
for (const record of records) {
|
|
49
|
+
const lines = record.split('\n').filter(Boolean);
|
|
50
|
+
const worktreeLines = lines.filter((line) => line.startsWith('worktree '));
|
|
51
|
+
const worktreeLine = worktreeLines[0];
|
|
52
|
+
if (lines.length === 0 ||
|
|
53
|
+
worktreeLines.length !== 1 ||
|
|
54
|
+
typeof worktreeLine !== 'string' ||
|
|
55
|
+
!worktreeLine.startsWith('worktree ') ||
|
|
56
|
+
lines[0] !== worktreeLine ||
|
|
57
|
+
worktreeLine.slice('worktree '.length).trim() === '') {
|
|
58
|
+
throw new CliError('Malformed `git worktree list --porcelain` output; refusing local sync.', 2);
|
|
59
|
+
}
|
|
60
|
+
registered.push(await canonicalizeLocalSyncPath(worktreeLine.slice('worktree '.length)));
|
|
61
|
+
}
|
|
62
|
+
if (registered.length === 0) {
|
|
63
|
+
throw new CliError('Git returned no registered worktrees; refusing repository-aware local sync.', 2);
|
|
64
|
+
}
|
|
65
|
+
const supportedRoots = await Promise.all([
|
|
66
|
+
canonicalizeLocalSyncPath(sourceRoot),
|
|
67
|
+
canonicalizeLocalSyncPath(targetRoot),
|
|
68
|
+
]);
|
|
69
|
+
return [...new Set(registered)].filter((worktreePath) => !supportedRoots.some((rootPath) => worktreeOwnsRoot(worktreePath, rootPath)));
|
|
70
|
+
}
|
|
71
|
+
async function containsNestedGitMarker(root) {
|
|
72
|
+
let entries;
|
|
73
|
+
try {
|
|
74
|
+
entries = await readdir(root, { withFileTypes: true });
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
if (error instanceof Error &&
|
|
78
|
+
'code' in error &&
|
|
79
|
+
(error.code === 'ENOENT' || error.code === 'ENOTDIR')) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
throw error;
|
|
83
|
+
}
|
|
84
|
+
for (const entry of entries) {
|
|
85
|
+
if (entry.name === '.git')
|
|
86
|
+
return true;
|
|
87
|
+
const entryPath = join(root, entry.name);
|
|
88
|
+
if (entry.isSymbolicLink()) {
|
|
89
|
+
// Local sync does not follow directory symlinks while looking for a
|
|
90
|
+
// worktree boundary. A symlink target is copied as a link by the I/O
|
|
91
|
+
// layer and cannot authorize recursive deletion of its destination.
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
if (entry.isDirectory() && (await containsNestedGitMarker(entryPath))) {
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
if (!entry.isDirectory() && !entry.isFile()) {
|
|
98
|
+
// Force filesystem errors to surface instead of silently treating an
|
|
99
|
+
// unfamiliar entry as safe.
|
|
100
|
+
await lstat(entryPath);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
5
105
|
export async function syncLocalPaths(options) {
|
|
6
106
|
const { sourceRoot, targetRoot, localPaths, direction, force } = options;
|
|
7
107
|
// Determine actual from/to based on direction
|
|
8
108
|
const fromRoot = direction === 'to' ? sourceRoot : targetRoot;
|
|
9
109
|
const toRoot = direction === 'to' ? targetRoot : sourceRoot;
|
|
10
110
|
const entries = [];
|
|
111
|
+
const registered = options.repoRoot
|
|
112
|
+
? await registeredNestedWorktrees(options.repoRoot, sourceRoot, targetRoot, options.gitRunner ?? defaultGitRunner)
|
|
113
|
+
: [];
|
|
11
114
|
const { resolved, missingGlobs } = await expandLocalPaths(fromRoot, localPaths);
|
|
12
115
|
for (const pattern of missingGlobs) {
|
|
13
116
|
entries.push({ path: pattern, status: 'missing' });
|
|
@@ -20,6 +123,24 @@ export async function syncLocalPaths(options) {
|
|
|
20
123
|
entries.push({ path: localPath, status: 'missing' });
|
|
21
124
|
continue;
|
|
22
125
|
}
|
|
126
|
+
// This check must cover the whole selected entry on both sides and must
|
|
127
|
+
// happen before force-removal. A localPath may be an ancestor of a linked
|
|
128
|
+
// worktree, so checking only `<entry>/.git` is insufficient.
|
|
129
|
+
const [canonicalSourcePath, canonicalDestPath] = await Promise.all([
|
|
130
|
+
canonicalizeLocalSyncPath(sourcePath),
|
|
131
|
+
canonicalizeLocalSyncPath(destPath),
|
|
132
|
+
]);
|
|
133
|
+
if (registered.some((worktreePath) => pathsOverlap(canonicalSourcePath, worktreePath) ||
|
|
134
|
+
pathsOverlap(canonicalDestPath, worktreePath)) ||
|
|
135
|
+
(await containsNestedGitMarker(sourcePath)) ||
|
|
136
|
+
(await containsNestedGitMarker(destPath))) {
|
|
137
|
+
entries.push({
|
|
138
|
+
path: localPath,
|
|
139
|
+
status: 'skipped',
|
|
140
|
+
reason: 'nested-worktree',
|
|
141
|
+
});
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
23
144
|
const destExists = (await dirExists(destPath)) || (await fileExists(destPath));
|
|
24
145
|
if (destExists && !force) {
|
|
25
146
|
entries.push({ path: localPath, status: 'skipped' });
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type OatConfig } from '../../config/oat-config.js';
|
|
1
2
|
export type PjmAdoptionState = 'declared' | 'inferred-legacy' | 'partial-initialization' | 'none';
|
|
2
3
|
export interface PjmAdoption {
|
|
3
4
|
state: PjmAdoptionState;
|
|
@@ -7,6 +8,7 @@ export interface PjmAdoption {
|
|
|
7
8
|
export interface ResolvePjmAdoptionOptions {
|
|
8
9
|
projectRoot: string;
|
|
9
10
|
repoRoot: string;
|
|
11
|
+
config?: OatConfig;
|
|
10
12
|
}
|
|
11
13
|
export declare function resolvePjmAdoption(options: ResolvePjmAdoptionOptions): Promise<PjmAdoption>;
|
|
12
14
|
//# sourceMappingURL=adoption.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adoption.d.ts","sourceRoot":"","sources":["../../../src/commands/pjm/adoption.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"adoption.d.ts","sourceRoot":"","sources":["../../../src/commands/pjm/adoption.ts"],"names":[],"mappings":"AAGA,OAAO,EAAiB,KAAK,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAInE,MAAM,MAAM,gBAAgB,GACxB,UAAU,GACV,iBAAiB,GACjB,wBAAwB,GACxB,MAAM,CAAC;AAEX,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,gBAAgB,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,cAAc,GAAG,IAAI,CAAC;CACjC;AAED,MAAM,WAAW,yBAAyB;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,SAAS,CAAC;CACpB;AAmBD,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,WAAW,CAAC,CA8BtB"}
|
|
@@ -18,7 +18,7 @@ async function pathExists(path) {
|
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
export async function resolvePjmAdoption(options) {
|
|
21
|
-
const config = await readOatConfig(options.projectRoot);
|
|
21
|
+
const config = options.config ?? (await readOatConfig(options.projectRoot));
|
|
22
22
|
if (config.pjm?.initialized === true) {
|
|
23
23
|
return {
|
|
24
24
|
state: 'declared',
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import { rename } from 'node:fs/promises';
|
|
2
|
+
import { type GitRunner } from '../../project/sync/git.js';
|
|
3
|
+
import { readSyncedRecord, writeSyncedRecord } from '../../project/sync/record.js';
|
|
4
|
+
import { commitRecordChange, preflightSyncedCheckout, removeSyncedCheckout } from '../../project/sync/ref-sync.js';
|
|
5
|
+
import { type ProjectScope } from '../../shared/project-scope.js';
|
|
2
6
|
import { copyDirectory, copySingleFile, dirExists, ensureDir, fileExists } from '../../../fs/io.js';
|
|
3
7
|
export type ExecFileResult = {
|
|
4
8
|
stdout: string;
|
|
@@ -56,6 +60,7 @@ export interface ArchiveProjectOnCompletionOptions {
|
|
|
56
60
|
* semantics as `awsProfile`.
|
|
57
61
|
*/
|
|
58
62
|
awsRegion?: string | null;
|
|
63
|
+
commit?: boolean;
|
|
59
64
|
}
|
|
60
65
|
export interface ResolvePrimaryRepoRootDependencies {
|
|
61
66
|
gitExecFile?: ExecFileLike;
|
|
@@ -66,6 +71,8 @@ export interface ResolveArchiveProjectTargetOptions {
|
|
|
66
71
|
repoRoot: string;
|
|
67
72
|
projectsRoot: string;
|
|
68
73
|
projectName: string;
|
|
74
|
+
archiveSnapshot?: string;
|
|
75
|
+
archiveScope?: ProjectScope;
|
|
69
76
|
}
|
|
70
77
|
export interface ResolveArchiveProjectTargetDependencies extends ResolvePrimaryRepoRootDependencies {
|
|
71
78
|
timestamp?: () => string;
|
|
@@ -92,6 +99,12 @@ interface ArchiveProjectOnCompletionDependencies extends EnsureS3ArchiveAccessDe
|
|
|
92
99
|
fileExists?: typeof fileExists;
|
|
93
100
|
renamePath?: typeof rename;
|
|
94
101
|
timestamp?: () => string;
|
|
102
|
+
gitRunner?: GitRunner;
|
|
103
|
+
readSyncedRecord?: typeof readSyncedRecord;
|
|
104
|
+
writeSyncedRecord?: typeof writeSyncedRecord;
|
|
105
|
+
preflightSyncedCheckout?: typeof preflightSyncedCheckout;
|
|
106
|
+
removeSyncedCheckout?: typeof removeSyncedCheckout;
|
|
107
|
+
commitRecordChange?: typeof commitRecordChange;
|
|
95
108
|
}
|
|
96
109
|
export interface ArchiveProjectRecapExportV1 {
|
|
97
110
|
sourceRunRoot: string;
|
|
@@ -104,9 +117,13 @@ export interface ArchiveProjectRecapExportV1 {
|
|
|
104
117
|
export interface ArchiveProjectOnCompletionResult {
|
|
105
118
|
archivePath: string;
|
|
106
119
|
s3Path: string | null;
|
|
120
|
+
/** Absolute filesystem path; normalize only when rendering repository links. */
|
|
107
121
|
summaryExportFile: string | null;
|
|
108
122
|
projectRecapExport: ArchiveProjectRecapExportV1 | null;
|
|
109
123
|
warnings: string[];
|
|
124
|
+
lifecycleCommit: string | null;
|
|
125
|
+
recapExportPaths: string[];
|
|
126
|
+
snapshotId: string;
|
|
110
127
|
}
|
|
111
128
|
export declare const ARCHIVE_SNAPSHOT_METADATA_FILENAME = ".oat-archive-source.json";
|
|
112
129
|
/**
|
|
@@ -117,7 +134,14 @@ export declare const S3_ARCHIVE_SYNC_EXCLUDES: string[];
|
|
|
117
134
|
export interface ArchiveSnapshotMetadata {
|
|
118
135
|
projectName: string;
|
|
119
136
|
snapshotName: string;
|
|
137
|
+
scope: ProjectScope;
|
|
138
|
+
sourceRefSha?: string;
|
|
120
139
|
}
|
|
140
|
+
export interface ExactArchiveProjectRoot {
|
|
141
|
+
canonicalProjectPath: string;
|
|
142
|
+
projectScope: ProjectScope;
|
|
143
|
+
}
|
|
144
|
+
export declare function assertExactArchiveProjectRoot(options: Pick<ArchiveProjectOnCompletionOptions, 'repoRoot' | 'projectsRoot' | 'projectPath' | 'projectName'>): ExactArchiveProjectRoot;
|
|
121
145
|
/**
|
|
122
146
|
* Build the env passed to every `aws` spawn in this module.
|
|
123
147
|
*
|