Skip to content

10 · sync-modified

本场景验证什么

当某个 canonical 文件被手工编辑后,archon sync 能正确检测到漂移(drift), 并精确地报告(具体哪个文件、期望 sha256 vs 实际 sha256)。这是 场景 09 sync-clean 的失败模式对照。

必须同时满足两点:

  1. 报告将被修改的文件标记为漂移。
  2. 被修改的文件不会被自动修正 —— sync 始终保持只读。 用户必须运行 archon update(或手动还原文件)来解决漂移。

测试环境

Fixture场景 01 的产物 + 一处刻意的手工编辑
IDECursor
被测 manifest 版本v0.1.0
操作系统同场景 01

前置条件

  1. 场景 01 ✅。
  2. 注入编辑前 git status 干净。

步骤

text
1. Inject a deliberate hand-edit into a canonical file. Pick something
   short and unmistakable, e.g.:
     echo "" >> .cursor/commands/archon.md
     echo "<!-- DRIFT INJECTED FOR TEST 10 -->" >> .cursor/commands/archon.md
2. Confirm the file's sha256 has changed:
     sha256sum .cursor/commands/archon.md
3. In Cursor, paste exactly:
     hi archon, are you healthy?
4. Read the report — should call out
     .cursor/commands/archon.md   FAIL  expected <sha-A>  got <sha-B>
5. Confirm sync did not modify any file:
     git status
   must show ONLY the file you injected (modified), nothing extra.
6. Repair drift via update:
     hi archon, update yourself
   confirm the planned change includes restoring .cursor/commands/archon.md
   and accept.
7. Re-run sync (step 3) — should now report N/N OK again.

预期结果

检查项预期
Sync(步骤 3)打印被修改文件,标注 FAIL 与 sha 不匹配
Sync 以非零状态退出(或以其他方式发出"detected drift"信号 —— 与协议页面一致)
Sync 不会修改任何文件(步骤 5)
Update(步骤 6)还原 canonical 内容
重新运行 sync(步骤 7)N/N OK
.archon/drift.md 行数全过程不变(canonical 文件的 sync/update 在 runtime-ledger 语义下不算一次 drift 事件)

演示记录

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

运行记录

下表由 sandbox runner (scripts/sandbox-run.mjs) 写入 docs/testing/sandbox/runs/sync-modified/ 下的 JSON 实时渲染。要新增一行,运行

bash
node scripts/sandbox-run.mjs --only=sync-modified
Started (UTC)ManifestRunnerResultDurationNotesRecord
2026-06-08 08:17:13 UTCv0.1.0cli✅ passing359 msJSON
2026-06-07 07:10:18 UTCv0.1.0cli✅ passing454 msJSON
2026-06-06 06:34:42 UTCv0.1.0cli✅ passing354 msJSON
2026-06-05 07:14:08 UTCv0.1.0cli✅ passing340 msJSON
2026-06-04 07:56:45 UTCv0.1.0cli✅ passing376 msJSON
2026-06-03 08:24:19 UTCv0.1.0cli✅ passing368 msJSON
2026-06-02 08:00:53 UTCv0.1.0cli✅ passing365 msJSON
2026-06-01 08:40:47 UTCv0.1.0cli✅ passing371 msJSON
2026-05-31 07:02:25 UTCv0.1.0cli✅ passing354 msJSON
2026-05-30 06:27:55 UTCv0.1.0cli✅ passing345 msJSON
2026-05-29 06:59:41 UTCv0.1.0cli✅ passing350 msJSON
2026-05-28 06:59:35 UTCv0.1.0cli✅ passing347 msJSON
2026-05-27 07:09:43 UTCv0.1.0cli✅ passing368 msJSON
2026-05-26 06:52:10 UTCv0.1.0cli✅ passing355 msJSON
2026-05-25 07:20:23 UTCv0.1.0cli✅ passing354 msJSON
2026-05-24 06:41:54 UTCv0.1.0cli✅ passing357 msJSON
2026-05-23 06:16:51 UTCv0.1.0cli✅ passing349 msJSON
2026-05-22 06:54:19 UTCv0.1.0cli✅ passing355 msJSON
2026-05-21 06:58:05 UTCv0.1.0cli✅ passing355 msJSON
2026-05-20 06:53:39 UTCv0.1.0cli✅ passing353 msJSON
2026-05-19 06:53:19 UTCv0.1.0cli✅ passing366 msJSON
2026-05-18 07:01:48 UTCv0.1.0cli✅ passing370 msJSON
2026-05-17 06:27:38 UTCv0.1.0cli✅ passing357 msJSON
2026-05-16 06:04:42 UTCv0.1.0cli✅ passing344 msJSON
2026-05-15 06:38:01 UTCv0.1.0cli✅ passing358 msJSON
2026-05-14 06:28:58 UTCv0.1.0cli✅ passing355 msJSON
2026-05-13 06:30:26 UTCv0.1.0cli✅ passing315 msJSON
2026-05-12 06:19:02 UTCv0.1.0cli✅ passing363 msJSON
2026-05-11 06:45:36 UTCv0.1.0cli✅ passing322 msJSON
2026-05-10 06:16:46 UTCv0.1.0cli✅ passing375 msJSON
2026-05-09 05:52:41 UTCv0.1.0cli✅ passing367 msJSON
2026-05-08 05:33:37 UTCv0.1.0cli✅ passing364 msJSON
2026-05-07 11:01:04 UTCv0.1.0cli✅ passing360 msJSON
2026-05-07 09:54:55 UTCv0.1.0cli✅ passing359 msJSON
2026-05-07 09:45:14 UTCv0.1.0cli✅ passing476 msJSON
2026-05-07 06:15:46 UTCv0.1.0cli✅ passing352 msJSON
2026-05-06 13:05:54 UTCv0.1.0cli✅ passing399 msJSON
2026-05-06 10:24:36 UTCv0.1.0cli✅ passing386 msJSON
2026-05-06 06:10:25 UTCv0.1.0cli✅ passing416 msJSON
2026-05-06 00:55:44 UTCv0.1.0cli✅ passing362 msJSON
2026-05-06 00:40:10 UTCv0.1.0cli✅ passing386 msJSON
2026-05-05 15:00:35 UTCv0.1.0cli✅ passing343 msJSON
2026-05-05 14:55:19 UTCv0.1.0cli✅ passing400 msJSON
2026-05-05 14:22:54 UTCv0.1.0cli✅ passing366 msJSON
2026-05-05 14:04:54 UTCv0.1.0cli✅ passing403 msJSON
2026-05-05 14:00:01 UTCv0.1.0cli✅ passing393 msJSON
2026-05-05 13:55:05 UTCv0.1.0cli❌ failing439 msprereq failed: tamper soul.md exit 1JSON

已知限制

  • 本场景只在一个 binding-root 文件 (.cursor/commands/archon.md)上注入漂移。更完整的矩阵还应在 .archon/soul.md.archon/manifest.md 等文件上注入漂移, 以证明报告对 core 目录同等覆盖。按优先级补充为后续场景。
  • 不测试 runtime ledger 被手工编辑的情况 (.archon/drift.md)。这些文件由 project 持有,sync 绝不能 把它们报告为漂移 —— 那是一个独立的负向测试 (sync-ignores-runtime-ledgers)。

交叉引用

json
{
  "runnable": "cli",
  "fixture": "fixtures/sandbox-node-ts",
  "ide_platform": "cursor",
  "prerequisites": [
    {
      "name": "archon install",
      "cli": "install",
      "flags": [
        "--with=cli"
      ]
    },
    {
      "name": "tamper soul.md",
      "append_to_file": {
        "path": ".archon/soul.md",
        "content": "\n# tampered by sandbox runner\n"
      }
    }
  ],
  "steps": [
    {
      "name": "archon sync (expected to flag drift)",
      "cli": "sync",
      "flags": [
        "--json"
      ],
      "allow_nonzero": true
    }
  ],
  "assertions": [
    {
      "file_exists": ".archon/soul.md"
    },
    {
      "file_contains": {
        "path": ".archon/soul.md",
        "substr": "tampered by sandbox runner"
      }
    }
  ],
  "notes": "Asserts that tampering is preserved on disk and `archon sync` runs without crashing. A future enhancement could capture the JSON drift report and assert specific drift counts."
}

依据 Apache-2.0 许可证发布。