accrete-kit 0.0.0-stage → 0.1.1
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/CHANGELOG.md +48 -0
- package/LICENSE +21 -0
- package/README.md +148 -2
- package/bin/accrete-kit.mjs +4 -0
- package/dist/kernel/darwin-arm64/LICENSE +21 -0
- package/dist/kernel/darwin-arm64/THIRD-PARTY-NOTICES +5780 -0
- package/dist/kernel/darwin-arm64/accrete +0 -0
- package/dist/kernel/darwin-arm64/licenses/RUST-COPYRIGHT-library.html +7038 -0
- package/dist/kernel/darwin-arm64/licenses/musl-COPYRIGHT +193 -0
- package/dist/kernel/darwin-arm64/licenses/rust/Apache-2.0.txt +73 -0
- package/dist/kernel/darwin-arm64/licenses/rust/BSD-2-Clause.txt +9 -0
- package/dist/kernel/darwin-arm64/licenses/rust/CC-BY-SA-4.0.txt +427 -0
- package/dist/kernel/darwin-arm64/licenses/rust/GCC-exception-3.1.txt +30 -0
- package/dist/kernel/darwin-arm64/licenses/rust/GPL-2.0-only.txt +133 -0
- package/dist/kernel/darwin-arm64/licenses/rust/GPL-3.0-or-later.txt +202 -0
- package/dist/kernel/darwin-arm64/licenses/rust/ISC.txt +7 -0
- package/dist/kernel/darwin-arm64/licenses/rust/LLVM-exception.txt +15 -0
- package/dist/kernel/darwin-arm64/licenses/rust/MIT.txt +9 -0
- package/dist/kernel/darwin-arm64/licenses/rust/NCSA.txt +29 -0
- package/dist/kernel/darwin-arm64/licenses/rust/OFL-1.1.txt +43 -0
- package/dist/kernel/darwin-arm64/licenses/rust/Unicode-3.0.txt +39 -0
- package/dist/kernel/darwin-x64/LICENSE +21 -0
- package/dist/kernel/darwin-x64/THIRD-PARTY-NOTICES +5780 -0
- package/dist/kernel/darwin-x64/accrete +0 -0
- package/dist/kernel/darwin-x64/licenses/RUST-COPYRIGHT-library.html +7038 -0
- package/dist/kernel/darwin-x64/licenses/musl-COPYRIGHT +193 -0
- package/dist/kernel/darwin-x64/licenses/rust/Apache-2.0.txt +73 -0
- package/dist/kernel/darwin-x64/licenses/rust/BSD-2-Clause.txt +9 -0
- package/dist/kernel/darwin-x64/licenses/rust/CC-BY-SA-4.0.txt +427 -0
- package/dist/kernel/darwin-x64/licenses/rust/GCC-exception-3.1.txt +30 -0
- package/dist/kernel/darwin-x64/licenses/rust/GPL-2.0-only.txt +133 -0
- package/dist/kernel/darwin-x64/licenses/rust/GPL-3.0-or-later.txt +202 -0
- package/dist/kernel/darwin-x64/licenses/rust/ISC.txt +7 -0
- package/dist/kernel/darwin-x64/licenses/rust/LLVM-exception.txt +15 -0
- package/dist/kernel/darwin-x64/licenses/rust/MIT.txt +9 -0
- package/dist/kernel/darwin-x64/licenses/rust/NCSA.txt +29 -0
- package/dist/kernel/darwin-x64/licenses/rust/OFL-1.1.txt +43 -0
- package/dist/kernel/darwin-x64/licenses/rust/Unicode-3.0.txt +39 -0
- package/dist/kernel/kernel.json +17 -0
- package/dist/kernel/linux-arm64/LICENSE +21 -0
- package/dist/kernel/linux-arm64/THIRD-PARTY-NOTICES +5780 -0
- package/dist/kernel/linux-arm64/accrete +0 -0
- package/dist/kernel/linux-arm64/licenses/RUST-COPYRIGHT-library.html +7038 -0
- package/dist/kernel/linux-arm64/licenses/musl-COPYRIGHT +193 -0
- package/dist/kernel/linux-arm64/licenses/rust/Apache-2.0.txt +73 -0
- package/dist/kernel/linux-arm64/licenses/rust/BSD-2-Clause.txt +9 -0
- package/dist/kernel/linux-arm64/licenses/rust/CC-BY-SA-4.0.txt +427 -0
- package/dist/kernel/linux-arm64/licenses/rust/GCC-exception-3.1.txt +30 -0
- package/dist/kernel/linux-arm64/licenses/rust/GPL-2.0-only.txt +133 -0
- package/dist/kernel/linux-arm64/licenses/rust/GPL-3.0-or-later.txt +202 -0
- package/dist/kernel/linux-arm64/licenses/rust/ISC.txt +7 -0
- package/dist/kernel/linux-arm64/licenses/rust/LLVM-exception.txt +15 -0
- package/dist/kernel/linux-arm64/licenses/rust/MIT.txt +9 -0
- package/dist/kernel/linux-arm64/licenses/rust/NCSA.txt +29 -0
- package/dist/kernel/linux-arm64/licenses/rust/OFL-1.1.txt +43 -0
- package/dist/kernel/linux-arm64/licenses/rust/Unicode-3.0.txt +39 -0
- package/dist/kernel/linux-x64/LICENSE +21 -0
- package/dist/kernel/linux-x64/THIRD-PARTY-NOTICES +5780 -0
- package/dist/kernel/linux-x64/accrete +0 -0
- package/dist/kernel/linux-x64/licenses/RUST-COPYRIGHT-library.html +7038 -0
- package/dist/kernel/linux-x64/licenses/musl-COPYRIGHT +193 -0
- package/dist/kernel/linux-x64/licenses/rust/Apache-2.0.txt +73 -0
- package/dist/kernel/linux-x64/licenses/rust/BSD-2-Clause.txt +9 -0
- package/dist/kernel/linux-x64/licenses/rust/CC-BY-SA-4.0.txt +427 -0
- package/dist/kernel/linux-x64/licenses/rust/GCC-exception-3.1.txt +30 -0
- package/dist/kernel/linux-x64/licenses/rust/GPL-2.0-only.txt +133 -0
- package/dist/kernel/linux-x64/licenses/rust/GPL-3.0-or-later.txt +202 -0
- package/dist/kernel/linux-x64/licenses/rust/ISC.txt +7 -0
- package/dist/kernel/linux-x64/licenses/rust/LLVM-exception.txt +15 -0
- package/dist/kernel/linux-x64/licenses/rust/MIT.txt +9 -0
- package/dist/kernel/linux-x64/licenses/rust/NCSA.txt +29 -0
- package/dist/kernel/linux-x64/licenses/rust/OFL-1.1.txt +43 -0
- package/dist/kernel/linux-x64/licenses/rust/Unicode-3.0.txt +39 -0
- package/dist/scaffold/assets/contract/cli-v1.json +296 -0
- package/dist/scaffold/assets/contract/example-inputs.json +38 -0
- package/dist/scaffold/assets/contract/input-drafts.schema.json +654 -0
- package/dist/scaffold/assets/generated/cli-commands.md +288 -0
- package/dist/scaffold/assets/generated/release.json +11 -0
- package/dist/scaffold/assets/skills/accrete-data/SKILL.md +73 -0
- package/dist/scaffold/assets/skills/accrete-data/references/commands.md +193 -0
- package/dist/scaffold/assets/skills/accrete-data/references/objects-and-native-work.md +123 -0
- package/dist/scaffold/assets/skills/accrete-data/references/remote-and-retention.md +98 -0
- package/dist/scaffold/assets/skills/accrete-memory/SKILL.md +61 -0
- package/dist/scaffold/assets/skills/accrete-memory/references/commands.md +124 -0
- package/dist/scaffold/assets/skills/accrete-memory/references/handovers-and-remote-work.md +78 -0
- package/dist/scaffold/assets/skills/accrete-memory/references/writing-and-continuity.md +101 -0
- package/dist/scaffold/assets/skills/accrete-models/SKILL.md +46 -0
- package/dist/scaffold/assets/skills/accrete-models/references/cli.md +117 -0
- package/dist/scaffold/assets/skills/accrete-models/references/objects.md +67 -0
- package/dist/scaffold/assets/skills/accrete-models/references/working-practice.md +48 -0
- package/dist/scaffold/assets/skills/accrete-results/SKILL.md +69 -0
- package/dist/scaffold/assets/skills/accrete-results/references/activities-and-relations.md +116 -0
- package/dist/scaffold/assets/skills/accrete-results/references/commands.md +191 -0
- package/dist/scaffold/assets/skills/accrete-results/references/scientific-practice.md +89 -0
- package/dist/scaffold/assets/skills/accrete-tools/SKILL.md +51 -0
- package/dist/scaffold/assets/skills/accrete-tools/references/cli.md +87 -0
- package/dist/scaffold/assets/skills/accrete-tools/references/objects.md +66 -0
- package/dist/scaffold/assets/skills/accrete-tools/references/working-practice.md +51 -0
- package/dist/scaffold/assets/template/.accrete/PROJECT.md +31 -0
- package/dist/scaffold/assets/template/.accrete/config-examples/local-compute.toml.example +27 -0
- package/dist/scaffold/assets/template/.accrete/config-examples/local-workstation.toml.example +21 -0
- package/dist/scaffold/assets/template/.accrete/config-examples/project.toml.example +27 -0
- package/dist/scaffold/assets/template/.accrete/docs/cli-contract.md +393 -0
- package/dist/scaffold/assets/template/.accrete/docs/configuration.md +117 -0
- package/dist/scaffold/assets/template/.accrete/docs/coordinator.md +102 -0
- package/dist/scaffold/assets/template/.accrete/docs/long-term-work.md +108 -0
- package/dist/scaffold/assets/template/.accrete/docs/overview.md +118 -0
- package/dist/scaffold/assets/template/.accrete/docs/remote-work.md +125 -0
- package/dist/scaffold/assets/template/.accrete/docs/subagents.md +78 -0
- package/dist/scaffold/assets/template/.accrete/examples/README.md +78 -0
- package/dist/scaffold/assets/template/.accrete/examples/data-register.json +19 -0
- package/dist/scaffold/assets/template/.accrete/examples/iteration-close.json +5 -0
- package/dist/scaffold/assets/template/.accrete/examples/iteration-open.json +8 -0
- package/dist/scaffold/assets/template/.accrete/examples/memory-entry.md +10 -0
- package/dist/scaffold/assets/template/.accrete/examples/model-register.json +7 -0
- package/dist/scaffold/assets/template/.accrete/examples/observation.md +9 -0
- package/dist/scaffold/assets/template/.accrete/examples/result-amend.json +5 -0
- package/dist/scaffold/assets/template/.accrete/examples/result-record.json +11 -0
- package/dist/scaffold/assets/template/.accrete/examples/tool-admit.json +8 -0
- package/dist/scaffold/assets/template/.accrete/examples/tool-retire.json +3 -0
- package/dist/scaffold/assets/template/.accrete/examples/tool-update.json +3 -0
- package/dist/scaffold/assets/template/.gitattributes +17 -0
- package/dist/scaffold/assets/template/AGENTS.md +23 -0
- package/dist/scaffold/assets/template/CLAUDE.md +5 -0
- package/dist/scaffold/assets/template/_gitignore +12 -0
- package/dist/scaffold/config/defaults.toml +20 -0
- package/dist/scaffold/manifest.json +622 -0
- package/lib/cli.mjs +188 -0
- package/lib/fsutil.mjs +135 -0
- package/lib/install.mjs +439 -0
- package/lib/kernel.mjs +76 -0
- package/lib/scaffold.mjs +129 -0
- package/lib/workspace.mjs +278 -0
- package/package.json +18 -4
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
// A Workspace on disk: its marker, where it is found, and how one is created.
|
|
2
|
+
import { randomUUID } from 'node:crypto';
|
|
3
|
+
import { spawnSync } from 'node:child_process';
|
|
4
|
+
import fs from 'node:fs';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { AccreteError, atomicWrite, refuseSymlinks } from './fsutil.mjs';
|
|
7
|
+
import { accept, publisher, readInventory, reconcile } from './install.mjs';
|
|
8
|
+
import { BINARY, compareVersions, hostPlatform, installKernel, numericVersion } from './kernel.mjs';
|
|
9
|
+
import { MARKER, parseAgents } from './scaffold.mjs';
|
|
10
|
+
|
|
11
|
+
/** The scalar keys of a TOML document by table. The rest of it is not our concern. */
|
|
12
|
+
function readSimpleToml(text) {
|
|
13
|
+
const tables = { '': {} };
|
|
14
|
+
let table = tables[''];
|
|
15
|
+
for (const line of text.split(/\r?\n/)) {
|
|
16
|
+
const header = line.match(/^\s*\[([^\[\]]+)\]\s*(?:#.*)?$/);
|
|
17
|
+
if (header) {
|
|
18
|
+
table = tables[header[1].trim()] ??= {};
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
const pair = line.match(/^\s*([A-Za-z0-9_-]+)\s*=\s*("(?:[^"\\]|\\.)*"|'[^']*'|[+-]?\d+)\s*(?:#.*)?$/);
|
|
22
|
+
if (!pair) continue;
|
|
23
|
+
const value = pair[2];
|
|
24
|
+
if (value.startsWith('"')) {
|
|
25
|
+
try {
|
|
26
|
+
table[pair[1]] = JSON.parse(value);
|
|
27
|
+
} catch {
|
|
28
|
+
table[pair[1]] = value.slice(1, -1);
|
|
29
|
+
}
|
|
30
|
+
} else {
|
|
31
|
+
table[pair[1]] = value.startsWith("'") ? value.slice(1, -1) : Number(value);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return tables;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function readMarker(root) {
|
|
38
|
+
refuseSymlinks(root, MARKER);
|
|
39
|
+
const tables = readSimpleToml(fs.readFileSync(path.join(root, MARKER), 'utf8'));
|
|
40
|
+
const { format, project_id: projectId, name, timezone } = tables[''];
|
|
41
|
+
if (!Number.isInteger(format) || typeof projectId !== 'string') {
|
|
42
|
+
throw new AccreteError('config', `${path.join(root, MARKER)} lacks format or project_id`);
|
|
43
|
+
}
|
|
44
|
+
return { format, project_id: projectId, name, timezone, paths: tables.paths ?? {} };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function checkFormat(scaffold, format) {
|
|
48
|
+
const { min, max } = scaffold.project_formats;
|
|
49
|
+
if (format < min || format > max) {
|
|
50
|
+
throw new AccreteError('unsupported_format', `This template supports project format ${min === max ? min : `${min} to ${max}`}, not ${format}`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** The defaults' text with the identity inserted after its `format` line. */
|
|
55
|
+
export function markerText(scaffold, { projectId, name, timezone }) {
|
|
56
|
+
const tomlString = value => JSON.stringify(value).replaceAll('\u007f', '\\u007f');
|
|
57
|
+
const identity = [`project_id = ${tomlString(projectId)}`, `name = ${tomlString(name)}`];
|
|
58
|
+
const lines = [];
|
|
59
|
+
for (const line of scaffold.defaults.split('\n')) {
|
|
60
|
+
if (/^\s*#/.test(line)) continue;
|
|
61
|
+
if (/^timezone\s*=/.test(line)) continue;
|
|
62
|
+
lines.push(line);
|
|
63
|
+
if (/^format\s*=/.test(line)) lines.push(...identity, `timezone = ${tomlString(timezone)}`);
|
|
64
|
+
}
|
|
65
|
+
return `${lines.join('\n').trim()}\n`;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function checkId(id) {
|
|
69
|
+
if (!/^[A-Za-z0-9._-]{1,180}$/.test(id) || id === '.' || id === '..') {
|
|
70
|
+
throw new AccreteError('invalid', "IDs must be 1-180 ASCII letters, digits, '.', '_' or '-' and cannot be '.' or '..'");
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function checkTimezone(zone) {
|
|
75
|
+
let resolved = null;
|
|
76
|
+
if (/^[A-Za-z]/.test(zone)) {
|
|
77
|
+
try {
|
|
78
|
+
resolved = new Intl.DateTimeFormat('en-US', { timeZone: zone }).resolvedOptions().timeZone;
|
|
79
|
+
} catch {
|
|
80
|
+
resolved = null;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// ICU folds case; the Kernel reads the exact IANA spelling.
|
|
84
|
+
if (!resolved || (resolved !== zone && resolved.toLowerCase() === zone.toLowerCase())) {
|
|
85
|
+
throw new AccreteError('invalid', `Unknown IANA timezone ${zone}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** The real path of the deepest existing ancestor, plus the rest. */
|
|
90
|
+
function canonicalFuture(target) {
|
|
91
|
+
const absolute = path.resolve(target);
|
|
92
|
+
const rest = [];
|
|
93
|
+
let current = absolute;
|
|
94
|
+
while (!fs.existsSync(current)) {
|
|
95
|
+
const parent = path.dirname(current);
|
|
96
|
+
if (parent === current) break;
|
|
97
|
+
rest.unshift(path.basename(current));
|
|
98
|
+
current = parent;
|
|
99
|
+
}
|
|
100
|
+
return path.join(fs.realpathSync(current), ...rest);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const git = (...args) => spawnSync('git', args, { encoding: 'utf8' });
|
|
104
|
+
|
|
105
|
+
function initializeGit(root) {
|
|
106
|
+
if (git('-C', root, 'rev-parse', '--git-dir').status === 0) return false;
|
|
107
|
+
const result = git('-C', root, 'init');
|
|
108
|
+
if (result.status !== 0) {
|
|
109
|
+
throw new AccreteError('external', 'Workspace files are in place, but git init failed', { project_root: root, stderr: result.stderr });
|
|
110
|
+
}
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const shellWord = word => /^[\w./-]+$/.test(word) ? word : `'${word.replaceAll("'", `'\\''`)}'`;
|
|
115
|
+
|
|
116
|
+
/** Install this host's Kernel. A failure leaves the Workspace and names the retry. */
|
|
117
|
+
function configureKernel(root, scaffold, receipt, { install = true, dryRun = false }) {
|
|
118
|
+
const report = action => ({ version: scaffold.kernel_version, platform: hostPlatform(), path: BINARY, action });
|
|
119
|
+
if (!install) {
|
|
120
|
+
receipt.kernel = report('skipped');
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
try {
|
|
124
|
+
const publish = publisher(root);
|
|
125
|
+
receipt.kernel = installKernel(root, scaffold, { dryRun, write: publish.write.bind(publish) });
|
|
126
|
+
receipt.written.push(...publish.written);
|
|
127
|
+
} catch (error) {
|
|
128
|
+
receipt.kernel = report('failed');
|
|
129
|
+
receipt.ok = false;
|
|
130
|
+
receipt.failed.push({
|
|
131
|
+
destination: BINARY,
|
|
132
|
+
action: 'failed',
|
|
133
|
+
planned: 'install',
|
|
134
|
+
error: error.message,
|
|
135
|
+
retry: `npx accrete-kit@${scaffold.template_version} install --project ${shellWord(root)}`
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export function createWorkspace(target, options, scaffold) {
|
|
141
|
+
const agents = options.agents === undefined ? null : parseAgents(scaffold, options.agents);
|
|
142
|
+
if (options.id !== undefined) checkId(options.id);
|
|
143
|
+
if (options.timezone !== undefined) checkTimezone(options.timezone);
|
|
144
|
+
if (options.name === '') throw new AccreteError('invalid', '--name cannot be empty');
|
|
145
|
+
const root = canonicalFuture(target);
|
|
146
|
+
if (options.git !== false && git('--version').status !== 0) {
|
|
147
|
+
throw new AccreteError('dependency', 'Git is needed to initialize a repository; use --no-git to omit it');
|
|
148
|
+
}
|
|
149
|
+
if (fs.existsSync(root) && !fs.statSync(root).isDirectory()) throw new AccreteError('invalid', `${root} is not a directory`);
|
|
150
|
+
refuseSymlinks(root, MARKER);
|
|
151
|
+
|
|
152
|
+
const created = !fs.existsSync(path.join(root, MARKER));
|
|
153
|
+
let identity;
|
|
154
|
+
if (created) {
|
|
155
|
+
const defaults = readSimpleToml(scaffold.defaults)[''];
|
|
156
|
+
checkFormat(scaffold, defaults.format);
|
|
157
|
+
identity = {
|
|
158
|
+
format: defaults.format,
|
|
159
|
+
project_id: options.id ?? randomUUID(),
|
|
160
|
+
name: options.name ?? path.basename(root),
|
|
161
|
+
timezone: options.timezone ?? defaults.timezone,
|
|
162
|
+
paths: readSimpleToml(scaffold.defaults).paths ?? {}
|
|
163
|
+
};
|
|
164
|
+
} else {
|
|
165
|
+
identity = readMarker(root);
|
|
166
|
+
checkFormat(scaffold, identity.format);
|
|
167
|
+
if (options.id !== undefined && options.id !== identity.project_id) {
|
|
168
|
+
throw new AccreteError('conflict', 'The existing Workspace identity differs from the requested ID', { path: path.join(root, MARKER), project_id: identity.project_id });
|
|
169
|
+
}
|
|
170
|
+
if (options.name !== undefined && options.name !== identity.name) {
|
|
171
|
+
throw new AccreteError('conflict', 'The existing Workspace name differs; creation does not rewrite shared configuration', { path: path.join(root, MARKER), name: identity.name });
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
const header = {
|
|
175
|
+
action: 'create',
|
|
176
|
+
created,
|
|
177
|
+
project_id: identity.project_id,
|
|
178
|
+
name: identity.name,
|
|
179
|
+
timezone: identity.timezone,
|
|
180
|
+
format: identity.format,
|
|
181
|
+
marker: path.join(root, MARKER)
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
// A repeated creation finishes its own version; moving to another is upgrade.
|
|
185
|
+
const installed = created ? null : readInventory(root);
|
|
186
|
+
if (installed && installed.template_version !== scaffold.template_version) {
|
|
187
|
+
return {
|
|
188
|
+
ok: true,
|
|
189
|
+
...header,
|
|
190
|
+
skipped: true,
|
|
191
|
+
project_root: root,
|
|
192
|
+
template_version: scaffold.template_version,
|
|
193
|
+
kernel_version: scaffold.kernel_version,
|
|
194
|
+
installed_version: installed.template_version,
|
|
195
|
+
git_initialized: false,
|
|
196
|
+
written: [],
|
|
197
|
+
removed: [],
|
|
198
|
+
pending: [],
|
|
199
|
+
failed: [],
|
|
200
|
+
message: `This Workspace has template ${installed.template_version}; use npx accrete-kit@${scaffold.template_version} upgrade`
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if (created) {
|
|
205
|
+
atomicWrite(path.join(root, MARKER), Buffer.from(markerText(scaffold, {
|
|
206
|
+
projectId: identity.project_id, name: identity.name, timezone: identity.timezone
|
|
207
|
+
})));
|
|
208
|
+
}
|
|
209
|
+
const receipt = reconcile(root, scaffold, { agents, paths: identity.paths });
|
|
210
|
+
if (created) receipt.written.unshift(MARKER);
|
|
211
|
+
const gitInitialized = options.git === false ? false : initializeGit(root);
|
|
212
|
+
if (!created && options.timezone !== undefined && options.timezone !== identity.timezone) {
|
|
213
|
+
receipt.warnings = [`The existing timezone ${identity.timezone} was kept; edit ${MARKER} to change it`];
|
|
214
|
+
}
|
|
215
|
+
configureKernel(root, scaffold, receipt, options);
|
|
216
|
+
return { ...receipt, ...header, git_initialized: gitInitialized };
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export function findWorkspace(start) {
|
|
220
|
+
let current = fs.realpathSync(start);
|
|
221
|
+
for (;;) {
|
|
222
|
+
if (fs.existsSync(path.join(current, MARKER))) return current;
|
|
223
|
+
const parent = path.dirname(current);
|
|
224
|
+
if (parent === current) return null;
|
|
225
|
+
current = parent;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/** An older package would rewrite newer guidance backward. Equal versions run. */
|
|
230
|
+
function refuseBackward(inventory, scaffold) {
|
|
231
|
+
const installed = numericVersion(inventory?.template_version ?? '');
|
|
232
|
+
const incoming = numericVersion(scaffold.template_version);
|
|
233
|
+
if (installed && incoming && compareVersions(installed, incoming) > 0) {
|
|
234
|
+
throw new AccreteError('conflict', `This Workspace has template ${inventory.template_version}, newer than accrete-kit ${scaffold.template_version}; use npx accrete-kit@latest upgrade`);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
export function upgradeWorkspace(root, options, scaffold) {
|
|
239
|
+
const identity = readMarker(root);
|
|
240
|
+
checkFormat(scaffold, identity.format);
|
|
241
|
+
refuseBackward(readInventory(root), scaffold);
|
|
242
|
+
const dryRun = Boolean(options.dryRun);
|
|
243
|
+
if (options.accept !== undefined) {
|
|
244
|
+
return { action: 'accept', project_id: identity.project_id, ...accept(root, scaffold, options.accept, { dryRun }) };
|
|
245
|
+
}
|
|
246
|
+
const agents = options.agents === undefined ? null : parseAgents(scaffold, options.agents);
|
|
247
|
+
const receipt = reconcile(root, scaffold, { agents, dryRun, paths: identity.paths });
|
|
248
|
+
configureKernel(root, scaffold, receipt, { ...options, dryRun });
|
|
249
|
+
return { action: 'upgrade', project_id: identity.project_id, ...receipt };
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/** Restore this host's Kernel in an existing Workspace, at the version it records. */
|
|
253
|
+
export function installWorkspace(root, scaffold) {
|
|
254
|
+
const identity = readMarker(root);
|
|
255
|
+
checkFormat(scaffold, identity.format);
|
|
256
|
+
const inventory = readInventory(root);
|
|
257
|
+
if (!inventory) throw new AccreteError('not_found', 'This Workspace has no template inventory; run npx accrete-kit@latest upgrade');
|
|
258
|
+
if (inventory.kernel_version !== scaffold.kernel_version) {
|
|
259
|
+
const command = `npx accrete-kit@${inventory.template_version} install`;
|
|
260
|
+
throw new AccreteError('conflict', `This Workspace records Kernel ${inventory.kernel_version}, and accrete-kit ${scaffold.template_version} carries ${scaffold.kernel_version}; run ${command}`, { command });
|
|
261
|
+
}
|
|
262
|
+
const publish = publisher(root);
|
|
263
|
+
const kernel = installKernel(root, scaffold, { write: publish.write.bind(publish) });
|
|
264
|
+
return {
|
|
265
|
+
ok: true,
|
|
266
|
+
action: 'install',
|
|
267
|
+
dry_run: false,
|
|
268
|
+
project_root: root,
|
|
269
|
+
project_id: identity.project_id,
|
|
270
|
+
template_version: inventory.template_version,
|
|
271
|
+
kernel_version: scaffold.kernel_version,
|
|
272
|
+
kernel,
|
|
273
|
+
written: publish.written,
|
|
274
|
+
removed: [],
|
|
275
|
+
pending: inventory.files.filter(entry => entry.pending).map(entry => entry.destination),
|
|
276
|
+
failed: []
|
|
277
|
+
};
|
|
278
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "accrete-kit",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
}
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Create and upgrade ACCRETE Workspaces",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": { "type": "git", "url": "git+https://github.com/Wanli-Wylie/accrete-template.git" },
|
|
7
|
+
"type": "module",
|
|
8
|
+
"engines": { "node": ">=20" },
|
|
9
|
+
"bin": { "accrete-kit": "bin/accrete-kit.mjs" },
|
|
10
|
+
"files": ["bin/", "lib/", "dist/scaffold/", "dist/kernel/", "LICENSE", "CHANGELOG.md"],
|
|
11
|
+
"accrete": { "cli": "0.1.0", "cliRepo": "Wanli-Wylie/accrete-cli" },
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "node scripts/build.mjs",
|
|
14
|
+
"check": "node scripts/build.mjs --check",
|
|
15
|
+
"pretest": "node scripts/build.mjs",
|
|
16
|
+
"test": "node --test test/install.test.mjs test/cli.test.mjs test/kernel.test.mjs test/contract.test.mjs test/package.test.mjs",
|
|
17
|
+
"prepublishOnly": "node scripts/fetch-kernel.mjs --check",
|
|
18
|
+
"prepack": "node scripts/build.mjs"
|
|
19
|
+
}
|
|
20
|
+
}
|