Skip to content

14 · install-existing-project

What this scenario proves

archon install is non-invasive: when run against a real existing project (Node + TypeScript), it adds Archon's files but does not touch a single byte of the host project's existing files.

Specifically, after install:

  • package.json, tsconfig.json, src/todo.ts, src/todo.test.ts — byte-identical to the fixture.
  • .archon/, .cursor/, tools/archon-cli/, scripts/ — newly added by the manifest projection.

This is the "host project respects me, I respect host project" contract that distinguishes Archon from frameworks that mutate package.json scripts, override tsconfig.json, or rewrite source files. Pair this with 13 · install-empty-dir to see that the delta between the two post-install trees is exactly the host project's pre-existing files — proving install is purely additive.

Test environment

Fixturefixtures/sandbox-node-ts
IDECursor
OSmacOS 14 / Ubuntu 22.04 / Windows 11
Archon sourcelocal mirror of docs/public/manifest.json
Manifest version under testv0.1.x
Language toolchainNode 20.11+

Pre-conditions

  1. Fixture copied — runner-managed.
  2. No .archon/, no .cursor/.
  3. Fixture's own files (package.json etc.) are intact.

Steps

text
1. Run:
     archon install --with=cli
2. Wait for the "install complete" summary line.

Expected outcome

CheckExpected
Exit code0
.archon/soul.mdexists
.cursor/commands/archon.mdexists
tools/archon-cli/exists (--with=cli was passed)
package.jsonbyte-identical to fixture
tsconfig.jsonbyte-identical to fixture
src/todo.tsbyte-identical to fixture
src/todo.test.tsbyte-identical to fixture
.archon/drift.md install rowsexactly 1

The byte-identity check is enforced by sha256_equals against the canonical fixture sha. If the fixture content ever changes, regenerate the sha values from git hash-object and update the spec block.

Demo recordings

Will be replaced by docs/public/videos/install-existing-project.mp4 once recorded. See videos/README for upload conventions.
Will be replaced by docs/public/asciinema/install-existing-project.cast embedded via the asciinema-player web component. See asciinema/README for the recording command.

Run records

bash
node scripts/sandbox-run.mjs --only=install-existing-project
Started (UTC)ManifestRunnerResultDurationNotesRecord
2026-06-08 08:17:11 UTCv0.1.0cli✅ passing333 msJSON
2026-06-07 07:10:16 UTCv0.1.0cli✅ passing337 msJSON
2026-06-06 06:34:40 UTCv0.1.0cli✅ passing346 msJSON
2026-06-05 07:14:06 UTCv0.1.0cli✅ passing334 msJSON
2026-06-04 07:56:43 UTCv0.1.0cli✅ passing385 msJSON
2026-06-03 08:24:17 UTCv0.1.0cli✅ passing387 msJSON
2026-06-02 08:00:51 UTCv0.1.0cli✅ passing343 msJSON
2026-06-01 08:40:45 UTCv0.1.0cli✅ passing349 msJSON
2026-05-31 07:02:23 UTCv0.1.0cli✅ passing378 msJSON
2026-05-30 06:27:52 UTCv0.1.0cli✅ passing343 msJSON
2026-05-29 06:59:39 UTCv0.1.0cli✅ passing371 msJSON
2026-05-28 06:59:33 UTCv0.1.0cli✅ passing354 msJSON
2026-05-27 07:09:41 UTCv0.1.0cli✅ passing353 msJSON
2026-05-26 06:52:08 UTCv0.1.0cli✅ passing321 msJSON
2026-05-25 07:20:21 UTCv0.1.0cli✅ passing352 msJSON
2026-05-24 06:41:52 UTCv0.1.0cli✅ passing340 msJSON
2026-05-23 06:16:49 UTCv0.1.0cli✅ passing342 msJSON
2026-05-22 06:54:17 UTCv0.1.0cli✅ passing344 msJSON
2026-05-21 06:58:03 UTCv0.1.0cli✅ passing333 msJSON
2026-05-20 06:53:37 UTCv0.1.0cli✅ passing348 msJSON
2026-05-19 06:53:17 UTCv0.1.0cli✅ passing341 msJSON
2026-05-18 07:01:46 UTCv0.1.0cli✅ passing360 msJSON
2026-05-17 06:27:35 UTCv0.1.0cli✅ passing343 msJSON
2026-05-16 06:04:39 UTCv0.1.0cli✅ passing337 msJSON
2026-05-15 06:37:58 UTCv0.1.0cli✅ passing346 msJSON
2026-05-14 06:28:56 UTCv0.1.0cli✅ passing381 msJSON
2026-05-13 06:30:24 UTCv0.1.0cli✅ passing313 msJSON
2026-05-12 06:19:00 UTCv0.1.0cli✅ passing345 msJSON
2026-05-11 06:45:34 UTCv0.1.0cli✅ passing310 msJSON
2026-05-10 06:16:44 UTCv0.1.0cli✅ passing369 msJSON
2026-05-09 05:52:37 UTCv0.1.0cli✅ passing400 msJSON
2026-05-08 05:33:35 UTCv0.1.0cli✅ passing363 msJSON
2026-05-07 11:01:02 UTCv0.1.0cli✅ passing323 msJSON
2026-05-07 09:54:53 UTCv0.1.0cli✅ passing338 msJSON
2026-05-07 09:45:11 UTCv0.1.0cli✅ passing555 msJSON
2026-05-07 06:15:44 UTCv0.1.0cli✅ passing282 msJSON
2026-05-06 11:45:36 UTCv0.1.0cli✅ passing332 msJSON
2026-05-06 11:44:05 UTCv0.1.0cli✅ passing357 msJSON
2026-05-06 11:19:25 UTCv0.1.0cli✅ passing364 msJSON

Known limitations

  • Only checks four host files for byte-identity. A larger fixture (e.g. a real Vite + React skeleton) would need a directory-tree hash — out of scope until an adopter actually reports a mutation bug on a richer tree.
  • Does not run npm install && npm run validate post-install. That belongs to scenario 01 (install-cursor-node) which also verifies the validation chain.

Cross-references

json
{
  "runnable": "cli",
  "fixture": "fixtures/sandbox-node-ts",
  "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/soul.md" },
    { "file_exists": ".cursor/commands/archon.md" },
    { "dir_exists": "tools/archon-cli" },
    { "file_exists": "package.json" },
    { "file_exists": "src/todo.ts" },
    { "file_exists": "src/todo.test.ts" },
    { "cmd_zero": ["node", "__sb-check.cjs", "pkg-name-equals", "acme-todos"] },
    { "cmd_zero": ["node", "__sb-check.cjs", "file-includes", "src/todo.ts", "Todo"] },
    { "cmd_zero": ["node", "__sb-check.cjs", "drift-install-count", "1"] },
    { "cmd_zero": ["python3", "scripts/archon-check.py", "--root", "."] }
  ],
  "notes": "Asserts install is non-invasive on a real Node+TS project: package.json identity field unchanged, source file content preserved, exactly one install row in drift."
}

Released under the Apache-2.0 License.