axstack 0.36.0 → 0.37.0
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/README.md +10 -6
- package/bin/axstack.js +4 -18
- package/docs/getting-started.md +6 -6
- package/docs/host-operations.md +77 -5
- package/docs/installation.md +25 -43
- package/docs/workflows.md +12 -9
- package/package.json +1 -1
- package/profiles/presets/claude-only.json +3 -3
- package/profiles/presets/codex-only.json +3 -3
- package/profiles/presets/mixed.json +5 -4
- package/skills/axstack/references/role-roster.md +5 -3
- package/skills/axstack/references/ui-verification.md +6 -10
- package/skills/axstack/scripts/single-server.js +164 -0
- package/skills/axstack/systemd/axstack-single-server.service +8 -0
- package/skills/axstack/systemd/axstack-single-server.timer +10 -0
- package/skills/axstack-anatomy/ANATOMY.md +172 -0
- package/skills/axstack-anatomy/CHANGELOG.md +70 -0
- package/skills/axstack-anatomy/LICENSE +21 -0
- package/skills/axstack-anatomy/PROVENANCE.md +21 -0
- package/skills/axstack-anatomy/README.md +316 -0
- package/skills/axstack-anatomy/SKILL.md +74 -0
- package/skills/axstack-anatomy/SOURCE-PROOF.json +107 -0
- package/skills/axstack-anatomy/examples/arcade-cabinet/arcade-cabinet.css +44 -0
- package/skills/axstack-anatomy/examples/arcade-cabinet/build.mjs +714 -0
- package/skills/axstack-anatomy/examples/arcade-cabinet/live.js +597 -0
- package/skills/axstack-anatomy/examples/arcade-cabinet/parts.mjs +89 -0
- package/skills/axstack-anatomy/examples/arcade-cabinet/screen.mjs +114 -0
- package/skills/axstack-anatomy/examples/desk-computer/build.mjs +435 -0
- package/skills/axstack-anatomy/examples/dial-indicator/build.mjs +275 -0
- package/skills/axstack-anatomy/examples/raptor-engine/build.mjs +938 -0
- package/skills/axstack-anatomy/examples/raptor-engine/live.js +907 -0
- package/skills/axstack-anatomy/examples/raptor-engine/raptor.css +359 -0
- package/skills/axstack-anatomy/examples/ripple-tank/build.mjs +558 -0
- package/skills/axstack-anatomy/examples/ripple-tank/live.js +579 -0
- package/skills/axstack-anatomy/examples/ripple-tank/model.mjs +131 -0
- package/skills/axstack-anatomy/examples/ripple-tank/ripple.css +103 -0
- package/skills/axstack-anatomy/examples/spot-plate/art.tsx +110 -0
- package/skills/axstack-anatomy/examples/spot-plate/drops.ts +541 -0
- package/skills/axstack-anatomy/examples/spot-plate/fan.ts +84 -0
- package/skills/axstack-anatomy/examples/spot-plate/figure.tsx +25 -0
- package/skills/axstack-anatomy/examples/spot-plate/geometry.ts +280 -0
- package/skills/axstack-anatomy/examples/spot-plate/live.tsx +339 -0
- package/skills/axstack-anatomy/examples/spot-plate/rig.ts +230 -0
- package/skills/axstack-anatomy/examples/spot-plate/spot-plate.css +92 -0
- package/skills/axstack-anatomy/examples/test-rig/art.tsx +196 -0
- package/skills/axstack-anatomy/examples/test-rig/figure.tsx +23 -0
- package/skills/axstack-anatomy/examples/test-rig/geometry.ts +305 -0
- package/skills/axstack-anatomy/examples/test-rig/live.tsx +511 -0
- package/skills/axstack-anatomy/examples/test-rig/pose.ts +107 -0
- package/skills/axstack-anatomy/examples/test-rig/rig.ts +170 -0
- package/skills/axstack-anatomy/examples/test-rig/stretch.css +80 -0
- package/skills/axstack-anatomy/examples/test-rig/view.ts +99 -0
- package/skills/axstack-anatomy/examples/turning-dial/build.mjs +479 -0
- package/skills/axstack-anatomy/examples/turning-dial/dial.css +10 -0
- package/skills/axstack-anatomy/examples/turning-dial/live.js +342 -0
- package/skills/axstack-anatomy/examples/turning-dial/stress.mjs +269 -0
- package/skills/axstack-anatomy/kit/audit.mjs +1913 -0
- package/skills/axstack-anatomy/kit/canvas-painter.mjs +722 -0
- package/skills/axstack-anatomy/kit/gl-shared.mjs +184 -0
- package/skills/axstack-anatomy/kit/gl.mjs +184 -0
- package/skills/axstack-anatomy/kit/iso-kit.mjs +674 -0
- package/skills/axstack-anatomy/kit/iso-kit.ts +842 -0
- package/skills/axstack-anatomy/kit/iso.css +106 -0
- package/skills/axstack-anatomy/kit/lathe.mjs +1184 -0
- package/skills/axstack-anatomy/kit/react/draw.tsx +205 -0
- package/skills/axstack-anatomy/kit/react/live.tsx +140 -0
- package/skills/axstack-anatomy/kit/tube.mjs +306 -0
- package/skills/axstack-anatomy/kit/turn-audit.mjs +1096 -0
- package/skills/axstack-anatomy/kit/turn-build.mjs +1355 -0
- package/skills/axstack-anatomy/kit/turn-fixed.mjs +3800 -0
- package/skills/axstack-anatomy/kit/turn.mjs +3610 -0
- package/skills/axstack-anatomy/references/3d.md +352 -0
- package/skills/axstack-anatomy/references/craft.md +325 -0
- package/skills/axstack-anatomy/references/kit.md +419 -0
- package/skills/axstack-anatomy/references/motion.md +165 -0
- package/skills/axstack-anatomy/references/react.md +42 -0
- package/skills/axstack-anatomy/references/verify.md +351 -0
- package/skills/axstack-anatomy/references/walkthrough.md +75 -0
- package/skills/axstack-anatomy/references/webgl.md +473 -0
- package/skills/axstack-anatomy/scripts/audit-affine-bounds.test.mjs +54 -0
- package/skills/axstack-anatomy/scripts/audit-cache.test.mjs +37 -0
- package/skills/axstack-anatomy/scripts/audit-clearance-envelope.test.mjs +39 -0
- package/skills/axstack-anatomy/scripts/audit-empty-clipping.test.mjs +38 -0
- package/skills/axstack-anatomy/scripts/audit-order-convergence.test.mjs +55 -0
- package/skills/axstack-anatomy/scripts/audit-path-origin.test.mjs +26 -0
- package/skills/axstack-anatomy/scripts/audit-profile.test.mjs +41 -0
- package/skills/axstack-anatomy/scripts/audit-projection.test.mjs +36 -0
- package/skills/axstack-anatomy/scripts/audit-slide-clearance.test.mjs +58 -0
- package/skills/axstack-anatomy/scripts/audit-svg-attributes.test.mjs +46 -0
- package/skills/axstack-anatomy/scripts/audit-taper.test.mjs +29 -0
- package/skills/axstack-anatomy/scripts/capture-selector.test.mjs +131 -0
- package/skills/axstack-anatomy/scripts/capture.mjs +228 -0
- package/skills/axstack-anatomy/scripts/capture.test.mjs +42 -0
- package/skills/axstack-anatomy/scripts/chrome-port.mjs +36 -0
- package/skills/axstack-anatomy/scripts/chrome-startup.test.mjs +38 -0
- package/skills/axstack-anatomy/scripts/drive-actions.test.mjs +46 -0
- package/skills/axstack-anatomy/scripts/drive.mjs +302 -0
- package/skills/axstack-anatomy/scripts/drive.test.mjs +72 -0
- package/skills/axstack-anatomy/scripts/enter-key.test.mjs +38 -0
- package/skills/axstack-anatomy/scripts/fidelity-cut.test.mjs +54 -0
- package/skills/axstack-anatomy/scripts/fidelity-tube-coverage.test.mjs +40 -0
- package/skills/axstack-anatomy/scripts/inline-kit.mjs +26 -0
- package/skills/axstack-anatomy/scripts/line-ends.mjs +306 -0
- package/skills/axstack-anatomy/scripts/lines-arcs.test.mjs +50 -0
- package/skills/axstack-anatomy/scripts/lines-bezier.test.mjs +28 -0
- package/skills/axstack-anatomy/scripts/lines-round.test.mjs +56 -0
- package/skills/axstack-anatomy/scripts/lines-rounded-rect.test.mjs +32 -0
- package/skills/axstack-anatomy/scripts/lines.mjs +31 -0
- package/skills/axstack-anatomy/scripts/lines.test.mjs +38 -0
- package/skills/axstack-anatomy/scripts/navigation.test.mjs +55 -0
- package/skills/axstack-anatomy/scripts/orbit-sampling.test.mjs +50 -0
- package/skills/axstack-anatomy/scripts/react-dots-opacity.test.mjs +51 -0
- package/skills/axstack-anatomy/scripts/react-readout-first-write.test.mjs +37 -0
- package/skills/axstack-anatomy/scripts/react-solid-seamless.test.mjs +47 -0
- package/skills/axstack-anatomy/scripts/react-visibility-target.test.mjs +38 -0
- package/skills/axstack-anatomy/scripts/turn-bench.mjs +74 -0
- package/skills/axstack-anatomy/scripts/turn-check.mjs +641 -0
- package/skills/axstack-anatomy/scripts/turn-fidelity.mjs +413 -0
- package/skills/axstack-anatomy/scripts/turn-group-reference.test.mjs +40 -0
- package/skills/axstack-anatomy/scripts/turn-split-owner.test.mjs +62 -0
- package/skills/axstack-anatomy/theme.js +56 -0
- package/skills/axstack-explain/SKILL.md +28 -15
- package/skills/axstack-explain/references/delivery.md +22 -0
- package/skills/{axstack-diagram → axstack-explain}/references/fidelity.md +1 -7
- package/skills/axstack-explain/references/inline-pages.md +8 -8
- package/skills/axstack-explain/references/visual-qa.md +3 -5
- package/skills/axstack-explain/references/whiteboard-defense.md +59 -0
- package/src/archify-legacy.js +70 -0
- package/src/capabilities.js +1 -29
- package/src/installer.js +11 -31
- package/skills/axstack-diagram/SKILL.md +0 -28
- package/skills/axstack-diagram/references/archify.md +0 -76
- package/src/archify-pin.js +0 -5
- package/src/archify.js +0 -151
package/src/archify.js
DELETED
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
import { lstat, mkdir, mkdtemp, readFile, rename, rm } from 'node:fs/promises';
|
|
2
|
-
import { join } from './posixpath.js';
|
|
3
|
-
import { ARCHIFY_PIN } from './archify-pin.js';
|
|
4
|
-
|
|
5
|
-
export const ARCHIFY_RECORD = 'axstack-diagram/archify.json';
|
|
6
|
-
|
|
7
|
-
export function archifyGit(path, ...args) {
|
|
8
|
-
try {
|
|
9
|
-
const result = Bun.spawnSync(['git', ...(path ? ['-C', path] : []), ...args], {
|
|
10
|
-
stdout: 'pipe', stderr: 'pipe', timeout: 60000,
|
|
11
|
-
env: { ...Bun.env, GIT_TERMINAL_PROMPT: '0' },
|
|
12
|
-
});
|
|
13
|
-
if (result.exitCode !== 0) throw new Error(result.stderr.toString().trim() || `git exit ${result.exitCode}`);
|
|
14
|
-
return result.stdout.toString().trim();
|
|
15
|
-
} catch (err) {
|
|
16
|
-
throw new Error(`git: ${err.message}`);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function verifySha(record, actual) {
|
|
21
|
-
if (actual === record.sha) return;
|
|
22
|
-
/** @type {Error & {code?: string}} */
|
|
23
|
-
const error = new Error(`archify SHA mismatch: expected ${record.sha}, got ${actual}`);
|
|
24
|
-
error.code = 'ARCHIFY_SHA_MISMATCH';
|
|
25
|
-
throw error;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
async function ownersSnapshot(path) {
|
|
29
|
-
const st = await lstat(path).catch((err) => {
|
|
30
|
-
if (err.code === 'ENOENT') return null;
|
|
31
|
-
throw err;
|
|
32
|
-
});
|
|
33
|
-
if (st && (!st.isFile() || st.isSymbolicLink())) throw new Error(`unsafe archify owners file: ${path}`);
|
|
34
|
-
const bytes = st ? await readFile(path) : null;
|
|
35
|
-
// JSON.parse coerces its argument to a string; preserve the existing Buffer coercion.
|
|
36
|
-
const owners = bytes ? /** @type {(text: {toString(): string}) => unknown} */ (JSON.parse)(bytes) : [];
|
|
37
|
-
if (!Array.isArray(owners) || owners.some((owner) => typeof owner !== 'string' || !owner.startsWith('/'))) {
|
|
38
|
-
throw new Error(`invalid archify owners file: ${path}`);
|
|
39
|
-
}
|
|
40
|
-
return { bytes, owners, mode: st ? st.mode & 0o777 : null };
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// Drop ownership transactionally; defer destructive cleanup until the skills
|
|
44
|
-
// manifest commits. A failed manifest write can then restore the owner list.
|
|
45
|
-
export async function planArchifyRelease({ record, skillsRoot, writeAtomic, log }) {
|
|
46
|
-
const ownersFile = `${record.path}.owners.json`;
|
|
47
|
-
const before = await ownersSnapshot(ownersFile);
|
|
48
|
-
const remaining = before.owners.filter((owner) => owner !== skillsRoot);
|
|
49
|
-
if (!before.owners.includes(skillsRoot)) {
|
|
50
|
-
return { rollback: async () => {}, finish: async () => log(`archify: kept ${record.path} (owner is absent)`) };
|
|
51
|
-
}
|
|
52
|
-
try {
|
|
53
|
-
await writeAtomic(ownersFile, JSON.stringify(remaining) + '\n', { mode: 0o600 });
|
|
54
|
-
} catch (err) {
|
|
55
|
-
const current = await readFile(ownersFile);
|
|
56
|
-
if (!current.equals(before.bytes)) {
|
|
57
|
-
try { await writeAtomic(ownersFile, before.bytes, { mode: before.mode }); }
|
|
58
|
-
catch (restoreErr) { err.message += ` (archify owner restore failed: ${restoreErr.message})`; }
|
|
59
|
-
}
|
|
60
|
-
throw err;
|
|
61
|
-
}
|
|
62
|
-
return {
|
|
63
|
-
rollback: () => writeAtomic(ownersFile, before.bytes, { mode: before.mode }),
|
|
64
|
-
finish: async () => {
|
|
65
|
-
try {
|
|
66
|
-
if (remaining.length) throw new Error('other skills roots still own this copy');
|
|
67
|
-
const st = await lstat(record.path);
|
|
68
|
-
if (!st.isDirectory() || st.isSymbolicLink()) throw new Error('copy is not a real directory');
|
|
69
|
-
if (archifyGit(record.path, 'rev-parse', 'HEAD') !== record.sha) throw new Error('HEAD differs from the recorded SHA');
|
|
70
|
-
if (archifyGit(record.path, 'status', '--porcelain', '--ignored')) throw new Error('copy has tracked, untracked, or ignored changes');
|
|
71
|
-
await rm(record.path, { recursive: true });
|
|
72
|
-
await rm(ownersFile);
|
|
73
|
-
log(`archify: removed ${record.path}`);
|
|
74
|
-
} catch (err) {
|
|
75
|
-
log(`archify: kept ${record.path} (${err.message})`);
|
|
76
|
-
}
|
|
77
|
-
},
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// The caller includes this transaction in the skills/manifest rollback.
|
|
82
|
-
export async function provisionArchify({ toolsRoot, skillsRoot, writeAtomic, log }) {
|
|
83
|
-
if (!Bun.which('git')) {
|
|
84
|
-
log('archify: unavailable (git is not on PATH)');
|
|
85
|
-
return { record: null, rollback: async () => {} };
|
|
86
|
-
}
|
|
87
|
-
const record = { path: join(toolsRoot, `archify-${ARCHIFY_PIN.sha}`), sha: ARCHIFY_PIN.sha };
|
|
88
|
-
const ownersFile = `${record.path}.owners.json`;
|
|
89
|
-
const before = await ownersSnapshot(ownersFile);
|
|
90
|
-
let created = false;
|
|
91
|
-
let ownersWritten = false;
|
|
92
|
-
const rollback = async () => {
|
|
93
|
-
const errors = [];
|
|
94
|
-
if (ownersWritten) {
|
|
95
|
-
try {
|
|
96
|
-
if (before.bytes === null) await rm(ownersFile);
|
|
97
|
-
else await writeAtomic(ownersFile, before.bytes, { mode: before.mode });
|
|
98
|
-
} catch (err) { errors.push(`${ownersFile}: ${err.message}`); }
|
|
99
|
-
}
|
|
100
|
-
if (created) {
|
|
101
|
-
try { await rm(record.path, { recursive: true }); }
|
|
102
|
-
catch (err) { errors.push(`${record.path}: ${err.message}`); }
|
|
103
|
-
}
|
|
104
|
-
if (errors.length) throw new Error(`incomplete archify rollback: ${errors.join('; ')}`);
|
|
105
|
-
};
|
|
106
|
-
const existing = await lstat(record.path).catch((err) => {
|
|
107
|
-
if (err.code === 'ENOENT') return null;
|
|
108
|
-
throw err;
|
|
109
|
-
});
|
|
110
|
-
if (existing && (!existing.isDirectory() || existing.isSymbolicLink())) {
|
|
111
|
-
throw new Error(`unsafe archify copy: ${record.path}`);
|
|
112
|
-
}
|
|
113
|
-
if (existing) {
|
|
114
|
-
const actual = archifyGit(record.path, 'rev-parse', 'HEAD');
|
|
115
|
-
verifySha(record, actual);
|
|
116
|
-
} else {
|
|
117
|
-
let temp = null;
|
|
118
|
-
try {
|
|
119
|
-
await mkdir(toolsRoot, { recursive: true });
|
|
120
|
-
temp = await mkdtemp(join(toolsRoot, '.archify-'));
|
|
121
|
-
archifyGit(null, 'clone', '--filter=blob:none', '--no-checkout', '--', Bun.env.AXSTACK_ARCHIFY_REPO || ARCHIFY_PIN.repo, temp);
|
|
122
|
-
archifyGit(temp, 'sparse-checkout', 'set', '--no-cone', '/archify/');
|
|
123
|
-
archifyGit(temp, 'checkout', '--detach', record.sha);
|
|
124
|
-
const actual = archifyGit(temp, 'rev-parse', 'HEAD');
|
|
125
|
-
verifySha(record, actual);
|
|
126
|
-
await rename(temp, record.path);
|
|
127
|
-
temp = null;
|
|
128
|
-
created = true;
|
|
129
|
-
} catch (err) {
|
|
130
|
-
if (err.code === 'ARCHIFY_SHA_MISMATCH') throw err;
|
|
131
|
-
log(`archify: unavailable (${err.message.replace(/\s+/g, ' ').slice(0, 180)})`);
|
|
132
|
-
return { record: null, rollback: async () => {} };
|
|
133
|
-
} finally {
|
|
134
|
-
if (temp) await rm(temp, { recursive: true });
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
try {
|
|
138
|
-
if (!before.owners.includes(skillsRoot)) {
|
|
139
|
-
ownersWritten = true;
|
|
140
|
-
await writeAtomic(ownersFile, JSON.stringify([...before.owners, skillsRoot].sort()) + '\n', { mode: 0o600 });
|
|
141
|
-
}
|
|
142
|
-
} catch (err) {
|
|
143
|
-
const current = await readFile(ownersFile).catch(() => null);
|
|
144
|
-
ownersWritten = before.bytes === null ? current !== null : current?.equals(before.bytes) !== true;
|
|
145
|
-
try { await rollback(); }
|
|
146
|
-
catch (restoreErr) { err.message += ` (${restoreErr.message})`; }
|
|
147
|
-
throw err;
|
|
148
|
-
}
|
|
149
|
-
log(`archify: ${record.path} (${record.sha})`);
|
|
150
|
-
return { record, rollback };
|
|
151
|
-
}
|