archik 0.20.0 → 0.21.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.
package/README.md CHANGED
@@ -110,6 +110,11 @@ There are no coordinates — layout is computed by [ELK](https://eclipse.dev/elk
110
110
  | --- | --- | --- |
111
111
  | Structure | `.archik/main.archik.yaml` | Services, databases, queues, agents, LLMs, edges |
112
112
  | Sub-architecture | `.archik/*.archik.yaml` | A node's internals, linked via `archikFile` |
113
+ | Decisions | `.archik/decisions/NNNN-*.md` | Why each accepted change was made — context, decision, alternatives, consequences |
114
+
115
+ The diagram says *what*; decision records say *why*. Every staged change carries one under `metadata.suggestion.decision` — `suggest set` refuses a draft without it — and accepting the change writes it as a numbered markdown record with the node and edge changes listed as evidence. Records are never edited; a later decision that changes course lists the old numbers in `supersedes`.
116
+
117
+ Each change is also labelled by how hard it is to undo. A **one-way door** — a new data store, queue, external system, gateway, LLM or top-level module, a removal, or a boundary move — gets its own canvas review before the build plan; if it adds data, an outside system or public traffic, its record must say how it is secured, observed and rolled back. A **two-way door** goes through one combined review of model and plan.
113
118
 
114
119
  Full schema: `npx archik schema`.
115
120
 
@@ -126,7 +131,7 @@ npx archik affected --since main # changed files → nodes → dependent
126
131
  npx archik otel check --graph deps.json # edges vs a production service-dependency graph
127
132
  ```
128
133
 
129
- `validate` proves the model is internally consistent, `drift` that it matches the code, and `otel check` that it matches production traffic. `smells` needs no model: it reports folder loops with the real imports as evidence (only relative imports are resolved, so every loop is real) and points at the cheapest import to cut. Gate every commit locally:
134
+ `validate` proves the model is internally consistent, `drift` that it matches the code, and `otel check` that it matches production traffic. `smells` needs no model: it reports folder loops with the real imports as evidence (only relative imports are resolved, so every loop is real) and points at the cheapest import to cut. On existing code, `archik smells --update-baseline` saves today's findings as known debt, so `--fail-on-warn` fails only on new loops and growing files. Gate every commit locally:
130
135
 
131
136
  ```bash
132
137
  npx archik hooks install # pre-commit: archik validate
@@ -188,7 +193,7 @@ jobs:
188
193
  - uses: actions/checkout@v4
189
194
  - uses: bacharSalleh/archik@main
190
195
  with:
191
- smells-fail: true # optional gate; omit for report-only
196
+ smells-fail: true # optional gate; with a committed baseline, fails only on new smells
192
197
  ```
193
198
 
194
199
  Inputs: `path`, `working-directory`, `validate`, `drift`, `smells-fail`, `compare-ref`, `comment`, `github-token`, `version`.
@@ -207,7 +212,7 @@ Every command supports `--help`; agent-facing commands support `--json`.
207
212
  | `archik dev` / `start` / `stop` / `status` | Live canvas lifecycle (foreground / detached) |
208
213
  | `archik validate [path]` | Schema + cross-file + constraints (exit 1 on error) |
209
214
  | `archik complexity [path]` | Flag over-large files, hub nodes, deep nesting (`--fail-on-warn` to gate) |
210
- | `archik smells [dir]` | Folder import loops + oversized source files, from the code (`--max-file-lines`, `--fail-on-warn`) |
215
+ | `archik smells [dir]` | Folder import loops + oversized source files, from the code (`--max-file-lines`, `--fail-on-warn`, `--update-baseline`) |
211
216
  | `archik render --out <svg>` | Headless SVG render (`--focus <id>`, `--hide-structural`) |
212
217
  | `archik watch` | Re-render SVG on every change |
213
218
  | `archik q <sub>` | Query: `describe` `deps` `dependents` `neighbors` `impact` `list` `edges` `stats` |
@@ -215,7 +220,7 @@ Every command supports `--help`; agent-facing commands support `--json`.
215
220
  | `archik affected` | Changed files → nodes, dependents, model files, unmapped (`--since <ref>`, `--files`) |
216
221
  | `archik drift` | sourcePath gaps (`--edges` verifies edges vs the import graph) |
217
222
  | `archik otel check --graph <f>` | Verify edges against a production service-dependency graph |
218
- | `archik suggest <sub>` | Suggestion sidecar lifecycle: `show` `set` `accept` `reject` |
223
+ | `archik suggest <sub>` | Suggestion sidecar lifecycle: `show` `set` `accept` `reject` — accept writes the decision record to `.archik/decisions/` |
219
224
  | `archik evolution <sub>` | Self-evolution loop: `enable` `reflect` `proposals` `approve` `reject` `report` |
220
225
  | `archik patterns <sub>` | Pattern library: `list` `show <id>` `apply <id>` |
221
226
  | `archik import compose\|mermaid [file]` | Bootstrap from docker-compose or a Mermaid flowchart |
@@ -224,7 +229,8 @@ Every command supports `--help`; agent-facing commands support `--json`.
224
229
  | `archik owners sync\|check` | Keep CODEOWNERS in step with node owners |
225
230
  | `archik mcp` | MCP server over stdio for non-Claude-Code agents |
226
231
  | `archik schema` | Print the document schema |
227
- | `archik upgrade` | Upgrade + refresh installed skill/commands |
232
+ | `archik upgrade` | Upgrade + refresh installed skill/commands (`--migrate` also runs `archik migrate` with the new version) |
233
+ | `archik migrate` | Bring the project's archik files up to the installed version — archives first, validates after (`--dry-run`) |
228
234
 
229
235
  Default file resolution: `.archik/main.archik.yaml`, falling back to the legacy `architecture.archik.yaml` (both present is an error).
230
236
 
@@ -238,6 +244,7 @@ Reach for archik when a project has more than a handful of components, ships wit
238
244
  | AI-editor integration | **Skill + MCP** | None | None |
239
245
  | Structural smells from code | **Yes** | No | No |
240
246
  | Drift detection | **Yes** | No | No |
247
+ | Decision records tied to model changes | **Yes** | No | No |
241
248
  | Governance constraints | **Yes** | No | No |
242
249
  | Validator | **Schema + cross-file + constraints** | Syntax only | Syntax only |
243
250
 
@@ -31,6 +31,11 @@ done at step 1 — the diagram changed; the code probably hasn't.
31
31
 
32
32
  3. **BUILD — plan (HITL).**
33
33
 
34
+ **Two-way door shortcut:** if `/archik:suggest` already showed the
35
+ build plan with this sidecar (two-way door), the accept you just
36
+ ran approved it — go straight to step 4. One-way doors always get
37
+ their own plan approval here.
38
+
34
39
  Translate the diagram delta into a numbered file-level
35
40
  plan and present it for approval **before** touching code:
36
41
  - Each new code-bearing node (`service`, `function`, `worker`,
@@ -42,6 +47,10 @@ done at step 1 — the diagram changed; the code probably hasn't.
42
47
  consumer handler; `writes` needs a repository method; etc).
43
48
  - Any node still `status: proposed` → flag it; code must land
44
49
  before flipping to `active`.
50
+ - If the accepted decision record has `crossCutting`, each
51
+ promise becomes a plan item: the security control, the signal
52
+ (log / metric / alert) and the rollback path (flag, revert,
53
+ migration down-step).
45
54
  - Default to **tests-first** when behaviour is clearly bounded.
46
55
  - If `superpowers:writing-plans` is available, use it; else
47
56
  inline.
@@ -84,6 +93,11 @@ done at step 1 — the diagram changed; the code probably hasn't.
84
93
  Catches folder loops and oversized files, with the real imports
85
94
  as evidence. A new loop is a gap — cut the cheapest import (or
86
95
  queue a `/archik:suggest`) before declaring the milestone done.
96
+ With a committed baseline (`.archik/smells-baseline.json`) only
97
+ findings marked **NEW** count; known debt is not this change's job.
98
+
99
+ For a one-way door, confirm each `crossCutting` promise from the
100
+ decision record is in the code before flipping nodes to `active`.
87
101
  `superpowers:verification-before-completion` when available.
88
102
  If `docs/architecture.svg` is committed, regenerate it:
89
103
  ```
@@ -64,6 +64,8 @@ brief and start the DESIGN loop.
64
64
  > forces priorities into the open before any code lands. New
65
65
  > nodes start `status: proposed` (the code doesn't exist on disk
66
66
  > yet) and flip to `status: active` when the code lands in BUILD.
67
+ > Only the first milestone is modelled in detail; later areas stay
68
+ > coarse placeholders until their turn.
67
69
  > The commitment lives in the YAML, not in the chat log."
68
70
  5. When the brief lands, run the standard DESIGN loop:
69
71
  `/archik:suggest` (structural sidecar) → `/archik:accept` →
@@ -91,7 +93,9 @@ diagram, then iterate from honest ground truth.
91
93
  duplicate them here.
92
94
  4. After the user accepts the spawn sidecar, suggest the natural
93
95
  follow-up: "Want to check the code for structural smells?
94
- `npx archik smells` finds folder loops and oversized files."
96
+ `npx archik smells` finds folder loops and oversized files — and
97
+ `--update-baseline` saves today's findings so CI fails only on new
98
+ ones."
95
99
 
96
100
  ### C. `.archik/` exists but the diagram is empty or near-empty
97
101
 
@@ -107,6 +107,13 @@ any file under `.archik/`.
107
107
  # full proposed end-state — every node, not just the delta
108
108
  edges:
109
109
  # ...
110
+ metadata:
111
+ suggestion:
112
+ decision:
113
+ context: <the smell and its evidence, e.g. the folder loop imports>
114
+ decision: <the refactor you chose>
115
+ alternatives: [<other fixes you weighed, incl. leaving it>]
116
+ consequences: <what gets easier and what it costs>
110
117
  YAML
111
118
  ```
112
119
 
@@ -4,7 +4,8 @@ description: Finish a migration — check the result and fix what the migrator f
4
4
 
5
5
  # /archik:migrate — check what the deterministic migration did
6
6
 
7
- `archik upgrade --migrate` already ran the **deterministic** migration:
7
+ `archik migrate` (or `archik upgrade --migrate`, which runs it through
8
+ the newly installed version) already ran the **deterministic** migration:
8
9
  it archived the old project, ran each pending step, validated, and
9
10
  advanced `.archik/.version`. The current steps are:
10
11
 
@@ -12,6 +13,9 @@ advanced `.archik/.version`. The current steps are:
12
13
  `.archik/main.archik.yaml`.
13
14
  - **#3** — strip retired node fields (`stereotype`, `seqFiles`) from the
14
15
  model files.
16
+ - **#4** — move retired use-case, sequence, actor, alpha and trace files
17
+ to `.archik/retired/`, strip retired fields from pending suggestions,
18
+ and flag code, CI and scripts that still use removed features.
15
19
 
16
20
  (#2, the old use-case back-fill, is retired and never runs.)
17
21
 
@@ -30,6 +34,23 @@ developer's only copy of the pre-migration project.
30
34
 
31
35
  1. **Read the migrator's output.** Any `ⓘ` line it printed is a task for
32
36
  you. If it printed none, the steps below are a quick check only.
37
+ The usual ones from 0.19 and older:
38
+ - **moved N retired files to `.archik/retired/`** — tell the user
39
+ they are kept only as history. Ask before deleting them. If a use
40
+ case explains *why* a structure exists, offer to capture that as a
41
+ decision record with the next `/archik:suggest` touching that area.
42
+ - **pending suggestion … has no decision record** — read it with
43
+ `npx archik suggest show`, then either re-stage it with a decision
44
+ record (`/archik:suggest`) or ask the user to reject it.
45
+ - **code imports `archik/trace`** — the recorder is gone. Remove the
46
+ `trace(...)` calls and the import from those test files; keep the
47
+ tests' real assertions. Run the tests afterwards.
48
+ - **workflow uses `trace-fail-on`** — replace it with
49
+ `smells-fail: true` (or drop it). On existing code, offer
50
+ `npx archik smells --update-baseline` first so CI fails only on
51
+ new smells.
52
+ - **package.json scripts call a removed command** — remove the
53
+ script or replace it (`archik smells`, `archik drift`).
33
54
 
34
55
  2. **Find the archived original.**
35
56
  ```bash
@@ -47,6 +68,9 @@ developer's only copy of the pre-migration project.
47
68
  npx archik drift
48
69
  npx archik smells
49
70
  ```
71
+ If `validate` reports `unrecognized key … removed in archik 0.20`,
72
+ the migration did not run with the new version — run
73
+ `npx archik migrate` and check again.
50
74
 
51
75
  4. **Fix gaps through the normal workflow.** If drift or the archive
52
76
  shows structure the model misses (a node, an edge, a `parentId`
@@ -55,7 +55,8 @@ Never `Read`/`Write`/`Edit` files under `.archik/`.
55
55
  (stages the blueprint as `status: proposed` nodes), then refine
56
56
  ids/names with a follow-up `suggest set`.
57
57
  - Tailored: author the full end-state and stage via
58
- `npx archik suggest set --note '…' - <<'YAML' … YAML`.
58
+ `npx archik suggest set --note '…' - <<'YAML' … YAML`, with a
59
+ decision record under `metadata.suggestion.decision` (required).
59
60
 
60
61
  6. **Wire the tests.** Name one test per loop step: "corrections are
61
62
  recorded", "insights become proposals", "approved change applies".
package/commands/spawn.md CHANGED
@@ -155,6 +155,13 @@ archik suggest set` stages it.
155
155
  name: <Id> Internals
156
156
  nodes: [ ... ]
157
157
  edges: [ ... ]
158
+ metadata:
159
+ suggestion:
160
+ decision:
161
+ context: <why this split is needed>
162
+ decision: <what you chose>
163
+ alternatives: [<option not chosen>]
164
+ consequences: <what gets easier and harder>
158
165
  YAML
159
166
  # mechanical: puts sub-file on disk so the main draft's
160
167
  # archikFile: pointer validates. NOT the user's review gate
@@ -191,9 +198,21 @@ archik suggest set` stages it.
191
198
  # full proposed end-state, with archikFile pointers
192
199
  edges:
193
200
  # ...
201
+ metadata:
202
+ suggestion:
203
+ decision:
204
+ context: <what the source tree shows and why it is split this way>
205
+ decision: <what you chose>
206
+ alternatives: [<option not chosen>]
207
+ consequences: <what gets easier and harder>
194
208
  YAML
195
209
  ```
196
210
 
211
+ Every draft needs its decision record — `suggest set` refuses
212
+ one without it. For a spawn, the context is what the source
213
+ tree shows; the alternatives are other ways to cut it (one
214
+ flat file, a different grouping).
215
+
197
216
  c. If `suggest set` reports validation errors, re-run with the
198
217
  corrected YAML. Never edit the sidecar by hand.
199
218
 
@@ -215,6 +234,12 @@ archik suggest set` stages it.
215
234
  `<a>` and `<b>`? The cheapest cut is `<file imports "specifier">`."*
216
235
  If it finds none, skip this line.
217
236
 
237
+ Existing code almost always has some debt. Also offer the
238
+ baseline so CI can gate on *new* smells from now on: *"Want me to
239
+ save today's findings as the baseline (`npx archik smells
240
+ --update-baseline`, commit `.archik/smells-baseline.json`)? Then
241
+ `--fail-on-warn` only fails on new loops or growing files."*
242
+
218
243
  Do NOT fix smells here — spawn is descriptive, and the fix is a
219
244
  separate ask from the user. This note is a prompt, not an action.
220
245
 
@@ -26,7 +26,7 @@ the contract with the user.
26
26
 
27
27
  The skill defines a 5-phase loop: **Discover → Design → Decide → Build
28
28
  → Verify**. This command covers Discover (grounding) and Design
29
- (staging the sidecar with rationale), then hands off to the user's
29
+ (staging the sidecar with its decision record), then hands off to the user's
30
30
  review and the explicit Decide gate (`/archik:accept` or
31
31
  `/archik:reject`). Don't skip clarification just because a slash
32
32
  command was typed — clarification is what makes the draft good. Don't
@@ -113,23 +113,51 @@ start Build phase here; that's gated on accept.
113
113
  # full proposed end-state — every node, not just the delta
114
114
  edges:
115
115
  # full proposed end-state — every edge, not just the delta
116
+ metadata:
117
+ suggestion:
118
+ decision:
119
+ context: <the problem and the forces — facts, not the solution>
120
+ decision: <what you chose, 1–2 sentences>
121
+ alternatives:
122
+ - <a real option you weighed and did not choose>
123
+ consequences: <what gets easier AND what gets harder>
124
+ # crossCutting: # REQUIRED when the change adds data, an
125
+ # security: ... # outside system or public traffic
126
+ # observability: ...
127
+ # rollback: ...
128
+ # supersedes: ["0003"] # only when this reverses an earlier record
116
129
  YAML
117
130
  ```
118
131
 
132
+ The decision record is required — `suggest set` refuses a draft
133
+ without it, and accept writes it to
134
+ `.archik/decisions/NNNN-<slug>.md`. Before writing it, read the
135
+ past records for the area (`ls .archik/decisions/`, they are plain
136
+ markdown). If your change reverses one, list it in `supersedes`.
137
+
138
+ `suggest set` prints whether the change is a **one-way door** (hard
139
+ to undo: a new data store, queue/stream, external system,
140
+ gateway/auth/cdn, cloud or LLM node, a new edge to an external
141
+ system, a new top-level module, a removal, a boundary move) or a
142
+ **two-way door**. If it adds data, an outside system or public
143
+ traffic it refuses the draft until `crossCutting` says how it is
144
+ **secured** (who can reach it, secrets, data exposure),
145
+ **observed** (the signal that shows it working or failing) and
146
+ **rolled back** (how to undo it safely). Write real answers, not
147
+ placeholders — the plan must later land what you promise here.
148
+
119
149
  If the command exits non-zero, re-run with the corrected YAML.
120
150
  Never write a draft file under `.archik/` and never edit the
121
151
  sidecar directly.
122
152
 
123
- 5. **Narrate the design rationale** in 2–4 short bullets before
124
- handing off to review. The user needs to see *why* this shape, not
125
- just *what* it is. Cover:
126
- - Which **bounded context(s)** the change touches and why those
127
- boundaries.
128
- - The **separation of concerns** — what each new node owns and why
129
- it's its own node (not folded into an existing one).
130
- - **Async vs sync** choice and the reason (cross-context coupling
131
- should default to async).
132
- - Any **alternative you rejected** and the trade-off.
153
+ 5. **Summarise the decision record** in 2–4 short bullets before
154
+ handing off to review — the same content the record holds, so the
155
+ user can judge the *why* next to the diagram (the canvas also shows
156
+ it under **Why** on the review banner). Make sure it covers:
157
+ - Which **boundaries** the change touches and why those boundaries.
158
+ - What each new node owns and why it is its own node.
159
+ - **Async vs sync** choice and the reason.
160
+ - The **alternatives** you rejected and what the choice costs.
133
161
 
134
162
  Keep it tight — bullets, not paragraphs. The diagram does the rest.
135
163
 
@@ -141,6 +169,14 @@ start Build phase here; that's gated on accept.
141
169
  **reject** and tell me what didn't fit (boundary? relationship?
142
170
  scope? naming? composition? lifecycle?) so I can revise."
143
171
 
172
+ Match the gate to the door:
173
+ - **One-way door** — say so ("This is hard to undo: <reasons>")
174
+ and hand off the sidecar alone. The build plan comes after
175
+ accept, as its own approval gate.
176
+ - **Two-way door** — include the numbered build plan in this same
177
+ hand-off, and say that `/archik:accept` approves both the model
178
+ change and the plan.
179
+
144
180
  Do NOT pre-emptively start implementing. Wait for `/archik:accept`.
145
181
 
146
182
  ## Notes