hamilton-core 0.1.0__tar.gz

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 (43) hide show
  1. hamilton_core-0.1.0/LICENSE +21 -0
  2. hamilton_core-0.1.0/PKG-INFO +402 -0
  3. hamilton_core-0.1.0/README.md +357 -0
  4. hamilton_core-0.1.0/hamilton_core/__init__.py +3 -0
  5. hamilton_core-0.1.0/hamilton_core/__main__.py +6 -0
  6. hamilton_core-0.1.0/hamilton_core/check.py +613 -0
  7. hamilton_core-0.1.0/hamilton_core/cli.py +75 -0
  8. hamilton_core-0.1.0/hamilton_core/guard.py +76 -0
  9. hamilton_core-0.1.0/hamilton_core/init.py +83 -0
  10. hamilton_core-0.1.0/hamilton_core/launch.py +198 -0
  11. hamilton_core-0.1.0/hamilton_core/model.py +202 -0
  12. hamilton_core-0.1.0/hamilton_core/show.py +138 -0
  13. hamilton_core-0.1.0/hamilton_core/status.py +141 -0
  14. hamilton_core-0.1.0/hamilton_core/templates/AGENTS.md +24 -0
  15. hamilton_core-0.1.0/hamilton_core/templates/CLAUDE.md +2 -0
  16. hamilton_core-0.1.0/hamilton_core/templates/claude/settings.json +16 -0
  17. hamilton_core-0.1.0/hamilton_core/templates/hamilton/config +26 -0
  18. hamilton_core-0.1.0/hamilton_core/templates/hamilton/phase +1 -0
  19. hamilton_core-0.1.0/hamilton_core/templates/prompts/hamilton.md +559 -0
  20. hamilton_core-0.1.0/hamilton_core/templates/spec/actors.md +11 -0
  21. hamilton_core-0.1.0/hamilton_core/templates/spec/requirements.md +45 -0
  22. hamilton_core-0.1.0/hamilton_core/templates/spec/vision.md +21 -0
  23. hamilton_core-0.1.0/hamilton_core/tree.py +70 -0
  24. hamilton_core-0.1.0/hamilton_core/upgrade.py +114 -0
  25. hamilton_core-0.1.0/hamilton_core.egg-info/PKG-INFO +402 -0
  26. hamilton_core-0.1.0/hamilton_core.egg-info/SOURCES.txt +41 -0
  27. hamilton_core-0.1.0/hamilton_core.egg-info/dependency_links.txt +1 -0
  28. hamilton_core-0.1.0/hamilton_core.egg-info/entry_points.txt +2 -0
  29. hamilton_core-0.1.0/hamilton_core.egg-info/requires.txt +3 -0
  30. hamilton_core-0.1.0/hamilton_core.egg-info/top_level.txt +1 -0
  31. hamilton_core-0.1.0/pyproject.toml +51 -0
  32. hamilton_core-0.1.0/setup.cfg +4 -0
  33. hamilton_core-0.1.0/tests/test_check.py +311 -0
  34. hamilton_core-0.1.0/tests/test_guard.py +249 -0
  35. hamilton_core-0.1.0/tests/test_init.py +159 -0
  36. hamilton_core-0.1.0/tests/test_launch.py +162 -0
  37. hamilton_core-0.1.0/tests/test_model.py +110 -0
  38. hamilton_core-0.1.0/tests/test_normalize.py +55 -0
  39. hamilton_core-0.1.0/tests/test_show.py +184 -0
  40. hamilton_core-0.1.0/tests/test_status.py +96 -0
  41. hamilton_core-0.1.0/tests/test_tree.py +109 -0
  42. hamilton_core-0.1.0/tests/test_upgrade.py +173 -0
  43. hamilton_core-0.1.0/tests/test_warnings.py +140 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 D5 Software GmbH
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,402 @@
1
+ Metadata-Version: 2.4
2
+ Name: hamilton-core
3
+ Version: 0.1.0
4
+ Summary: Specification-gated development with enforced verification
5
+ Author-email: Sebastian Greshake <sebastian.greshake@d5software.de>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2026 D5 Software GmbH
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Project-URL: Homepage, https://github.com/hamilton-toolkit/core
29
+ Project-URL: Repository, https://github.com/hamilton-toolkit/core
30
+ Project-URL: Issues, https://github.com/hamilton-toolkit/core/issues
31
+ Classifier: Development Status :: 3 - Alpha
32
+ Classifier: Environment :: Console
33
+ Classifier: Intended Audience :: Developers
34
+ Classifier: License :: OSI Approved :: MIT License
35
+ Classifier: Programming Language :: Python :: 3
36
+ Classifier: Programming Language :: Python :: 3.11
37
+ Classifier: Programming Language :: Python :: 3.12
38
+ Classifier: Programming Language :: Python :: 3.13
39
+ Requires-Python: >=3.11
40
+ Description-Content-Type: text/markdown
41
+ License-File: LICENSE
42
+ Provides-Extra: test
43
+ Requires-Dist: pytest; extra == "test"
44
+ Dynamic: license-file
45
+
46
+ # Hamilton
47
+
48
+ > Forget vibe coding, start engineering.
49
+
50
+ Hamilton is a small framework for building software **with** an AI agent
51
+ without taking its word for when the work is done. You write down what the
52
+ software must do — as specific, testable acceptance criteria — *before* it is
53
+ built. The agent then implements it and writes the tests. One command,
54
+ `hamilton check`, verifies that every criterion has a test that names it, that
55
+ the suite passes, and that no criterion has been quietly reworded since it last
56
+ passed. Specification, code and tests live in one repository and land in one
57
+ review.
58
+
59
+ ## Why
60
+
61
+ Vibe coding optimises for the first working version and leaves you to discover
62
+ later what it actually does. That is fine until the software matters, and then
63
+ the missing half of the work — *deciding what it should do, and proving it
64
+ does* — is the expensive half.
65
+
66
+ Hamilton borrows the discipline of the **V-model** from systems engineering:
67
+ verification intent is fixed *before* implementation, by someone not yet
68
+ anchored by the code, and every requirement is paired with the criteria that
69
+ say when it is met. It is deliberately a scale-appropriate slice — one engineer
70
+ to a small team, not a defence contractor — but the core move is the same: the
71
+ target is written down first, and "done" is checked against it rather than
72
+ asserted by whoever (or whatever) wrote the code.
73
+
74
+ It is named after **Margaret Hamilton**, who ran software engineering for the
75
+ Apollo flight computer and coined the term "software engineering" to make the
76
+ point that it deserved to be taken as seriously as any other kind.
77
+
78
+ ### The loop
79
+
80
+ 1. **You specify.** In `spec/` you write the vision, the actors, and a tree of
81
+ requirements. Each requirement is one sentence and carries acceptance
82
+ criteria — observable conditions and their expected outcomes.
83
+ 2. **The agent implements.** It writes the code and the tests. Each test
84
+ carries a one-line comment naming the single criterion it covers —
85
+ `@covers R-0001/AC1`.
86
+ 3. **`hamilton check` verifies.** It runs your suite and stays red until every
87
+ criterion has a passing tagged test. Reword a criterion and it goes red
88
+ again until the test and code are reconciled with the new wording.
89
+
90
+ The acceptance criteria are yours. The rigorous tests that bind to them are the
91
+ agent's. `hamilton check` is what keeps the two honest.
92
+
93
+ ## The two phases
94
+
95
+ Work happens in one of two phases, and the point of each is what it stops you
96
+ (or the agent) from doing.
97
+
98
+ **Spec phase** — you decide what the software should do. The agent can edit
99
+ `spec/` and nothing else. It cannot start writing code against a target you
100
+ have not finished setting.
101
+
102
+ **Build phase** — the agent writes the code and the tests. It cannot edit
103
+ `spec/`, `.claude/`, or `AGENTS.md`, and of `.hamilton/` only `config` — and
104
+ there only `test_command` / `test_paths`, because picking the test framework
105
+ and layout is a build-time call. It cannot quietly change a requirement to
106
+ match what it built, or rewrite its own rules.
107
+
108
+ You start a session in a phase with **`hamilton design`** (spec) or
109
+ **`hamilton build`** (build). Each writes the phase to `.hamilton/phase`,
110
+ prints a status banner, then runs your agent as a child process holding the
111
+ terminal, with a one-line kickoff so the session starts working straight away.
112
+ The phase is fixed for that whole session: it exports `HAMILTON_SESSION`, and
113
+ `design` / `build` refuse to run when that is already set, so an agent can't
114
+ relaunch itself into the other phase. A `PreToolUse` hook blocks edits to
115
+ read-only paths during the session as fast feedback.
116
+
117
+ None of this is unbypassable — unset the variable, edit the phase file by hand,
118
+ or run the agent directly and you are outside it. It stops drift, not a
119
+ determined operator. `hamilton check` run in CI, which ignores the phase
120
+ entirely, is the gate that enforces the outcome for real.
121
+
122
+ ## Quick start
123
+
124
+ ### 1. Check out the framework
125
+
126
+ Get this repository onto your machine (`git clone`, or you may already have it)
127
+ and `cd` into it. This checkout *is* the distribution — `hamilton-core` is not
128
+ published anywhere.
129
+
130
+ Requires Python 3.11+. There are no dependencies — standard library only.
131
+
132
+ Run its own test suite before you trust a checkout, especially one you have
133
+ been editing:
134
+
135
+ ```
136
+ $ python -m pytest -q # expects 194 passing
137
+ ```
138
+
139
+ ### 2. Link it into a separate test project
140
+
141
+ `hamilton-core` is not on PyPI (the name `hamilton` there belongs to an
142
+ unrelated project), so you install it from the checkout. To exercise it on a
143
+ real project, install it from your working copy into that project's virtualenv
144
+ — exactly what a published release would look like, just pointed at a local
145
+ path.
146
+
147
+ ```
148
+ $ cd /path/to/your-test-project
149
+ $ python -m venv .venv
150
+ $ . .venv/bin/activate
151
+
152
+ # editable install: your edits to the framework take effect with no reinstall
153
+ $ pip install -e /path/to/hamilton
154
+
155
+ # — or — a fixed snapshot, exactly like installing a published release
156
+ $ pip install /path/to/hamilton
157
+
158
+ # the test project needs its own test runner in the same venv
159
+ $ pip install pytest
160
+
161
+ $ hamilton --help
162
+ ```
163
+
164
+ `hamilton` is now on the venv's `PATH`. Keep the venv activated so that a
165
+ `test_command` of `python -m pytest -q` in `.hamilton/config` resolves to this
166
+ venv's pytest.
167
+
168
+ ### 3. Scaffold the project
169
+
170
+ ```
171
+ $ cd /path/to/your-test-project
172
+ $ git init -q
173
+ $ hamilton init
174
+ hamilton init: scaffolded /path/to/your-test-project
175
+
176
+ Run `hamilton design` to write the specification with an AI agent's help.
177
+ Prefer to write it by hand? Start from the files in spec/ -- each explains
178
+ what it should contain.
179
+ ```
180
+
181
+ `init` writes `spec/` (`vision.md`, `actors.md`, `requirements.md` — each with
182
+ a fenced example to replace), `.hamilton/` (`phase`, `config`), `AGENTS.md`
183
+ with `CLAUDE.md` pointing at it, and `.claude/` (the phase-guard hook settings
184
+ and the `hamilton` skill). `AGENTS.md` and `.claude/` belong to the framework
185
+ and stay as written.
186
+
187
+ If your coding agent is not `claude`, set `agent_command` in `.hamilton/config`
188
+ before the next step.
189
+
190
+ ### 4. Specify, build, check
191
+
192
+ ```
193
+ $ hamilton design # spec phase: draft the vision and the requirements with the agent
194
+ $ hamilton build # build phase: the agent writes code + tagged tests, gets the gate green
195
+ $ hamilton check # the verification gate — run it yourself, and in CI
196
+ ```
197
+
198
+ `hamilton check` exits `0` when every criterion has a passing tagged test and
199
+ nothing is stale; `1` on any finding; `2` if it cannot run at all. Wire the
200
+ same command into your pipeline — that CI run, outside the agent, is the real
201
+ gate.
202
+
203
+ ### Following along without an agent
204
+
205
+ Every step `hamilton design` / `hamilton build` drive can be done by hand to
206
+ see the mechanism:
207
+
208
+ ```
209
+ $ printf spec > .hamilton/phase # (what `hamilton design` does)
210
+ # ... edit spec/requirements.md and spec/actors.md ...
211
+ $ printf build > .hamilton/phase # (what `hamilton build` does)
212
+ # ... write the implementation and tests/ with @covers tags ...
213
+ $ hamilton check
214
+ hamilton check: running test_command: python -m pytest -q
215
+ 2 passed in 0.01s
216
+ hamilton check: 1 requirement(s), 2 acceptance criteria
217
+ hamilton check: ok
218
+ ```
219
+
220
+ A green run writes `.hamilton/verified` — the hash of each criterion's text at
221
+ that passing run. Commit it; that is what a later `stale` finding compares
222
+ against.
223
+
224
+ ### Starting from an existing codebase
225
+
226
+ If the code already exists, run `hamilton reverse` instead of `hamilton design`
227
+ for the first spec session:
228
+
229
+ ```
230
+ $ hamilton init
231
+ $ hamilton reverse # spec phase: the agent surveys the code and its git
232
+ # history, confirms with you what the system is and who
233
+ # its actors are, then derives the requirement tree
234
+ # module by module — you ratify each piece
235
+ $ hamilton check # red on `uncovered` — expected; the derived spec has
236
+ # no tests bound to it yet
237
+ $ hamilton build # the agent binds your existing tests to the derived
238
+ # criteria (and writes AC-level tests where the unit
239
+ # tests are too fine-grained), then gets the gate green
240
+ ```
241
+
242
+ The derived spec is deliberately **thinner than the code** — it records intent
243
+ and the load-bearing decisions and leaves the rest to the implementing agent, so
244
+ `hamilton check` still runs against the same one-tree model as a greenfield
245
+ project. `hamilton reverse` refuses once `spec/requirements.md` has real
246
+ requirements; extend an existing spec with `hamilton design`.
247
+
248
+ ## Commands
249
+
250
+ | Command | Phase | What it does |
251
+ |---|---|---|
252
+ | `hamilton init [path]` | — | Scaffold a project: `spec/`, `.hamilton/`, `AGENTS.md` / `CLAUDE.md`, `.claude/`. Refuses if `.hamilton/` already exists. |
253
+ | `hamilton design` | sets **spec** | Write the phase, print the status banner, launch the agent scoped to spec phase with a kickoff to draft the vision / requirements through the review protocol. |
254
+ | `hamilton build` | sets **build** | Write the phase, print the banner, launch the agent scoped to build phase with a kickoff to propagate the latest spec change and get `hamilton check` green. |
255
+ | `hamilton reverse` | sets **spec** | Brownfield: like `hamilton design`, but the kickoff has the agent derive a first spec from the existing code and its git history, module by module. Refuses if `spec/requirements.md` already has requirements. |
256
+ | `hamilton check [--json]` | ignores phase | The verification gate: run `test_command`, check every AC has a passing `@covers` test under `test_paths`, flag reworded criteria as `stale`, validate the requirement tree. Writes `.hamilton/verified` on a clean run. This is the gate — run it in CI. |
257
+ | `hamilton status` | read-only | Print the project snapshot the launcher shows as its banner: phase, requirement and coverage counts, and the last three `spec/` changes. |
258
+ | `hamilton tree [--json]` | read-only | Print the whole requirement tree with a dotted path computed at render time, an `i` / `!` marker for whether each interior node carries an `Interface:` yet, and a per-requirement coverage mark. |
259
+ | `hamilton show <ID> [--json]` | read-only | Print one entity in full and what refers to it. `R-nnnn`: path by title, statement, criteria with coverage status and the file holding each `@covers` tag, `Interface:` / `Actor:`, child requirements. `A-nnnn`: description and the requirements that name it. |
260
+ | `hamilton upgrade [path]` | — | Bring the framework-managed files up to date after installing a newer Hamilton — `AGENTS.md`, `CLAUDE.md`, the `.claude/` tree. Prints a diff, then overwrites. Never touches `spec/`, `.hamilton/phase`, `.hamilton/config`, `.hamilton/verified`. |
261
+ | `hamilton guard` | — | Internal: the `PreToolUse` hook backend that blocks read-only-path edits during a session. Not run by hand. |
262
+
263
+ `hamilton tree`, `hamilton show` and `hamilton status` write nothing and never
264
+ touch the gate. All three, plus `hamilton check`, take `--json` for tooling.
265
+
266
+ ### When `hamilton check` fails
267
+
268
+ | Rule | What it means / what to do |
269
+ |---|---|
270
+ | `no-test-command` | `.hamilton/config` has no `test_command` (or a blank one). Set it — e.g. `test_command=python -m pytest -q`. |
271
+ | `tests-failed` | `test_command` ran and did not exit 0. Run it yourself to see why, and fix the code or the test. |
272
+ | `uncovered` | An acceptance criterion has no `@covers R-nnnn/ACn` tag in any file under `test_paths`. Add the tag to the test that checks that criterion. |
273
+ | `orphan-tag` | A `@covers` tag names a requirement or criterion that `spec/requirements.md` does not declare. Fix the tag, or add the criterion (in spec phase). |
274
+ | `orphan-requirement` | A requirement with no `Parent:` does not name an `Actor:`. Add the `Actor:`, or give it a `Parent:`. |
275
+ | `dangling-ref` | A `Parent:` or `Actor:` value names an entity that isn't declared. Fix the reference, or add the entity. |
276
+ | `cyclic-parent` | Following `Parent:` links from some requirement loops back on itself. Re-point one `Parent:`. |
277
+ | `stale` | A criterion was reworded since the last green check. Re-read it, confirm the tagged test still fits, and run `hamilton check` again — it clears once the run is otherwise clean. |
278
+ | `malformed` | A requirement is missing its `Statement`, has no criteria, repeats an id, or has a line that doesn't parse — or the file has no real requirements at all. The message names the line. |
279
+
280
+ It also prints **advisory warnings** — never fail the run, never change the
281
+ exit code: `long-statement` (a `Statement:` over 20 words — it is several
282
+ requirements welded together), `long-description` (an actor `Description:` over
283
+ one sentence), `no-interface` (an interior requirement with no `Interface:`
284
+ line yet). And a **notice** if `.hamilton/config` sets `mutation_command`: that
285
+ key is reserved for future mutation testing and is not implemented — unset it.
286
+
287
+ ## The spec files
288
+
289
+ `hamilton init` writes three files under `spec/`. Each opens with a fenced
290
+ example that `hamilton check` ignores; you replace it with your own content
291
+ below the fence. `spec/` is writable in spec phase, read-only in build.
292
+
293
+ ### `spec/vision.md`
294
+
295
+ Prose, not a model — `hamilton check` never reads it. Three sections:
296
+ **Purpose** (one or two sentences on what the software is for and for whom),
297
+ **Users** (who uses it and what they need), **Non-goals** (plausible features
298
+ that are deliberately out of scope, each with why). The non-goals are the
299
+ load-bearing part: they are what lets a reviewer, and a future agent, tell a
300
+ requested change from an unrequested feature. On a brand-new project
301
+ `hamilton design` offers to draft this with you first.
302
+
303
+ ### `spec/actors.md`
304
+
305
+ A flat list of the external entities that interact with the system — they
306
+ define its boundary. One `## A-nnnn` block each, with a `Name:` and a
307
+ one-sentence `Description:`.
308
+
309
+ ```markdown
310
+ ## A-0001
311
+ Name: CLI user
312
+ Description: Runs the initials tool from the command line.
313
+ ```
314
+
315
+ ### `spec/requirements.md`
316
+
317
+ The whole model: one `Parent:` tree.
318
+
319
+ - A requirement with **no `Parent:`** is a **root** — a system-level goal — and
320
+ must name the `Actor:` whose goal it is. Ratify the root layer first;
321
+ specification is top-down.
322
+ - A requirement **with children** is a subsystem boundary and carries an
323
+ `Interface:` line — one sentence naming what crosses that boundary. The
324
+ interior of the tree *is* the architecture.
325
+ - A **leaf** needs neither: just a `Statement:` and criteria.
326
+
327
+ Every requirement is a `## R-nnnn Short title` block with a one-sentence
328
+ `Statement:` (under 20 words, one behaviour — detail belongs in the criteria)
329
+ and at least one `- ACn:` line, written as `<observable condition> -> <expected
330
+ outcome>` where that shape fits.
331
+
332
+ ```markdown
333
+ ## R-0001 Initials of a name
334
+ Actor: A-0001
335
+ Statement: initials(name) returns the capitalised first letter of each whitespace-separated word.
336
+ Criteria:
337
+ - AC1: "ada lovelace" -> "AL"
338
+ - AC2: runs of whitespace between words count as one separator
339
+ ```
340
+
341
+ A test that covers one of its criteria:
342
+
343
+ ```python
344
+ def test_two_words(): # @covers R-0001/AC1
345
+ assert initials("ada lovelace") == "AL"
346
+ ```
347
+
348
+ A shared field rule — a format, an enum, a validation rule — goes once in a
349
+ `## Domain vocabulary` section at the top of the file and is referenced by name
350
+ from the criteria that need it, never restated inside a `Statement:`.
351
+
352
+ ## What this does not do
353
+
354
+ It runs your tests and checks that each criterion has one — it does **not**
355
+ check that your tests are any good. A test that asserts nothing, or the wrong
356
+ thing, passes the gate as long as it runs. `hamilton check` proves your
357
+ criteria are written down, tied to tests, and passing; it does not prove those
358
+ tests would catch a regression.
359
+
360
+ Related limits, stated plainly:
361
+
362
+ - **`stale` clears by re-running.** It proves the suite was re-executed against
363
+ the reworded criterion, not that a person reconciled the test with it.
364
+ - **The phase hook is defeatable from a shell.** It covers file-editing tools
365
+ only, so it stops drift inside a cooperating session, not deliberate
366
+ circumvention. CI — `hamilton check` run outside the agent — is the real gate.
367
+ - **Only requirements and criteria can *fail* the gate.** `spec/actors.md` is
368
+ read for the view commands, for `dangling-ref` on an `Actor:` link, and for
369
+ `long-description` warnings, but nothing in it turns a build red by itself.
370
+ - **IDs are hand-written.** A repeated `R-nnnn` is caught by `hamilton check`
371
+ (`malformed`), not prevented as you type.
372
+ - **The Claude Code hook and skill are one supported agent, not the only one.**
373
+ The launcher works with any `agent_command`; the per-edit `PreToolUse` hook
374
+ ships for Claude Code only.
375
+
376
+ ## Upgrading the scaffold
377
+
378
+ After installing a newer Hamilton, `hamilton upgrade` brings the
379
+ framework-managed files up to date — `AGENTS.md`, `CLAUDE.md` (a pointer at
380
+ it), and the `.claude/` tree (the phase-guard hook settings and the `hamilton`
381
+ skill). It never touches your own work: `spec/` (including `spec/vision.md`),
382
+ `.hamilton/phase`, `.hamilton/config`, `.hamilton/verified`.
383
+
384
+ ```
385
+ $ hamilton upgrade
386
+ ```
387
+
388
+ It prints a diff of everything it changes, then overwrites those files with the
389
+ current templates, recreates any you deleted, and deletes any it has since
390
+ retired. They belong to the framework, so it does not ask before replacing them
391
+ — keep local changes out of them.
392
+
393
+ **A project created before the launcher** has no `agent_command` line in
394
+ `.hamilton/config` (that file is yours, so `upgrade` won't add it). Add
395
+ `agent_command=claude` — or whatever starts your agent — by hand, or the first
396
+ `hamilton design` / `hamilton build` stops with "agent_command is not set".
397
+
398
+ ## The rationale
399
+
400
+ The design rationale is in `docs/` — `concept.md` (the V-model / MBSE slice)
401
+ and `data-model.md` (the spec format in full). You do not need either to use
402
+ the tool.