@event4u/agent-config 3.0.0 → 3.1.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.
Files changed (207) hide show
  1. package/.agent-src/commands/install-via-agent.md +129 -0
  2. package/.agent-src/commands/video/from-script.md +1 -1
  3. package/.agent-src/commands/video.md +1 -1
  4. package/.agent-src/contexts/execution/cheap-question-mechanics.md +81 -0
  5. package/.agent-src/rules/caveman-speak.md +2 -2
  6. package/.agent-src/rules/context-hygiene.md +36 -0
  7. package/.agent-src/rules/engineering-safety-floor.md +102 -0
  8. package/.agent-src/rules/finance-safety-floor.md +114 -0
  9. package/.agent-src/rules/git-history-discipline.md +1 -1
  10. package/.agent-src/rules/no-cheap-questions.md +34 -32
  11. package/.agent-src/rules/provider-lifecycle-discipline.md +4 -4
  12. package/.agent-src/rules/strategy-safety-floor.md +114 -0
  13. package/.agent-src/skills/agents-md-thin-root/SKILL.md +15 -9
  14. package/.agent-src/skills/async-python-patterns/SKILL.md +1 -1
  15. package/.agent-src/skills/project-analysis-node-express/SKILL.md +1 -1
  16. package/.agent-src/skills/readme-reviewer/SKILL.md +52 -3
  17. package/.agent-src/skills/readme-writing/SKILL.md +52 -4
  18. package/.agent-src/skills/readme-writing-package/SKILL.md +48 -5
  19. package/.agent-src/skills/systematic-debugging/SKILL.md +41 -0
  20. package/.agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  21. package/.agent-src/templates/hooks/pre-commit-frontmatter +66 -0
  22. package/.agent-src/templates/hooks/pre-commit-roadmap-progress +78 -39
  23. package/.agent-src/templates/scripts/work_engine/_lib/agent_settings.py +4 -1
  24. package/.agent-src/templates/scripts/work_engine/orchestration.py +25 -11
  25. package/.claude-plugin/marketplace.json +2 -1
  26. package/AGENTS.md +10 -8
  27. package/CHANGELOG.md +223 -125
  28. package/README.md +165 -553
  29. package/config/agent-settings.template.yml +0 -7
  30. package/config/discovery/packs.yml +20 -0
  31. package/config/discovery/unassigned-artefacts.yml +2 -0
  32. package/config/gitignore-block.txt +19 -3
  33. package/dist/cli/commands/uiServe.js +13 -4
  34. package/dist/cli/commands/uiServe.js.map +1 -1
  35. package/dist/cli/registry.js +2 -0
  36. package/dist/cli/registry.js.map +1 -1
  37. package/dist/discovery/deprecation-report.md +7 -0
  38. package/dist/discovery/discovery-manifest.json +2107 -1409
  39. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  40. package/dist/discovery/discovery-manifest.summary.md +9 -9
  41. package/dist/discovery/orphan-report.md +10 -0
  42. package/dist/discovery/packs.json +1002 -0
  43. package/dist/discovery/trust-report.md +26 -0
  44. package/dist/discovery/workspaces.json +705 -0
  45. package/dist/mcp/registry-manifest.json +4 -4
  46. package/dist/router.json +1623 -0
  47. package/dist/server/app.js +11 -3
  48. package/dist/server/app.js.map +1 -1
  49. package/dist/server/io/atomicMultiWrite.js +3 -1
  50. package/dist/server/io/atomicMultiWrite.js.map +1 -1
  51. package/dist/server/io/yamlIO.js +22 -0
  52. package/dist/server/io/yamlIO.js.map +1 -1
  53. package/dist/server/routes/ping.js +8 -0
  54. package/dist/server/routes/ping.js.map +1 -1
  55. package/dist/server/routes/schema.js +2 -2
  56. package/dist/server/routes/schema.js.map +1 -1
  57. package/dist/server/routes/settings.js +104 -23
  58. package/dist/server/routes/settings.js.map +1 -1
  59. package/dist/server/routes/userMd.js +37 -27
  60. package/dist/server/routes/userMd.js.map +1 -1
  61. package/dist/server/routes/wizard.js +256 -20
  62. package/dist/server/routes/wizard.js.map +1 -1
  63. package/dist/server/schemas/settings.js +0 -1
  64. package/dist/server/schemas/settings.js.map +1 -1
  65. package/dist/server/token.js +10 -3
  66. package/dist/server/token.js.map +1 -1
  67. package/dist/server/writeRoot.js +28 -11
  68. package/dist/server/writeRoot.js.map +1 -1
  69. package/dist/server/writeRoot.test.js +22 -4
  70. package/dist/server/writeRoot.test.js.map +1 -1
  71. package/dist/shared/userMd/formAdapter.js +29 -51
  72. package/dist/shared/userMd/formAdapter.js.map +1 -1
  73. package/dist/shared/userMd/schema.js +32 -104
  74. package/dist/shared/userMd/schema.js.map +1 -1
  75. package/dist/shared/userMd/utils.js +64 -50
  76. package/dist/shared/userMd/utils.js.map +1 -1
  77. package/dist/ui/assets/index-D-DY1ywI.js +35 -0
  78. package/dist/ui/assets/index-D-DY1ywI.js.map +1 -0
  79. package/dist/ui/index.html +1 -1
  80. package/docs/adrs/router/0001-three-tier-routing.md +5 -5
  81. package/docs/adrs/smoke/0001-per-tier-smoke-scripts.md +1 -1
  82. package/docs/architecture.md +3 -3
  83. package/docs/archive/CHANGELOG-pre-3.1.0.md +167 -0
  84. package/docs/catalog.md +30 -26
  85. package/docs/contracts/CHANGELOG-conventions.md +1 -1
  86. package/docs/contracts/agent-user-schema.md +6 -9
  87. package/docs/contracts/consumer-bridge.md +79 -0
  88. package/docs/contracts/discovery-manifest.md +209 -0
  89. package/docs/contracts/discovery-manifest.schema.json +77 -4
  90. package/docs/contracts/explain-trace.schema.json +1 -1
  91. package/docs/contracts/file-ownership-matrix.json +197 -13
  92. package/docs/contracts/frontmatter-contract.md +140 -0
  93. package/docs/contracts/gui-wizard.md +223 -0
  94. package/docs/contracts/installer-agent-mode.md +137 -0
  95. package/docs/contracts/kernel-membership.md +1 -1
  96. package/docs/contracts/mcp-tool-inventory.md +9 -9
  97. package/docs/contracts/namespace.md +6 -6
  98. package/docs/contracts/provider-lifecycle.md +5 -5
  99. package/docs/contracts/rule-router.md +4 -4
  100. package/docs/contracts/settings-api.md +53 -6
  101. package/docs/contracts/smoke-contracts.md +3 -3
  102. package/docs/contracts/trust-and-safety.md +144 -0
  103. package/docs/customization.md +2 -2
  104. package/docs/decisions/ADR-007-agent-discovery-scopes.md +12 -0
  105. package/docs/decisions/ADR-013-discovery-frontmatter-contract.md +24 -0
  106. package/docs/decisions/ADR-015-discovery-manifest-contract.md +146 -0
  107. package/docs/decisions/ADR-016-installer-architecture.md +189 -0
  108. package/docs/decisions/ADR-017-monorepo-physical-layout.md +261 -0
  109. package/docs/decisions/ADR-018-trust-and-safety-layer.md +159 -0
  110. package/docs/decisions/ADR-019-router-json-dist-location.md +124 -0
  111. package/docs/decisions/ADR-020-global-only-consumer-scope.md +123 -0
  112. package/docs/decisions/ADR-021-deployment-shape.md +153 -0
  113. package/docs/decisions/INDEX.md +7 -0
  114. package/docs/deploy/connector-setup.md +129 -0
  115. package/docs/deploy/env-vars.md +70 -0
  116. package/docs/deploy/policy-cookbook.md +130 -0
  117. package/docs/deploy/quickstart.md +112 -0
  118. package/docs/distribution/public-install-smoke.md +68 -0
  119. package/docs/distribution/registries.md +55 -0
  120. package/docs/distribution/telemetry-privacy.md +128 -0
  121. package/docs/distribution/telemetry-schema.md +174 -0
  122. package/docs/featured-skills.md +95 -0
  123. package/docs/getting-started-by-role.md +19 -1
  124. package/docs/getting-started.md +2 -2
  125. package/docs/guidelines/agent-infra/installed-tools-manifest.md +11 -8
  126. package/docs/guidelines/docs/readme-size-and-splitting.md +53 -1
  127. package/docs/installation.md +27 -14
  128. package/docs/maintainers/dev-mode.md +105 -0
  129. package/docs/setup/per-ide/claude-desktop.md +3 -2
  130. package/docs/wizard.md +39 -4
  131. package/package.json +18 -1
  132. package/scripts/__pycache__/validate_frontmatter.cpython-312.pyc +0 -0
  133. package/scripts/_cli/cmd_doctor.py +150 -2
  134. package/scripts/_cli/cmd_explain.py +2 -1
  135. package/scripts/_cli/cmd_migrate_to_global.py +415 -0
  136. package/scripts/_cli/cmd_settings_migrate.py +146 -0
  137. package/scripts/_cli/explain_last/route.py +2 -1
  138. package/scripts/_dispatch.bash +36 -3
  139. package/scripts/_lib/__pycache__/__init__.cpython-312.pyc +0 -0
  140. package/scripts/_lib/__pycache__/agent_src.cpython-312.pyc +0 -0
  141. package/scripts/_lib/agent_settings.py +4 -1
  142. package/scripts/_lib/agent_src.py +157 -0
  143. package/scripts/agent-config +17 -6
  144. package/scripts/audit_skill_descriptions.py +18 -6
  145. package/scripts/build_discovery_manifest.py +373 -17
  146. package/scripts/check_artefact_checksums.py +104 -0
  147. package/scripts/check_cluster_patterns.py +20 -4
  148. package/scripts/check_command_count_messaging.py +33 -14
  149. package/scripts/check_council_references.py +43 -4
  150. package/scripts/check_overlay_cascade_subdirs.py +7 -3
  151. package/scripts/check_references.py +5 -2
  152. package/scripts/check_reply_consistency.py +32 -9
  153. package/scripts/check_template_pin_drift.py +24 -7
  154. package/scripts/check_token_optimizer_freshness.py +18 -3
  155. package/scripts/compile_router.py +34 -2
  156. package/scripts/compress.py +162 -44
  157. package/scripts/config/presets.py +19 -1
  158. package/scripts/config/profiles.py +16 -1
  159. package/scripts/discovery_stats.py +70 -0
  160. package/scripts/expected_perms.json +47 -0
  161. package/scripts/generate_index.py +78 -46
  162. package/scripts/generate_ownership_matrix.py +98 -43
  163. package/scripts/generate_pack_manifests.py +183 -0
  164. package/scripts/install +18 -1
  165. package/scripts/install.py +934 -59
  166. package/scripts/install.sh +27 -9
  167. package/scripts/lint_agents_layout.py +93 -13
  168. package/scripts/lint_agents_md.py +1 -1
  169. package/scripts/lint_archived_skills.py +32 -16
  170. package/scripts/lint_bench_corpus.py +14 -2
  171. package/scripts/lint_command_tiers.py +15 -2
  172. package/scripts/lint_featured_skills.py +139 -0
  173. package/scripts/lint_framework_leakage.py +33 -6
  174. package/scripts/lint_global_paths.py +147 -0
  175. package/scripts/lint_orchestration_dsl.py +6 -3
  176. package/scripts/lint_pack_boundaries.py +147 -0
  177. package/scripts/lint_pack_first_win.py +103 -0
  178. package/scripts/lint_readme_jargon.py +131 -0
  179. package/scripts/lint_readme_size.py +33 -0
  180. package/scripts/lint_rule_interactions.py +23 -5
  181. package/scripts/lint_rule_tiers.py +12 -3
  182. package/scripts/lint_trust_coherence.py +212 -0
  183. package/scripts/measure_rule_budget.py +22 -4
  184. package/scripts/move_artefact.py +143 -0
  185. package/scripts/new_skill.py +148 -0
  186. package/scripts/plan_physical_move.py +353 -0
  187. package/scripts/refine_ticket_detect.py +30 -7
  188. package/scripts/schemas/command.schema.json +4 -0
  189. package/scripts/skill_linter.py +248 -118
  190. package/scripts/skill_trigger_eval.py +28 -8
  191. package/scripts/smoke/kernel.sh +1 -1
  192. package/scripts/smoke/router.sh +24 -5
  193. package/scripts/smoke/skills.sh +15 -7
  194. package/scripts/smoke_quickstart.py +11 -2
  195. package/scripts/snapshot_agent_outputs.py +144 -0
  196. package/scripts/update_counts.py +45 -17
  197. package/scripts/validate_decision_engine.py +9 -1
  198. package/scripts/validate_discovery_manifest.py +94 -0
  199. package/scripts/validate_frontmatter.py +39 -20
  200. package/scripts/verify_physical_move.py +185 -0
  201. package/templates/agent-user.md +0 -1
  202. package/templates/agent-user.yml +21 -0
  203. package/templates/minimal/agents-overrides-readme.md +46 -0
  204. package/templates/minimal/overrides-gitkeep +2 -0
  205. package/dist/ui/assets/index-BTRcKDlB.js +0 -39
  206. package/dist/ui/assets/index-BTRcKDlB.js.map +0 -1
  207. package/templates/minimal/agents-gitkeep +0 -2
@@ -0,0 +1,146 @@
1
+ ---
2
+ adr: 015
3
+ status: accepted
4
+ date: 2026-05-21
5
+ decision: discovery-manifest-contract
6
+ supersedes: —
7
+ superseded_by: —
8
+ phase: v2.x · monorepo-phase-2-virtual-packs-discovery Phase 1
9
+ type: prospective
10
+ ---
11
+
12
+ # ADR-015 — Discovery Manifest Contract
13
+
14
+ ## Status
15
+
16
+ **Accepted** · 2026-05-21 · in-session AI Council pass. Folds the Phase-2
17
+ intake invariant (`agents/tmp/refactor-package.txt`, last paragraph) and
18
+ the additive-vs-rewrite call into the schema. Phase-1 prerequisite for
19
+ [`monorepo-phase-2-virtual-packs-discovery`](../../agents/roadmaps/monorepo-phase-2-virtual-packs-discovery.md).
20
+
21
+ ## Context
22
+
23
+ [ADR-013](ADR-013-discovery-frontmatter-contract.md) locked the five
24
+ per-artefact frontmatter keys. The release pipeline now needs a single
25
+ JSON contract — `dist/discovery/discovery-manifest.json` — that the
26
+ TypeScript installer (Phase 3), the browser wizard (Phase 6), the docs
27
+ site, and any third-party consumer read instead of walking the source
28
+ tree. The invariant from the founder intake:
29
+
30
+ > Beim Erstellen eines Releases müssen alle Skills, etc. nach Workspace
31
+ > und Pack untersucht werden, so dass das für den Installer gespeichert
32
+ > wird und zur Verfügung steht. Es soll keine manuelle Package &
33
+ > Workspace Liste gepflegt werden.
34
+
35
+ **No manual list. Ever.** The pack and workspace shape grows by stamping
36
+ frontmatter, not by editing a list.
37
+
38
+ A v1 manifest schema already lives at
39
+ [`docs/contracts/discovery-manifest.schema.json`](../contracts/discovery-manifest.schema.json)
40
+ (carried over from the archived R3 discovery roadmap). The Phase-2
41
+ roadmap §"Manifest shape" sketched an *ideal* shape that differs from
42
+ the on-disk schema in several places (per-artefact `checksum`,
43
+ optional `requires`, a `stats` block). The decision is whether to
44
+ rewrite the schema or extend it additively.
45
+
46
+ ## Decision
47
+
48
+ **Extend the v1 schema additively.** Three changes, no removals, no
49
+ field renames, version stays `1`:
50
+
51
+ 1. **`artefact.checksum`** — `sha256:<hex>`, REQUIRED. Computed over the
52
+ on-disk file bytes after frontmatter normalization (sorted keys,
53
+ trailing newline). Drift detector for the Phase-3 installer.
54
+ 2. **`artefact.requires`** — `array<pack_id>`, OPTIONAL. Pack-level
55
+ dependency edges resolved by the installer; empty/absent means the
56
+ artefact has no extra pack requirements beyond its own `packs[]`.
57
+ 3. **`stats`** — REQUIRED top-level object. `total_artefacts`,
58
+ `by_category`, `by_lifecycle`, `by_trust_level`. Cheap sanity surface
59
+ for `task discovery-stats` + downstream dashboards.
60
+
61
+ The Phase-2 roadmap's example also mentioned `id`, `owner`, and
62
+ `install.managed`. **Not adopted.** The path is the canonical artefact
63
+ identity (matches ADR-013), ownership is already encoded in
64
+ `workspaces[]` + `packs[]`, and `install.managed` adds a third
65
+ install-axis without a current consumer. Re-evaluate in Phase 5.
66
+
67
+ ### Source-of-truth tree
68
+
69
+ The generator walks `.agent-src.uncompressed/`, **not** `.agent-src/`.
70
+ The Phase-2 roadmap text §Phase 2 says "the compressed canonical tree"
71
+ — that is a documentation slip. `augment-source-of-truth` rule states
72
+ that uncompressed is canonical; the compressed tree is a build output
73
+ and may be regenerated. Manifest pipelines that read build outputs are
74
+ fragile to bootstrap order.
75
+
76
+ ### No git in the manifest
77
+
78
+ The roadmap example included `source_commit`. **Not adopted.** The
79
+ existing `scanner_version` (first 12 hex of `sha256(build_discovery_manifest.py)`)
80
+ already pins generator identity. Embedding `git rev-parse HEAD` breaks
81
+ hermetic determinism tests in environments without a git checkout
82
+ (CI shallow clones, vendor tarballs). A consumer that needs the commit
83
+ can pin from the surrounding release artefact (changelog, tag).
84
+
85
+ ## Consequences
86
+
87
+ ### Positive
88
+
89
+ - Existing consumers (the Phase-1 linter, the round-trip test, the
90
+ `lint_discovery_manifest.py` validator) keep working — top-level
91
+ `version` stays `1`, all v1 fields stay required.
92
+ - Per-artefact `checksum` makes the Phase-3 installer drift-detection
93
+ trivial — one hash compare per file.
94
+ - `requires` is opt-in: artefacts that don't need cross-pack deps cost
95
+ zero extra bytes.
96
+ - Stats are computed from the artefact list — no second walk of the
97
+ tree, no risk of stats/list desync.
98
+
99
+ ### Negative
100
+
101
+ - Every artefact entry grows by ~80 bytes (the checksum). For ~420
102
+ artefacts, the manifest grows ~33 KB. Acceptable.
103
+ - The first build after this ADR rewrites every artefact entry; the
104
+ diff is large. Reviewed once and committed.
105
+
106
+ ### Neutral
107
+
108
+ - `version` stays `1`. A future breaking change (rename `packs` to
109
+ `pack_ids`, drop `unassigned`, etc.) bumps to `2`. This ADR sets the
110
+ precedent that **additive** changes do not bump.
111
+
112
+ ## Determinism contract
113
+
114
+ Two builds of the same source tree MUST produce byte-identical JSON
115
+ when `generated_at` is normalized. Specifically:
116
+
117
+ - All arrays sorted (`artefacts` by `path`, `workspaces`/`packs` in
118
+ vocabulary order, `requires`/`workspaces[]`/`packs[]` per-entry sorted).
119
+ - JSON serialized with `sort_keys=True`, `indent=2`, trailing newline.
120
+ - The global `checksum` covers the manifest minus `generated_at` and
121
+ itself (zeroed during hash input).
122
+ - Per-artefact `checksum` covers the file content with frontmatter
123
+ normalized (sorted keys, trailing newline, no trailing whitespace).
124
+
125
+ ## Failure modes guarded against
126
+
127
+ - **Manual drift** — no pack list to hand-edit; new packs/workspaces
128
+ enter via frontmatter stamps on artefacts.
129
+ - **Stale manifest in release** — Phase 3 ships `task validate-discovery-manifest`
130
+ which re-builds to a tempdir and `diff`s against the committed file.
131
+ - **Checksum collision with content edits** — per-artefact `checksum`
132
+ surfaces any file mutation; the installer can refuse to overwrite a
133
+ user-modified artefact (Phase 3).
134
+ - **`version: 1` reused for breaking changes** — this ADR explicitly
135
+ scopes `version: 1` to additive evolutions; breaking → bump + new ADR.
136
+
137
+ ## References
138
+
139
+ - [ADR-013](ADR-013-discovery-frontmatter-contract.md) — frontmatter
140
+ contract (the input side of this manifest).
141
+ - [`docs/contracts/discovery-manifest.schema.json`](../contracts/discovery-manifest.schema.json)
142
+ — the locked schema.
143
+ - [`docs/contracts/discovery-manifest.md`](../contracts/discovery-manifest.md)
144
+ — worked examples + consumer guide.
145
+ - [`agents/roadmaps/monorepo-phase-2-virtual-packs-discovery.md`](../../agents/roadmaps/monorepo-phase-2-virtual-packs-discovery.md)
146
+ — the implementing roadmap.
@@ -0,0 +1,189 @@
1
+ ---
2
+ adr: 016
3
+ status: accepted
4
+ date: 2026-05-21
5
+ decision: installer-architecture
6
+ supersedes: —
7
+ superseded_by: —
8
+ phase: v2.x · monorepo-phase-3-typescript-installer
9
+ type: prospective
10
+ ---
11
+
12
+ # ADR-016 — TypeScript Installer Architecture
13
+
14
+ ## Status
15
+
16
+ **Accepted** · 2026-05-21 · external AI Council pass (`claude-sonnet-4-5`
17
+ + `gpt-4o`, 2 rounds, `design` lens, actual cost $0.13) on
18
+ [`agents/roadmaps/monorepo-phase-3-typescript-installer.md`](../../agents/roadmaps/monorepo-phase-3-typescript-installer.md).
19
+ Council issued **conditional approval** with five blockers; this ADR
20
+ folds each blocker into the design before Phase 3.1 starts.
21
+
22
+ Session: [`agents/runtime/council/responses/phase-3-installer-design.json`](../../agents/runtime/council/responses/phase-3-installer-design.json) <!-- council-ref-allowed: ADR decision-trace -->
23
+
24
+ ## Context
25
+
26
+ Phase 3 of the monorepo plan replaces the shell-based `install.sh` with
27
+ a TypeScript Core Installer that drives interactive TUI, non-interactive
28
+ CI flags, and a structured **agent-mode** JSON protocol over stdio. It
29
+ consumes [`dist/discovery/discovery-manifest.json`](../../dist/discovery/discovery-manifest.json)
30
+ (locked by [ADR-015](ADR-015-discovery-manifest-contract.md)) and
31
+ writes managed files into the consumer's `.augment/` and `.agent-src/`,
32
+ tracked in `agents/agent-config.lock.yml`.
33
+
34
+ The council raised five architectural risks that, left unaddressed,
35
+ would force post-merge rework in Phase 5 (trust) and Phase 6 (browser
36
+ wizard). This ADR locks the resolution of each.
37
+
38
+ ## Decision
39
+
40
+ ### 1. Lockfile schema v1 records provenance, not just paths
41
+
42
+ ```yaml
43
+ schema_version: 1
44
+ agent_config_version: 2.0.0
45
+ manifest_sha256: <hex> # sha256 of the consumed discovery-manifest.json
46
+ generated_at: 2026-05-21T12:00:00Z
47
+ workspaces: [engineering, governance]
48
+ packs:
49
+ - id: pack.laravel
50
+ version: 2.0.0
51
+ auto_selected: false
52
+ required_by: []
53
+ files:
54
+ - path: .augment/skills/laravel/SKILL.md
55
+ pack: pack.laravel
56
+ pack_version: 2.0.0
57
+ sha256: <hex>
58
+ manifest_sha256: <hex> # which manifest sourced this file
59
+ managed: true
60
+ ```
61
+
62
+ `manifest_sha256` is per-file (not just per-lockfile) so Phase 5 trust
63
+ gates can answer "which manifest claimed this artefact was safe?"
64
+ without needing a lockfile rewrite.
65
+
66
+ ### 2. Overrides live in a separate file the installer never writes
67
+
68
+ ```yaml
69
+ # agents/agent-config.overrides.yml — user-managed, installer reads but never writes
70
+ schema_version: 1
71
+ overrides:
72
+ - path: agents/overrides/skills/laravel/SKILL.md
73
+ shadows: .augment/skills/laravel/SKILL.md
74
+ reason: "Custom prompt for our team's Laravel style"
75
+ ```
76
+
77
+ The lockfile (`.lock.yml`) is **append-only by the installer**;
78
+ overrides (`.overrides.yml`) are **read-only to the installer**.
79
+ `validate` cross-references the two. This resolves the source-of-truth
80
+ ambiguity the council flagged on `managed: false`.
81
+
82
+ ### 3. Merge decision table replaces "three-way merge" handwaving
83
+
84
+ | Disk | Lock | Upstream | Override? | Action |
85
+ |---------|------|----------|-----------|--------------------------------------|
86
+ | A | A | A | — | no-op |
87
+ | A | A | B | no | write B, update lock |
88
+ | A | A | B | yes | write B to `.augment/`, leave override |
89
+ | A | A | absent | — | offer prune |
90
+ | X (drift) | A | A | — | warn, suggest `validate --fix` |
91
+ | X (drift) | A | B | no | error: manual merge required |
92
+ | X (drift) | A | B | yes | error: override may be stale |
93
+ | absent | A | B | — | write B (recreate) |
94
+
95
+ Encoded in `src/sync/merge-strategy.ts`; covered by
96
+ `tests/sync-algorithm.test.ts` with one case per row.
97
+
98
+ ### 4. Agent mode: strict question-ID validation (stateless)
99
+
100
+ Of the three options the council surfaced (session token, nonce,
101
+ strict sequencing) we adopt **strict sequencing**: the CLI tracks the
102
+ current question id in the manifest of expected answers; any
103
+ `--answer` that does not match the current question id returns:
104
+
105
+ ```json
106
+ { "status": "error", "protocol_version": 1, "reason": "out_of_order",
107
+ "expected_question_id": "q1.workspaces", "received": "q2.packs" }
108
+ ```
109
+
110
+ Stateless (no session file), enforceable, and easy to test. Nonces
111
+ can be added later under the same protocol version if the threat model
112
+ hardens.
113
+
114
+ ### 5. Atomic writes via staging directory
115
+
116
+ Every command that writes to `.augment/`, `.agent-src/`, or the
117
+ lockfile stages changes under `.augment/.agent-config-staging/<uuid>/`,
118
+ verifies sha256s against intended manifest entries, then performs:
119
+
120
+ 1. Atomic rename: `staging/.augment/foo.md` → `.augment/foo.md`
121
+ (per-file `fs.renameSync` is atomic on POSIX and Windows ≥ 10).
122
+ 2. Lockfile written last (so a mid-flight crash leaves the lockfile
123
+ pointing at the previous-good state, not the partial new state).
124
+ 3. Staging directory removed on success.
125
+
126
+ `init`, `sync`, and `prune` share the same `commitAtomic(staging)`
127
+ helper.
128
+
129
+ ### 6. `protocol_version` field on every agent-mode response
130
+
131
+ ```json
132
+ { "status": "question", "protocol_version": 1, "id": "q1.workspaces", ... }
133
+ ```
134
+
135
+ Pinned at 1 for Phase 3; bumped to 2 only on breaking change.
136
+ Versioning the schema (not just `next_call`) lets Phase 5 add trust
137
+ banners without breaking existing agents.
138
+
139
+ ## Consequences
140
+
141
+ **Positive**
142
+
143
+ - Phase 5 (trust) can add `trust_level` to lockfile packs without a
144
+ schema migration (already at `schema_version: 1`; trust fields
145
+ become optional v1 additions).
146
+ - Phase 6 (browser wizard) reuses the same agent-mode JSON shape over
147
+ a local HTTP server; the strict-sequencing model maps to HTTP
148
+ request/response naturally.
149
+ - `agents/agent-config.overrides.yml` becomes a Git-tracked
150
+ declaration of user intent — diffable, reviewable, and never
151
+ silently overwritten.
152
+ - Atomic writes give `sync` and `prune` crash safety without a
153
+ rollback subcommand.
154
+
155
+ **Negative**
156
+
157
+ - One extra YAML file in the consumer repo (overrides).
158
+ - Strict sequencing means agents must replay the conversation if they
159
+ lose state mid-call; this is the simplest threat-model resolution
160
+ but pushes complexity onto agent authors.
161
+ - Per-file `manifest_sha256` adds ~64 bytes per lockfile entry; for a
162
+ 500-file install that's 32 KB. Acceptable.
163
+
164
+ **Deferred to Phase 5**
165
+
166
+ - npm package signature verification (SLSA Level 3 / `npm
167
+ provenance`). Reviewer A's "sign the package, not just the
168
+ manifest" call. Phase 5 owns trust gates; Phase 3 only records
169
+ provenance.
170
+
171
+ ## Rejected alternatives
172
+
173
+ - **Single lockfile with `overrides:` section** — the original spec.
174
+ Rejected because the installer cannot detect untracked
175
+ user-authored overrides without either scanning `agents/overrides/`
176
+ (which a malicious agent could pollute) or trusting user edits to
177
+ the lockfile (which breaks "lockfile is installer-generated").
178
+ - **Nonce-based agent mode** — overkill for v1. Re-evaluate when
179
+ agent mode lands on a remote surface.
180
+ - **Rollback subcommand with lockfile history** — atomic writes
181
+ already give us crash safety; full version history is a Phase 6
182
+ concern (the browser wizard wants a timeline).
183
+
184
+ ## References
185
+
186
+ - Roadmap: [`agents/roadmaps/monorepo-phase-3-typescript-installer.md`](../../agents/roadmaps/monorepo-phase-3-typescript-installer.md)
187
+ - Discovery manifest: [ADR-015](ADR-015-discovery-manifest-contract.md)
188
+ - CLI shell precedent: [ADR-012](ADR-012-typescript-cli-shell.md)
189
+ - Council session: [`agents/runtime/council/responses/phase-3-installer-design.json`](../../agents/runtime/council/responses/phase-3-installer-design.json) <!-- council-ref-allowed: ADR decision-trace -->
@@ -0,0 +1,261 @@
1
+ ---
2
+ adr: 017
3
+ status: accepted
4
+ date: 2026-05-21
5
+ decision: monorepo-physical-layout
6
+ supersedes: —
7
+ superseded_by: —
8
+ phase: v2.x · monorepo-phase-4-physical-package-layout
9
+ type: prospective
10
+ ---
11
+
12
+ # ADR-017 — Monorepo Physical Package Layout
13
+
14
+ ## Status
15
+
16
+ **Accepted** · 2026-05-21 · external AI Council pass (`claude-sonnet-4-5`
17
+ + `gpt-4o`, 2 rounds, `design` lens, actual cost $0.0961) on the Phase 4
18
+ roadmap. Council issued **conditional approval** with four blockers and
19
+ two refinements; this revision folds each into the design before the
20
+ `--apply` step runs.
21
+
22
+ Session: [`agents/runtime/council/responses/phase-4-physical-layout.json`](../../agents/runtime/council/responses/phase-4-physical-layout.json) <!-- council-ref-allowed: ADR decision-trace -->
23
+
24
+ Companion artefacts:
25
+ - [`agents/roadmaps/monorepo-phase-4-physical-package-layout.md`](../../agents/roadmaps/monorepo-phase-4-physical-package-layout.md)
26
+ - [`dist/migration/move-plan.json`](../../dist/migration/move-plan.json) (94 moves, 432 core, 0 conflicts)
27
+ - [`dist/migration/pre-move-snapshot.json`](../../dist/migration/pre-move-snapshot.json) (744 files hashed)
28
+ - [`scripts/plan_physical_move.py`](../../scripts/plan_physical_move.py) (plan + apply)
29
+ - [`scripts/verify_physical_move.py`](../../scripts/verify_physical_move.py) (post-move diff vs. snapshot)
30
+
31
+ ## Context
32
+
33
+ Phases 1–3 produced the artefact metadata (`packs[]`, `workspaces[]`,
34
+ `trust.level`, `install.removable`), the discovery manifest, and the
35
+ TypeScript installer **without** moving a single file. The on-disk
36
+ source tree is still flat:
37
+
38
+ ```text
39
+ .agent-src.uncompressed/
40
+ rules/ # 72 entries
41
+ skills/ # 218 entries
42
+ commands/ # 129 entries
43
+ personas/ # 24 entries
44
+ contexts/ # 32 entries
45
+ templates/ # 24 scaffolds
46
+
47
+ ```
48
+
49
+ This means the metadata says "this skill belongs to `pack.laravel`" but
50
+ the file lives next to a Symfony skill and a finance persona. Consumers
51
+ of the npm release, the consumer-side `.augment/` overlay, and the
52
+ upcoming Phase 5 trust gates would all benefit from physical separation
53
+ that mirrors the manifest. Phase 4 introduces that separation in one PR
54
+ with a deterministic, history-preserving migration.
55
+
56
+ The four risks the council flagged on Phase 3 (history loss, stale path
57
+ refs, cross-pack drift, hand-edited paths) all bite hardest here.
58
+
59
+ ## Decision
60
+
61
+ ### 1. Layout — one core, one folder per pack
62
+
63
+ ```text
64
+ packages/
65
+ core/
66
+ installer/ # TS CLI (already there post-Phase 3)
67
+ .agent-src.uncompressed/ # rules + kernel skills + scaffolds
68
+ pack-php/.agent-src.uncompressed/
69
+ pack-laravel/.agent-src.uncompressed/
70
+
71
+ pack-ai-video/.agent-src.uncompressed/
72
+ ```
73
+
74
+ No flag day: every commit between "before" and "after" the move builds
75
+ and ships. The TS installer needs zero behavioural changes — only the
76
+ `manifest-loader.ts` path roots flip.
77
+
78
+ ### 2. Mapping rules (deterministic, lockfile-stable)
79
+
80
+ Implemented in [`scripts/plan_physical_move.py`](../../scripts/plan_physical_move.py):
81
+
82
+ 1. **Kernel rules** → `packages/core/` (allowlist, sanity-checked against
83
+ [`docs/contracts/kernel-membership.md`](../contracts/kernel-membership.md) §4).
84
+ The locked set is 10 entries; `user-interrupt-priority` was admitted
85
+ post-P2.2 and is included.
86
+ 2. **Core-trust artefacts** (`trust.level: core` AND
87
+ `install.removable: false`) → `packages/core/`.
88
+ 3. **Non-frontmatter trees** (`templates/`, `profiles/`, `presets/`,
89
+ `contexts/`, `user-types/`, `scripts/`, `ghostwriter/`, `packs/`,
90
+ `personas/`) → `packages/core/` verbatim. These are scaffolding and
91
+ product internals, not pack-routable artefacts.
92
+ 4. **Skill auxiliary files** (`prompts/*.md`, sub-pages inside a skill
93
+ directory) → inherit the destination of the nearest `SKILL.md` in
94
+ the parent directory tree. Codified to fix 9 false-positive conflicts
95
+ on Phase 4 dry-run.
96
+ 5. **Pack-routable artefacts** → `packages/pack-<id>/`, where `<id>` is
97
+ the first entry in `packs[]`. Tie-breaking by alphabetic pack id.
98
+ 6. **Quarantined scaffolds** (the 26 entries in
99
+ [`config/discovery/unassigned-artefacts.yml`](../../config/discovery/unassigned-artefacts.yml))
100
+ → `packages/core/` with `unassigned scaffold:` reason recorded in the
101
+ move plan. The top-level `.agent-src.uncompressed/README.md` was added
102
+ here during dry-run.
103
+ 7. **`primary pack: meta`** → `packages/core/` (package-internal
104
+ scaffolding, not a real pack).
105
+ 8. **Unknown / missing pack** → fall back to `packages/core/` AND emit
106
+ a conflict. `--apply` refuses to run if `conflicts > 0`.
107
+
108
+ ### 3. Mechanic — `git mv` only
109
+
110
+ Every move uses `git mv` so `git log --follow` keeps working on every
111
+ artefact post-move. The plan script's `--apply` mode is the only entry
112
+ point; it refuses if any conflict remains. No human-edited paths.
113
+
114
+ ### 4. Byte-identity contract
115
+
116
+ `task sync` + `task build-discovery` after the move must produce
117
+ `.agent-src/`, `.augment/`, and `dist/discovery/discovery-manifest.json`
118
+ byte-identical to the pre-move snapshot **except** for
119
+ `artefacts[].path` values. [`scripts/verify_physical_move.py`](../../scripts/verify_physical_move.py)
120
+ captures a post-move snapshot and diffs against
121
+ `dist/migration/pre-move-snapshot.json`; the only allowed delta is the
122
+ `path` field per artefact.
123
+
124
+ ### 5. Rollback
125
+
126
+ The whole move is a single PR. `git revert <merge-sha>` restores the
127
+ prior layout in one commit; the next `task sync` round-trip is back to
128
+ the pre-move snapshot. No data migration, no manifest schema change, no
129
+ installer behaviour change.
130
+
131
+ ## Consequences
132
+
133
+ ### Positive
134
+
135
+ - Metadata-to-disk parity: a consumer can now `cd packages/pack-laravel`
136
+ and see exactly what `pack.laravel` ships, no manifest indirection.
137
+ - Phase 5 (trust) lands cleanly inside `packages/core/installer/` and
138
+ reads per-pack metadata from `packages/pack-*/.agent-src.uncompressed/`.
139
+ - Phase 6 (browser wizard) maps packs 1:1 to its left-nav.
140
+ - Cross-pack drift is now lintable (`task lint-pack-boundaries` in
141
+ Phase 4.4 of the roadmap).
142
+ - `git log --follow` keeps working — no history loss.
143
+
144
+ ### Negative
145
+
146
+ - One large PR (~526 file moves). Reviewers need the move plan as the
147
+ primary review artefact, not per-file diff inspection.
148
+ - Editors with the old tree open will hit broken paths until they pull.
149
+ Mitigated by docs-update in the same PR (`AGENTS.md`, `README.md`,
150
+ `docs/architecture.md`).
151
+ - Path refs in CI workflows, Taskfile, and the discovery scanner need
152
+ one-line updates. The roadmap enumerates each.
153
+
154
+ ### Neutral
155
+
156
+ - The npm tarball shape changes (paths only). The installer copies
157
+ files by manifest entry, not by source path, so consumers see no
158
+ difference.
159
+
160
+ ## Alternatives considered
161
+
162
+ 1. **Phased move (one pack per PR).** Rejected: 16 PRs, partial states
163
+ on disk for weeks, `task sync` invariants harder to enforce.
164
+ 2. **Symlink farm.** Rejected: Windows support, npm tarball duplication,
165
+ and the installer would have to dereference paths.
166
+ 3. **Stay flat, lift packs into manifest-only.** Rejected: this is the
167
+ current state; it forfeits the metadata-to-disk parity that Phase 5
168
+ and Phase 6 depend on.
169
+
170
+ ## Council resolution (Round 2)
171
+
172
+ Four blocking items and two refinements raised by the council; each
173
+ resolved before `--apply` runs.
174
+
175
+ ### B1 — Final source location of `.agent-src.uncompressed/`
176
+
177
+ The council asked whether the source tree nests inside `packages/core/`
178
+ (current design) or becomes a peer `pack-core/`. **Decision: keep
179
+ `packages/core/.agent-src.uncompressed/`.** Three reasons:
180
+
181
+ 1. `packages/core/` is the engine + installer + kernel rules +
182
+ scaffolding (templates, profiles, presets, contexts, user-types).
183
+ None of that is pack-routable; making it a "pack" inverts the
184
+ product mental model.
185
+ 2. The installer in `packages/core/installer/` already lives next to
186
+ the manifest loader; co-locating the rules that bootstrap the
187
+ installer reduces cross-package import chains.
188
+ 3. The TS installer consumes `dist/discovery/discovery-manifest.json`,
189
+ not source paths, so the "location is privileged" critique does not
190
+ bite — the manifest is the API.
191
+
192
+ ### B2 — `git mv` rename detection at scale
193
+
194
+ Default `diff.renameLimit` since git 2.9 is 1000. Plan: 94 explicit
195
+ `git mv` operations + 1 directory rename for `core/`. Each move is
196
+ content-identical (no edits during move). Test gate: after `--apply`,
197
+ run `git diff --name-status HEAD~1` and assert `R100` (100 % rename
198
+ similarity) on every moved file. Verification script enforces this.
199
+
200
+ ### B3 — Consumer-facing output contract
201
+
202
+ `task sync` writes `.agent-src/` (compressed) and `.augment/` (overlay)
203
+ at repo root — **unchanged** location and structure. The byte-identity
204
+ contract covers exactly these two trees plus the discovery manifest.
205
+ What changes:
206
+
207
+ - `dist/discovery/discovery-manifest.json` `artefacts[].path` values
208
+ (path-only delta, enforced by `verify_physical_move.py`).
209
+ - npm tarball internal paths (consumers never touch these; installer
210
+ uses manifest entries).
211
+
212
+ What stays identical: `.agent-src/`, `.augment/`, manifest checksums
213
+ of non-path fields, lockfile schema, installer behaviour.
214
+
215
+ ### B4 — Installer dual-layout support
216
+
217
+ Not required. Consumers install via `npm install
218
+ @event4u/agent-config@<version>`; each version ships a self-consistent
219
+ tarball. There is no "consumer pulls mid-PR" scenario because consumers
220
+ do not consume the source repo — they consume the published tarball.
221
+ Source-tree contributors who pull the merge commit move atomically
222
+ with the layout. The "dual-layout" complexity the council proposed
223
+ exists in code-host-as-CDN ecosystems we do not target.
224
+
225
+ ### R1 — `primary_pack` frontmatter field
226
+
227
+ `scripts/plan_physical_move.py` already uses `packs[0]` as the
228
+ destination. Round-2 hardening: the plan also reads an explicit
229
+ `primary_pack:` frontmatter field when present and prefers it over
230
+ `packs[0]`. Lint that requires `primary_pack` on every pack-routable
231
+ artefact lands in Phase 4.4 (out of scope for the move itself; the
232
+ move uses today's data and the new fallback).
233
+
234
+ ### R2 — Pre-move pack-boundary lint
235
+
236
+ The current plan dry-run finds 0 conflicts after the auxiliary-file
237
+ inheritance rule landed. A cross-pack-reference lint (an artefact in
238
+ `pack.laravel` citing one in `pack.symfony` without a declared
239
+ dependency) is deferred to Phase 4.4 — the move itself does not edit
240
+ file contents, so cross-pack references survive the move byte-identical.
241
+
242
+ ## Compliance + verification
243
+
244
+ - `scripts/plan_physical_move.py` is the only mover. Hand-edited paths
245
+ fail `task verify-physical-move`.
246
+ - `scripts/verify_physical_move.py` enforces the byte-identity
247
+ contract.
248
+ - `task ci` runs both as a hard gate post-move.
249
+ - Per-pack lint matrix lands in Phase 4.4 of the roadmap.
250
+
251
+ ## Future work
252
+
253
+ - Phase 4.4 — per-pack `pack.yaml` + boundary lint.
254
+ - Phase 4.5 — contributor scaffolders (`task new-skill`,
255
+ `task move-artefact`).
256
+ - Phase 6 (optional) — split distribution per pack as separate npm
257
+ packages. Specification removed 2026-05-24 (drift audit, finding
258
+ F-1): the 150-line "documented-only" addendum had zero consumers
259
+ and ~6 months of unmaintained drift versus the bundled-tarball
260
+ model. Restore from git history at `d06af2c5` if a real consumer
261
+ ever asks for a single-pack install path.