13 · install-empty-dir
What this scenario proves
archon install succeeds on a fully empty directory — no package.json, no pyproject.toml, no source files, nothing but a single placeholder README. This is the null reference point for the install-matrix: the simplest "before" state imaginable, and the upper bound on what install can possibly add.
A passing run here proves three things:
- Install does not require any pre-existing language manifest (
package.json/pyproject.toml/go.mod/Cargo.toml). - Install does not require any business code or runnable tests.
- Seeded runtime ledgers (
.archon/drift.md,.archon/manifest.md, etc.) are created fromseedRuntimeLedgers()even when the target tree is otherwise empty.
This scenario pairs with 14 · install-existing-project to bracket the install behaviour: 13 is "install adds everything", 14 is "install adds Archon files and touches nothing else".
Test environment
| Fixture | fixtures/sandbox-empty |
| IDE | Cursor (default; binding directory .cursor/ is laid out) |
| OS | macOS 14 / Ubuntu 22.04 / Windows 11 |
| Archon source | local mirror of docs/public/manifest.json (sandbox runner) |
| Manifest version under test | v0.1.x |
| Language toolchain | none |
Pre-conditions
- Fixture copied to a fresh tmp dir (the runner does this automatically).
- No
.archon/and no.cursor/exist.
Steps
text
1. Run:
archon install --with=cli
2. Wait for the "install complete" summary line.Expected outcome
| Check | Expected |
|---|---|
| Exit code (CLI) | 0 |
.archon/VERSION | exists, matches manifest version |
.archon/soul.md | exists |
.archon/manifest.md | exists (seeded header) |
.archon/drift.md | exists; contains exactly one ## install row |
.cursor/commands/archon.md | exists |
.cursor/rules/ | exists |
.cursor/skills/ | exists |
tools/archon-cli/ (because --with=cli) | exists |
.archon-backup-* (no force, no prior install) | absent |
Demo recordings
Recording coming soon
install-empty-dir.mp4IDE chat-panel walkthroughdocs/public/videos/install-empty-dir.mp4 once recorded. See videos/README for upload conventions. $ archon doctor .
[L1 Structural] OK
[L2 Contract] OK
[L3 Hints] OK
✔ Recording coming soon — placeholderdocs/public/asciinema/install-empty-dir.cast embedded via the asciinema-player web component. See asciinema/README for the recording command. Run records
The table below is rendered live from JSON written by the sandbox runner (scripts/sandbox-run.mjs) under docs/testing/sandbox/runs/install-empty-dir/. To add a new row, run
bash
node scripts/sandbox-run.mjs --only=install-empty-dir| Started (UTC) | Manifest | Runner | Result | Duration | Notes | Record |
|---|---|---|---|---|---|---|
2026-06-08 08:17:10 UTC | v0.1.0 | cli | ✅ passing | 310 ms | — | JSON |
2026-06-07 07:10:15 UTC | v0.1.0 | cli | ✅ passing | 328 ms | — | JSON |
2026-06-06 06:34:39 UTC | v0.1.0 | cli | ✅ passing | 329 ms | — | JSON |
2026-06-05 07:14:06 UTC | v0.1.0 | cli | ✅ passing | 308 ms | — | JSON |
2026-06-04 07:56:42 UTC | v0.1.0 | cli | ✅ passing | 381 ms | — | JSON |
2026-06-03 08:24:16 UTC | v0.1.0 | cli | ✅ passing | 369 ms | — | JSON |
2026-06-02 08:00:50 UTC | v0.1.0 | cli | ✅ passing | 321 ms | — | JSON |
2026-06-01 08:40:44 UTC | v0.1.0 | cli | ✅ passing | 337 ms | — | JSON |
2026-05-31 07:02:23 UTC | v0.1.0 | cli | ✅ passing | 336 ms | — | JSON |
2026-05-30 06:27:52 UTC | v0.1.0 | cli | ✅ passing | 315 ms | — | JSON |
2026-05-29 06:59:38 UTC | v0.1.0 | cli | ✅ passing | 373 ms | — | JSON |
2026-05-28 06:59:32 UTC | v0.1.0 | cli | ✅ passing | 345 ms | — | JSON |
2026-05-27 07:09:41 UTC | v0.1.0 | cli | ✅ passing | 350 ms | — | JSON |
2026-05-26 06:52:08 UTC | v0.1.0 | cli | ✅ passing | 282 ms | — | JSON |
2026-05-25 07:20:21 UTC | v0.1.0 | cli | ✅ passing | 320 ms | — | JSON |
2026-05-24 06:41:51 UTC | v0.1.0 | cli | ✅ passing | 333 ms | — | JSON |
2026-05-23 06:16:49 UTC | v0.1.0 | cli | ✅ passing | 334 ms | — | JSON |
2026-05-22 06:54:17 UTC | v0.1.0 | cli | ✅ passing | 335 ms | — | JSON |
2026-05-21 06:58:03 UTC | v0.1.0 | cli | ✅ passing | 314 ms | — | JSON |
2026-05-20 06:53:36 UTC | v0.1.0 | cli | ✅ passing | 314 ms | — | JSON |
2026-05-19 06:53:17 UTC | v0.1.0 | cli | ✅ passing | 311 ms | — | JSON |
2026-05-18 07:01:46 UTC | v0.1.0 | cli | ✅ passing | 336 ms | — | JSON |
2026-05-17 06:27:35 UTC | v0.1.0 | cli | ✅ passing | 325 ms | — | JSON |
2026-05-16 06:04:39 UTC | v0.1.0 | cli | ✅ passing | 308 ms | — | JSON |
2026-05-15 06:37:58 UTC | v0.1.0 | cli | ✅ passing | 351 ms | — | JSON |
2026-05-14 06:28:55 UTC | v0.1.0 | cli | ✅ passing | 332 ms | — | JSON |
2026-05-13 06:30:24 UTC | v0.1.0 | cli | ✅ passing | 295 ms | — | JSON |
2026-05-12 06:18:59 UTC | v0.1.0 | cli | ✅ passing | 323 ms | — | JSON |
2026-05-11 06:45:34 UTC | v0.1.0 | cli | ✅ passing | 316 ms | — | JSON |
2026-05-10 06:16:43 UTC | v0.1.0 | cli | ✅ passing | 337 ms | — | JSON |
2026-05-09 05:52:36 UTC | v0.1.0 | cli | ✅ passing | 265 ms | — | JSON |
2026-05-08 05:33:34 UTC | v0.1.0 | cli | ✅ passing | 347 ms | — | JSON |
2026-05-07 11:01:02 UTC | v0.1.0 | cli | ✅ passing | 327 ms | — | JSON |
2026-05-07 09:54:52 UTC | v0.1.0 | cli | ✅ passing | 327 ms | — | JSON |
2026-05-07 09:45:11 UTC | v0.1.0 | cli | ✅ passing | 520 ms | — | JSON |
2026-05-07 06:15:43 UTC | v0.1.0 | cli | ✅ passing | 248 ms | — | JSON |
2026-05-06 11:45:36 UTC | v0.1.0 | cli | ✅ passing | 316 ms | — | JSON |
2026-05-06 11:44:05 UTC | v0.1.0 | cli | ✅ passing | 324 ms | — | JSON |
2026-05-06 11:19:25 UTC | v0.1.0 | cli | ✅ passing | 348 ms | — | JSON |
2026-05-06 11:15:59 UTC | v0.1.0 | cli | ✅ passing | 354 ms | — | JSON |
2026-05-06 11:14:04 UTC | v0.1.0 | cli | ❌ failing | 267 ms | failed assertions: cmd_zero: ["node","-e","const fs=require('fs');const c=fs.readFileSync('.archon/drift.md','utf8');const m=c.match(/^## install /gm);const n=m?m.length:0;if(n!==1){console.error('expected 1 install row, got',n);process.exit(1)}"]: cmd exited 1: node -e const fs=require('fs');const c=fs.readFileSync('.archon/drift.md','utf8');const m=c.match(/^## install /gm);const n=m?m.length:0;if(n!==1){console.error('expected 1 install row, got',n);process.exit(1)} stderr-tail: m:185:14) at compileScript (node:internal/process/execution:386:10) at node:internal/process/execution:450:25 at [eval]-wrapper:6:24 at runScriptInContext (node:internal/process/execution:447:60) at evalFunction (node:internal/process/execution:87:30) at evalScript (node:internal/process/execution:99:3) at node:internal/main/eval_string:74:3 Node.js v22.14.0 | JSON |
2026-05-06 11:12:53 UTC | v0.1.0 | cli | ❌ failing | 274 ms | failed assertions: cmd_zero: ["node","-e","const fs=require('fs');const c=fs.readFileSync('.archon/drift.md','utf8');const n=(c.match(/^## install /gm)||[]).length;if(n!==1){console.error('expected 1 install row, got',n);process.exit(1)}"]: cmd exited 1: node -e const fs=require('fs');const c=fs.readFileSync('.archon/drift.md','utf8');const n=(c.match(/^## install /gm)||[]).length;if(n!==1){console.error('expected 1 install row, got',n);process.exit(1)} stderr-tail: s/execution:450:25 at [eval]-wrapper:6:24 at runScriptInContext (node:internal/process/execution:447:60) at evalFunction (node:internal/process/execution:87:30) at evalScript (node:internal/process/execution:99:3) at node:internal/main/eval_string:74:3 Node.js v22.14.0 '[]).length' is not recognized as an internal or external command, operable program or batch file. | JSON |
Known limitations
- Does not test what happens if the directory does not exist at all.
install.mjscallsfs.mkdir(targetDir, { recursive: true })so a non-existent path is handled, but that is exercised by the CLI's own unit tests, not by the sandbox. - Does not validate the ledger seeding content (drift body, manifest header) line-by-line — only that the files exist. A future scenario may diff the seeded headers against
seedRuntimeLedgers()literals.
Cross-references
- Protocol page:
/setup/install - Companion scenario: 14 · install-existing-project — same install, but on a non-empty fixture.
- Install matrix index: Install Matrix
- CLI source:
docs/source-files/tools/archon-cli/lib/install.mjs
json
{
"runnable": "cli",
"fixture": "fixtures/sandbox-empty",
"ide_platform": "cursor",
"prerequisites": [
{
"name": "drop sandbox check helper",
"write_file": {
"path": "__sb-check.cjs",
"content": "const fs=require('fs');const op=process.argv[2];const args=process.argv.slice(3);if(op==='drift-install-count'){const want=Number(args[0]);const c=fs.readFileSync('.archon/drift.md','utf8');const m=c.match(/^## install /gm);const n=m?m.length:0;if(n!==want){console.error('drift install rows: want',want,'got',n);process.exit(1)}process.exit(0)}if(op==='no-backup-dir'){const found=fs.readdirSync('.').some(function(x){return x.indexOf('.archon-backup-')===0});if(found){console.error('unexpected .archon-backup-*');process.exit(1)}process.exit(0)}if(op==='has-backup-dir'){const found=fs.readdirSync('.').some(function(x){return x.indexOf('.archon-backup-')===0});if(!found){console.error('expected .archon-backup-* missing');process.exit(1)}process.exit(0)}if(op==='pkg-name-equals'){const p=require('./package.json');if(p.name!==args[0]){console.error('package.json name mutated:',p.name);process.exit(1)}process.exit(0)}if(op==='file-includes'){const text=fs.readFileSync(args[0],'utf8');if(text.indexOf(args[1])===-1){console.error(args[0],'missing',args[1]);process.exit(1)}process.exit(0)}if(op==='drift-modules-excludes'){const c=fs.readFileSync('.archon/drift.md','utf8');const re=new RegExp('^- Modules:.*\\\\b'+args[0]+'\\\\b','m');if(re.test(c)){console.error(args[0],'unexpectedly listed');process.exit(1)}process.exit(0)}console.error('unknown op:',op);process.exit(2);\n"
}
}
],
"steps": [
{
"name": "archon install --with=cli",
"cli": "install",
"flags": ["--with=cli"]
}
],
"assertions": [
{ "file_exists": ".archon/VERSION" },
{ "file_exists": ".archon/soul.md" },
{ "file_exists": ".archon/manifest.md" },
{ "file_exists": ".archon/drift.md" },
{ "dir_exists": ".cursor/commands" },
{ "dir_exists": ".cursor/rules" },
{ "dir_exists": ".cursor/skills" },
{ "file_exists": ".cursor/commands/archon.md" },
{ "dir_exists": "tools/archon-cli" },
{ "file_exists": "scripts/archon-check.py" },
{ "cmd_zero": ["node", "__sb-check.cjs", "drift-install-count", "1"] },
{ "cmd_zero": ["node", "__sb-check.cjs", "no-backup-dir"] },
{ "cmd_zero": ["python3", "scripts/archon-check.py", "--root", "."] }
],
"notes": "Null reference point for the install matrix: empty dir + minimal flags. The __sb-check.cjs helper is written by a prerequisite step and provides cross-platform-safe assertions (Windows shell-quoting strips embedded quotes from `node -e ...`)."
}