@iceinvein/agent-skills 0.1.40 → 0.2.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 +18 -2
- package/dist/cli/index.js +105 -28
- package/package.json +1 -1
- package/skills/index.json +14 -2
- package/skills/magpie/SKILL.md +118 -40
- package/skills/magpie/bin/magpie.ts +43 -0
- package/skills/magpie/fixtures/fake-gh-nodiff.sh +38 -0
- package/skills/magpie/package.json +1 -1
- package/skills/magpie/references/peer-review.md +7 -2
- package/skills/magpie/references/specialists.md +38 -7
- package/skills/magpie/scripts/__tests__/cli.test.ts +101 -1
- package/skills/magpie/scripts/__tests__/dedupe-cmd.test.ts +187 -0
- package/skills/magpie/scripts/__tests__/diff-chunks.test.ts +51 -0
- package/skills/magpie/scripts/__tests__/filter-diff-preservation.test.ts +54 -0
- package/skills/magpie/scripts/__tests__/findings-files.test.ts +35 -0
- package/skills/magpie/scripts/__tests__/gh.test.ts +69 -0
- package/skills/magpie/scripts/__tests__/git-diff.test.ts +83 -0
- package/skills/magpie/scripts/__tests__/helpers/git-fixture.ts +47 -0
- package/skills/magpie/scripts/__tests__/path-filter.test.ts +27 -0
- package/skills/magpie/scripts/__tests__/render-cmd.test.ts +95 -0
- package/skills/magpie/scripts/__tests__/render-findings.test.ts +33 -0
- package/skills/magpie/scripts/__tests__/render-progress.test.ts +42 -0
- package/skills/magpie/scripts/__tests__/setup-cmd.test.ts +83 -1
- package/skills/magpie/scripts/__tests__/shard.test.ts +165 -0
- package/skills/magpie/scripts/__tests__/skill-lint.test.ts +96 -1
- package/skills/magpie/scripts/dedupe-cmd.ts +58 -3
- package/skills/magpie/scripts/diff-chunks.ts +28 -0
- package/skills/magpie/scripts/findings-files.ts +32 -0
- package/skills/magpie/scripts/gh.ts +64 -13
- package/skills/magpie/scripts/git-diff.ts +111 -0
- package/skills/magpie/scripts/path-filter.ts +9 -5
- package/skills/magpie/scripts/refresh.ts +8 -0
- package/skills/magpie/scripts/render-cmd.ts +28 -9
- package/skills/magpie/scripts/render-findings.ts +11 -1
- package/skills/magpie/scripts/render-progress.ts +6 -1
- package/skills/magpie/scripts/setup-cmd.ts +38 -1
- package/skills/magpie/scripts/shard.ts +171 -0
- package/skills/magpie/scripts/status-cmd.ts +4 -1
- package/skills/magpie/skill.json +2 -2
- package/skills/magpie/templates/styles.css +5 -0
- package/skills/migrate/README.md +194 -0
- package/skills/migrate/SKILL.md +197 -0
- package/skills/migrate/bin/migrate +15 -0
- package/skills/migrate/bin/migrate.ts +309 -0
- package/skills/migrate/biome.json +35 -0
- package/skills/migrate/bun.lock +24 -0
- package/skills/migrate/docs/architecture.md +294 -0
- package/skills/migrate/docs/reference.md +590 -0
- package/skills/migrate/fixtures/tiny-express/GROUND-TRUTH.md +39 -0
- package/skills/migrate/fixtures/tiny-express/app.js +29 -0
- package/skills/migrate/fixtures/tiny-express/cron.js +6 -0
- package/skills/migrate/fixtures/tiny-express/reports/daily-users.json +6 -0
- package/skills/migrate/fixtures/tiny-express/schema.sql +12 -0
- package/skills/migrate/fixtures/tiny-express/settings.json +4 -0
- package/skills/migrate/fixtures/tiny-express/views/users.html +9 -0
- package/skills/migrate/fixtures/tiny-webforms/Controllers/UsersController.cs +68 -0
- package/skills/migrate/fixtures/tiny-webforms/Default.aspx +7 -0
- package/skills/migrate/fixtures/tiny-webforms/Default.aspx.cs +14 -0
- package/skills/migrate/fixtures/tiny-webforms/GROUND-TRUTH.md +50 -0
- package/skills/migrate/fixtures/tiny-webforms/Integrations/BillingClient.cs +16 -0
- package/skills/migrate/fixtures/tiny-webforms/Jobs/NightlyDigestJob.cs +33 -0
- package/skills/migrate/fixtures/tiny-webforms/Reports/DailyUsers.rdl +11 -0
- package/skills/migrate/fixtures/tiny-webforms/Schema.sql +12 -0
- package/skills/migrate/fixtures/tiny-webforms/Site.master +16 -0
- package/skills/migrate/fixtures/tiny-webforms/Users.aspx +8 -0
- package/skills/migrate/fixtures/tiny-webforms/Users.aspx.cs +14 -0
- package/skills/migrate/fixtures/tiny-webforms/web.config +10 -0
- package/skills/migrate/install.sh +68 -0
- package/skills/migrate/package.json +17 -0
- package/skills/migrate/references/phases/enumerate.md +291 -0
- package/skills/migrate/references/phases/extract.md +652 -0
- package/skills/migrate/references/phases/parity.md +275 -0
- package/skills/migrate/references/phases/probe.md +135 -0
- package/skills/migrate/references/phases/queue.md +242 -0
- package/skills/migrate/references/phases/seam.md +416 -0
- package/skills/migrate/references/recipes/README.md +116 -0
- package/skills/migrate/references/recipes/aspnet.md +287 -0
- package/skills/migrate/references/run-ops.md +280 -0
- package/skills/migrate/scripts/__tests__/census.test.ts +775 -0
- package/skills/migrate/scripts/__tests__/check.test.ts +458 -0
- package/skills/migrate/scripts/__tests__/citations.test.ts +156 -0
- package/skills/migrate/scripts/__tests__/cli.test.ts +183 -0
- package/skills/migrate/scripts/__tests__/concurrency.test.ts +164 -0
- package/skills/migrate/scripts/__tests__/config.test.ts +112 -0
- package/skills/migrate/scripts/__tests__/e2e-express.test.ts +1093 -0
- package/skills/migrate/scripts/__tests__/e2e-webforms.test.ts +1276 -0
- package/skills/migrate/scripts/__tests__/e2e.test.ts +320 -0
- package/skills/migrate/scripts/__tests__/ids.test.ts +38 -0
- package/skills/migrate/scripts/__tests__/import.test.ts +155 -0
- package/skills/migrate/scripts/__tests__/init.test.ts +192 -0
- package/skills/migrate/scripts/__tests__/leaks.test.ts +176 -0
- package/skills/migrate/scripts/__tests__/lock.test.ts +183 -0
- package/skills/migrate/scripts/__tests__/paths.test.ts +129 -0
- package/skills/migrate/scripts/__tests__/phase-cmd.test.ts +151 -0
- package/skills/migrate/scripts/__tests__/phases.test.ts +70 -0
- package/skills/migrate/scripts/__tests__/queue.test.ts +475 -0
- package/skills/migrate/scripts/__tests__/report.test.ts +150 -0
- package/skills/migrate/scripts/__tests__/run-state.test.ts +136 -0
- package/skills/migrate/scripts/__tests__/status-reset.test.ts +318 -0
- package/skills/migrate/scripts/__tests__/store.test.ts +132 -0
- package/skills/migrate/scripts/__tests__/validate.test.ts +54 -0
- package/skills/migrate/scripts/census-cmd.ts +109 -0
- package/skills/migrate/scripts/census.ts +342 -0
- package/skills/migrate/scripts/check-cmd.ts +24 -0
- package/skills/migrate/scripts/check.ts +376 -0
- package/skills/migrate/scripts/citations.ts +92 -0
- package/skills/migrate/scripts/config.ts +237 -0
- package/skills/migrate/scripts/ids.ts +31 -0
- package/skills/migrate/scripts/import-cmd.ts +141 -0
- package/skills/migrate/scripts/init-cmd.ts +118 -0
- package/skills/migrate/scripts/leaks.ts +184 -0
- package/skills/migrate/scripts/lock.ts +188 -0
- package/skills/migrate/scripts/paths.ts +103 -0
- package/skills/migrate/scripts/phase-cmd.ts +63 -0
- package/skills/migrate/scripts/phases.ts +113 -0
- package/skills/migrate/scripts/queue-cmd.ts +98 -0
- package/skills/migrate/scripts/queue.ts +258 -0
- package/skills/migrate/scripts/report-cmd.ts +47 -0
- package/skills/migrate/scripts/report.ts +131 -0
- package/skills/migrate/scripts/reset-cmd.ts +120 -0
- package/skills/migrate/scripts/status-cmd.ts +52 -0
- package/skills/migrate/scripts/store.ts +159 -0
- package/skills/migrate/scripts/types.ts +137 -0
- package/skills/migrate/scripts/validate.ts +221 -0
- package/skills/migrate/skill.json +33 -0
- package/skills/migrate/templates/config.toml +27 -0
- package/skills/migrate/templates/queue-item.md +17 -0
- package/skills/migrate/tsconfig.json +18 -0
- package/skills/migrate/uninstall.sh +31 -0
- package/skills/sluice/SKILL.md +82 -0
- package/skills/sluice/references/deep-channel.md +94 -0
- package/skills/sluice/references/finish.md +35 -0
- package/skills/sluice/references/intent.md +29 -0
- package/skills/sluice/references/review.md +42 -0
- package/skills/sluice/references/root-cause.md +38 -0
- package/skills/sluice/references/show-or-say.md +36 -0
- package/skills/sluice/references/test-first.md +35 -0
- package/skills/sluice/references/verify.md +26 -0
- package/skills/sluice/skill.json +32 -0
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
# Phase 4: Parity
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
Assign an oracle to every requirement whose confidence is not `queued`, and
|
|
6
|
+
maintain the sanctioned-difference catalog for whatever legitimately cannot
|
|
7
|
+
match. Exit condition: no unsigned delta in `deltas.jsonl`, every non-queued
|
|
8
|
+
requirement carries a parity value, and `migrate phase parity --status
|
|
9
|
+
done` has run.
|
|
10
|
+
|
|
11
|
+
## Inputs
|
|
12
|
+
|
|
13
|
+
- `config.toml`: `target.parity_test_path`, the template every parity `ref`
|
|
14
|
+
must be built from by hand. Its shipped default is
|
|
15
|
+
`tests/parity/{capability}/{fr_slug}.test.ts`; probe.md is where an
|
|
16
|
+
operator would have hand-edited it to something else, so read it, never
|
|
17
|
+
assume the default.
|
|
18
|
+
- `.migrate/parity-basis.md`: hand-written prose from probe, carrying
|
|
19
|
+
whether the source is `runnable` or `source-only` and the detection
|
|
20
|
+
evidence behind that call. This phase does not redetect it; it reads what
|
|
21
|
+
probe already decided.
|
|
22
|
+
- The store: `requirements.jsonl` (every non-queued row needs a plan),
|
|
23
|
+
`deltas.jsonl` (existing sanctioned differences, checked before writing a
|
|
24
|
+
new rubric or a new delta rather than after).
|
|
25
|
+
|
|
26
|
+
## Procedure
|
|
27
|
+
|
|
28
|
+
**The three parity kinds, stated once, before anything is assigned.**
|
|
29
|
+
`parity.kind` is `golden-master`, `differential`, or `rubric`.
|
|
30
|
+
|
|
31
|
+
- **`golden-master`.** Capture the legacy system's actual output for a
|
|
32
|
+
fixed input once, and assert the target reproduces it exactly. Fits a
|
|
33
|
+
deterministic, replayable behavior: the same request into the same state
|
|
34
|
+
gets the same response every time, so one captured snapshot is a
|
|
35
|
+
reusable oracle.
|
|
36
|
+
- **`differential`.** Run both systems side by side on the same input and
|
|
37
|
+
diff the two live results, rather than trusting one frozen capture. Fits
|
|
38
|
+
a behavior whose *exact* output legitimately varies (a token, a
|
|
39
|
+
timestamp, a generated id) while the comparison that actually matters
|
|
40
|
+
(did both systems accept, reject, and decide the same way) still
|
|
41
|
+
automates cleanly.
|
|
42
|
+
- **`rubric`, with a `level` of `high`, `moderate`, `low`, or `unknown`.**
|
|
43
|
+
For when no automatable oracle exists at all: a `source-only` basis with
|
|
44
|
+
nothing to run, or a behavior that crosses a boundary neither capture nor
|
|
45
|
+
live diffing can reach (an external mail send, a third-party callback).
|
|
46
|
+
**Only `level: high` needs no queue id; `moderate`, `low`, and `unknown`
|
|
47
|
+
each require one**, because a rubric below `high` is itself a claim that
|
|
48
|
+
something is not fully known, and that claim needs an owner's eyes, not a
|
|
49
|
+
guess standing in for one.
|
|
50
|
+
|
|
51
|
+
A worked example, run against a real store, assigning all three kinds
|
|
52
|
+
across the requirements extract.md mined:
|
|
53
|
+
|
|
54
|
+
```json
|
|
55
|
+
{ "id": "UM-001", "parity": { "kind": "differential", "ref": "tests/parity/user-management/login.test.ts" } }
|
|
56
|
+
{ "id": "UM-002", "parity": { "kind": "golden-master", "ref": "tests/parity/user-management/list-users.test.ts" } }
|
|
57
|
+
{ "id": "UM-003", "parity": { "kind": "rubric", "level": "moderate", "queue": "q-parity-um-003-reset-flow" } }
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
(each shown here trimmed to its `id` and `parity` field; the real batch
|
|
61
|
+
carries every other required field for each row unchanged). UM-001 gets
|
|
62
|
+
`differential`: both systems get the same credentials, and while the issued
|
|
63
|
+
token differs, whether the attempt succeeds and what it rejects must match.
|
|
64
|
+
UM-002 gets `golden-master`: a `GET` with no side effects and no
|
|
65
|
+
input-dependent branching is exactly the deterministic case golden-master
|
|
66
|
+
fits. UM-003 gets `rubric:moderate`: its confidence was already `inferred`
|
|
67
|
+
in extract.md, since nothing in the source shows what happens when a reset
|
|
68
|
+
token is actually submitted, so no automated oracle has anything to run
|
|
69
|
+
against, and the `moderate` level needs the queue id it names.
|
|
70
|
+
|
|
71
|
+
`migrate import reqs batch.json` accepts this and prints `import reqs: 0
|
|
72
|
+
added, 3 updated, batch b-reqs-parity-001`: this is the write-back
|
|
73
|
+
`SKILL.md` calls out as load-bearing, in the same shape as extract's
|
|
74
|
+
disposition write-back. This import is the only writer of a *resolved*
|
|
75
|
+
`parity` value; the phase-status flip at the end of this phase does not
|
|
76
|
+
touch it, and neither does anything else short of `migrate reset --phase
|
|
77
|
+
parity`, which clears it back to `null` rather than resolving it.
|
|
78
|
+
|
|
79
|
+
**A sub-high rubric's queue id is checked by the refs gate, so file it in
|
|
80
|
+
the same pass, before any check that would otherwise name it dangling.**
|
|
81
|
+
UM-003's `moderate` level named `q-parity-um-003-reset-flow`; file it now:
|
|
82
|
+
|
|
83
|
+
```markdown
|
|
84
|
+
---
|
|
85
|
+
id: q-parity-um-003-reset-flow
|
|
86
|
+
severity: moderate
|
|
87
|
+
status: open
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Evidence
|
|
91
|
+
|
|
92
|
+
`UM-003` (password reset) has `confidence: inferred`: the source shows a
|
|
93
|
+
link is emailed and that account existence is not leaked, but nothing in
|
|
94
|
+
`AuthController.cs` shows what the token looks like, how long it lives, or
|
|
95
|
+
what happens when it is submitted. There is no fixture that can play back a
|
|
96
|
+
real reset end-to-end, so neither `golden-master` nor `differential` has
|
|
97
|
+
anything to run against.
|
|
98
|
+
|
|
99
|
+
## Options
|
|
100
|
+
|
|
101
|
+
(a) Ship a `rubric:low` plan now and revisit once the token-verification
|
|
102
|
+
question resolves. (b) Block parity on this FR until that question
|
|
103
|
+
resolves. (c) Ship `rubric:moderate`: enough is observable (email is sent,
|
|
104
|
+
no account-existence leak) to check by hand, but not enough for an
|
|
105
|
+
executable oracle.
|
|
106
|
+
|
|
107
|
+
## Recommendation
|
|
108
|
+
|
|
109
|
+
Recommend (c); `rubric:moderate` matches what is actually known today.
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
`migrate queue add q-parity-um-003-reset-flow.md` accepts this and prints
|
|
113
|
+
`queue add: q-parity-um-003-reset-flow [moderate]`.
|
|
114
|
+
|
|
115
|
+
**Show the substitution, because nothing else will.** `{capability}` is the
|
|
116
|
+
capability's own `slug` from `capabilities.jsonl`, already known.
|
|
117
|
+
`{fr_slug}` has no deriving code anywhere in this CLI: it is a short,
|
|
118
|
+
kebab-case name you choose by hand for what the requirement actually is
|
|
119
|
+
(`login`, `list-users`), not the arbitrary FR id (`UM-001` tells a reader of
|
|
120
|
+
the test tree nothing). This is hand work the same way writing
|
|
121
|
+
`capabilities.jsonl` itself is hand work in seam.md: nothing imports a
|
|
122
|
+
parity plan's `ref` against the template, checks that it resolves to a real
|
|
123
|
+
file, or even checks that it looks like the template at all. Verified on a
|
|
124
|
+
disposable copy of the store, not the running example (overwriting UM-001's
|
|
125
|
+
real plan here just to prove this point would only recreate the exact kind
|
|
126
|
+
of drift this manual exists to prevent): a `golden-master` row with
|
|
127
|
+
`"ref": "this/path/does/not/exist/anywhere.test.ts"`, matching neither the
|
|
128
|
+
template nor any real file, imports cleanly and passes `migrate check`
|
|
129
|
+
without a single violation. The convention is entirely this manual's
|
|
130
|
+
discipline; get the substitution right by hand, because no gate is behind
|
|
131
|
+
you if you do not.
|
|
132
|
+
|
|
133
|
+
**Deltas exist to record sanctioned differences, never to silence a real
|
|
134
|
+
failure.** State this before writing one, not after: a delta is a *reason*
|
|
135
|
+
a difference is acceptable, backed by a rationale a reviewer can check, not
|
|
136
|
+
a lever for making an inconvenient test pass. If a parity test fails and
|
|
137
|
+
the honest cause is "the requirement was wrong" or "the target has a bug,"
|
|
138
|
+
the fix is to correct the requirement or the target, never to paper over
|
|
139
|
+
the failure with a delta whose rationale was written after the fact to fit.
|
|
140
|
+
A delta's `parity_exclusion` field says precisely what a parity test may
|
|
141
|
+
not assert on, not that the whole area is exempt from comparison.
|
|
142
|
+
|
|
143
|
+
A worked example, run against a real store. The target sends password-reset
|
|
144
|
+
emails through an async queue; the legacy system sent them synchronously in
|
|
145
|
+
the request, so response timing between the two systems now legitimately
|
|
146
|
+
differs for reasons that have nothing to do with correctness.
|
|
147
|
+
|
|
148
|
+
```json
|
|
149
|
+
{
|
|
150
|
+
"id": "delta-async-email-delivery",
|
|
151
|
+
"scope": "Password reset email delivery timing (UM-003)",
|
|
152
|
+
"rationale": "The target sends reset emails through an async queue instead of synchronously in the request, so response timing legitimately differs from the legacy system.",
|
|
153
|
+
"parity_exclusion": "The UM-003 parity check must not assert on how soon the email was actually sent, only that a send was enqueued.",
|
|
154
|
+
"validation": "A separate async-delivery test in the greenfield-only suite confirms the queued job eventually sends the email; the parity suite does not re-prove it.",
|
|
155
|
+
"owner_signed": null
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
`migrate import deltas batch.json` accepts this (`owner_signed: null` is a
|
|
160
|
+
valid value while a delta is proposed but not yet ratified) and prints
|
|
161
|
+
`import deltas: 1 added, 0 updated, batch b-deltas-001`. Unsigned, it fails
|
|
162
|
+
its own gate; `migrate check --phase parity`, run for real right now,
|
|
163
|
+
reports:
|
|
164
|
+
|
|
165
|
+
```
|
|
166
|
+
deltas:
|
|
167
|
+
delta-async-email-delivery is not owner-signed
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Re-import the same id with `"owner_signed": "2026-08-07"` once an owner has
|
|
171
|
+
actually looked at it, and the gate clears; `deltas` never appears again in
|
|
172
|
+
the same store's `check` output.
|
|
173
|
+
|
|
174
|
+
### The split-suite discipline
|
|
175
|
+
|
|
176
|
+
Three suites, kept apart on purpose:
|
|
177
|
+
|
|
178
|
+
- **parity.** Tests whose whole job is proving the target matches the
|
|
179
|
+
legacy system, one per requirement's `parity.ref`. This is the only suite
|
|
180
|
+
a delta's `parity_exclusion` ever narrows.
|
|
181
|
+
- **greenfield-only.** Tests for target-only behavior with no legacy
|
|
182
|
+
analog: the async email queue itself, from the delta above, is exactly
|
|
183
|
+
this. Nothing here compares against the legacy system, because there is
|
|
184
|
+
nothing on the legacy side to compare against.
|
|
185
|
+
- **legacy-only.** Behavior deliberately not carried forward. An
|
|
186
|
+
`out-of-scope` element (`route-get-legacy-admin-tool`, from extract.md)
|
|
187
|
+
gets no parity test at all; there is no requirement to assign one to, and
|
|
188
|
+
writing one would imply a comparison this run explicitly decided not to
|
|
189
|
+
make.
|
|
190
|
+
|
|
191
|
+
### Parity coverage
|
|
192
|
+
|
|
193
|
+
**Every requirement whose confidence is not `queued` must carry a parity
|
|
194
|
+
value; a `queued` requirement is exempt.** The exemption exists because a
|
|
195
|
+
queued requirement's entire content, not just its oracle, is still
|
|
196
|
+
provisional: assigning it a parity plan before an owner has even confirmed
|
|
197
|
+
the requirement is real would be planning a test for something that might
|
|
198
|
+
not exist. Verified on a disposable copy of the store, using an extra
|
|
199
|
+
requirement never added to the running example: a requirement with
|
|
200
|
+
`confidence: {kind: queued, ...}` and `parity: null` produces no `parity`
|
|
201
|
+
gate violation; the same row with `confidence: confirmed` and
|
|
202
|
+
`parity: null` produces exactly one, naming the requirement's id. The
|
|
203
|
+
running example already shows this in the other direction, without needing
|
|
204
|
+
a separate copy: extract.md's own "What closes it" transcript names
|
|
205
|
+
`UM-001`, `UM-002`, and `UM-003` under `parity`, one line each, at the point
|
|
206
|
+
where all three are `confirmed` or `inferred` (never `queued`) and none yet
|
|
207
|
+
has a plan.
|
|
208
|
+
|
|
209
|
+
**The honest limit: a parity plan on record is a commitment, not a proof.**
|
|
210
|
+
`check`'s parity gate is satisfied once `parity` is a well-formed value; it
|
|
211
|
+
never runs `target.commands.test`, never opens the file the `ref` names,
|
|
212
|
+
and never confirms the test that file describes actually exists or passes.
|
|
213
|
+
Writing `{"kind": "golden-master", "ref": "..."}` and later writing the test
|
|
214
|
+
file at that path are two separate acts, and only the manual's own
|
|
215
|
+
discipline connects them.
|
|
216
|
+
|
|
217
|
+
## What closes it
|
|
218
|
+
|
|
219
|
+
`migrate check --phase parity` mid-run reads the same way extract's did:
|
|
220
|
+
noisy on the surfaces this scratch run never enumerated, and quiet on
|
|
221
|
+
everything parity itself owns once every non-queued requirement has a plan,
|
|
222
|
+
`q-parity-um-003-reset-flow` is filed (above), and every delta is signed.
|
|
223
|
+
Skip filing that queue item and `refs` reappears here, naming `UM-003` via
|
|
224
|
+
`parity.queue`, the same way `q-legacy-admin-tool` reappears in extract.md's
|
|
225
|
+
own check if that one is skipped. Run for real, right after the delta above
|
|
226
|
+
was signed:
|
|
227
|
+
|
|
228
|
+
```
|
|
229
|
+
4/5 mapped, 1 out-of-scope, 0 unaccounted
|
|
230
|
+
|
|
231
|
+
Violations (7):
|
|
232
|
+
census:
|
|
233
|
+
declared surface jobs has no lens census record; the lens did not run or did not close
|
|
234
|
+
declared surface reports has no lens census record; the lens did not run or did not close
|
|
235
|
+
declared surface screens has no lens census record; the lens did not run or did not close
|
|
236
|
+
declared surface integrations has no lens census record; the lens did not run or did not close
|
|
237
|
+
declared surface workflows has no lens census record; the lens did not run or did not close
|
|
238
|
+
declared surface settings has no lens census record; the lens did not run or did not close
|
|
239
|
+
run-state:
|
|
240
|
+
phase parity is running; every phase through parity must be done
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
Neither `deltas` nor `parity` appears: both are already clean at this
|
|
244
|
+
point. Flip the phase:
|
|
245
|
+
|
|
246
|
+
```
|
|
247
|
+
migrate phase parity --status done
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
## Degradation
|
|
251
|
+
|
|
252
|
+
- **`source.basis` is `source-only`.** No live legacy system to run a
|
|
253
|
+
`differential` against, and often nothing to capture a fresh
|
|
254
|
+
`golden-master` from either, unless an existing fixture or recorded
|
|
255
|
+
output in the source already plays that role. When neither is possible,
|
|
256
|
+
`rubric` is what remains; expect more `moderate`, `low`, and `unknown`
|
|
257
|
+
levels, and more queue items, on a `source-only` run than on a `runnable`
|
|
258
|
+
one.
|
|
259
|
+
- **The target's test command is still `init`'s placeholder.** A parity
|
|
260
|
+
plan can still be recorded (the gate only checks the value's shape); the
|
|
261
|
+
test itself has nowhere real to run yet. This is exactly the "commitment,
|
|
262
|
+
not proof" limit above, sharpest right after probe when `target.commands`
|
|
263
|
+
has not been wired up.
|
|
264
|
+
- **Genuinely unclear which rubric level applies.** Use `unknown` rather
|
|
265
|
+
than guessing a specific level to avoid a queue id; `unknown` still needs
|
|
266
|
+
one, so nothing is gained by picking a falsely specific level instead.
|
|
267
|
+
|
|
268
|
+
## Commands
|
|
269
|
+
|
|
270
|
+
```
|
|
271
|
+
migrate import deltas <batch.json>
|
|
272
|
+
migrate import reqs <batch.json>
|
|
273
|
+
migrate queue add <item.md>
|
|
274
|
+
migrate phase parity --status done
|
|
275
|
+
```
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# Phase 0: Probe
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
Detect the source stack, detect whether the source is runnable, interview for
|
|
6
|
+
the target profile, and confirm the surface set this run will enumerate.
|
|
7
|
+
Write `.migrate/config.toml` and `.migrate/parity-basis.md`. Every later phase
|
|
8
|
+
reads `config.toml`; deciding the runtime basis here means the enumerate
|
|
9
|
+
phase never has to re-check it, and no phase after this one probes the
|
|
10
|
+
source's runnability again.
|
|
11
|
+
|
|
12
|
+
Exit condition: `config.toml` exists, `parity-basis.md` carries the
|
|
13
|
+
detection evidence as prose, and `migrate phase probe --status done` has
|
|
14
|
+
run.
|
|
15
|
+
|
|
16
|
+
## Inputs
|
|
17
|
+
|
|
18
|
+
There is no `config.toml` and no store yet; this phase writes the first one.
|
|
19
|
+
`migrate init` refuses at exit 1 if `.migrate/config.toml` already exists, so
|
|
20
|
+
re-running probe on a live store means editing the file directly, not
|
|
21
|
+
re-running `init`.
|
|
22
|
+
|
|
23
|
+
What you read instead:
|
|
24
|
+
|
|
25
|
+
- The source checkout itself (read-only): manifest and build files,
|
|
26
|
+
dependency lockfiles, a `.git` directory or its absence, README and any
|
|
27
|
+
docs tree.
|
|
28
|
+
- The target repo: it must already be a git working copy (the store commits
|
|
29
|
+
inside it), and whatever `.gitignore` it already has.
|
|
30
|
+
- The operator: the target profile is an interview, not something detectable
|
|
31
|
+
from the source.
|
|
32
|
+
|
|
33
|
+
## Procedure
|
|
34
|
+
|
|
35
|
+
1. **Detect the source stack.** Read the manifest and build files. If
|
|
36
|
+
nothing in the checkout names a stack you can commit to, record
|
|
37
|
+
`unknown` rather than guessing. `unknown` is a valid value, not a failure:
|
|
38
|
+
it is what routes the enumerate phase into contract-only mode instead of
|
|
39
|
+
into the wrong stack's recipe, which is worse than no recipe at all.
|
|
40
|
+
|
|
41
|
+
2. **Detect whether the source is runnable.** Try to install dependencies,
|
|
42
|
+
build, and start it, in whatever order the stack suggests. Write every
|
|
43
|
+
probe command you ran and its actual output to `.migrate/parity-basis.md`
|
|
44
|
+
as prose, along with any dependency gap or environmental blocker you hit.
|
|
45
|
+
This is prose, not a census record, because it is an argument for the
|
|
46
|
+
basis you are about to declare, not a count anything can balance. Decide
|
|
47
|
+
`runnable` or `source-only` from that evidence and pass it to `--basis`.
|
|
48
|
+
|
|
49
|
+
3. **Interview for the target profile.** Ask for: a name, the target stack,
|
|
50
|
+
the layout (which directories hold which part of the target), the
|
|
51
|
+
commands that test, lint, and build it, and `parity_test_path` (the path
|
|
52
|
+
template later phases will write parity tests under, for example
|
|
53
|
+
`tests/parity/{capability}/{fr_slug}.test.ts`).
|
|
54
|
+
|
|
55
|
+
4. **Confirm or replace the default surface set.** The default is
|
|
56
|
+
`["routes", "tables", "jobs", "reports", "screens", "integrations",
|
|
57
|
+
"workflows", "settings"]`. This is written by `migrate init` and is not
|
|
58
|
+
yours to change through a flag: `init` takes no surface-set argument at
|
|
59
|
+
all. If the default fits the source, leave it. If it does not, this is
|
|
60
|
+
the single largest source-genericity lever in the whole tool, and it
|
|
61
|
+
costs one config key. A COBOL source, for example, declares:
|
|
62
|
+
|
|
63
|
+
```toml
|
|
64
|
+
[surfaces]
|
|
65
|
+
types = ["programs", "copybooks", "jcl-jobs", "bms-maps", "datasets"]
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Hand-edit `[surfaces].types` in `config.toml` to replace it. Every
|
|
69
|
+
downstream gate reads the declared set, not the default, so this one edit
|
|
70
|
+
is what makes the rest of the run track a non-.NET source honestly
|
|
71
|
+
instead of forcing it through a shape that does not fit.
|
|
72
|
+
|
|
73
|
+
Element ids derive from the surface name with a trailing `s` stripped
|
|
74
|
+
(`tables` -> `table-...`). If a declared surface is already singular but
|
|
75
|
+
ends in `s` anyway (`status`, stripped naively to `statu-...`), add an
|
|
76
|
+
entry to `[surfaces.singular]` to override it, for example
|
|
77
|
+
`status = "status"`. `enumerate.md`'s Inputs section reads this table
|
|
78
|
+
when it derives ids; probe is the only phase that ever writes
|
|
79
|
+
`config.toml`, so an override missed here has no later phase to catch it
|
|
80
|
+
in.
|
|
81
|
+
|
|
82
|
+
`[target.layout]` and `[target.commands]` have the same property:
|
|
83
|
+
`init` writes them as an empty table and three placeholder `echo`
|
|
84
|
+
commands respectively, and nothing else fills them in. Hand-edit the
|
|
85
|
+
interview answers from step 3 into both before enumerate starts.
|
|
86
|
+
`target.parity_test_path` is different: `init` already writes a real
|
|
87
|
+
default, `tests/parity/{capability}/{fr_slug}.test.ts`, not a
|
|
88
|
+
placeholder, so it needs no edit when the operator's answer matches it.
|
|
89
|
+
When it does not (a different path convention, a different test file
|
|
90
|
+
extension), hand-edit `target.parity_test_path` in `[target]` the same
|
|
91
|
+
way, since nothing else will. Neither `SKILL.md` nor `docs/reference.md`
|
|
92
|
+
names this field, so this paragraph is its only documented home; the
|
|
93
|
+
parity phase is what reads it back.
|
|
94
|
+
|
|
95
|
+
## What closes it
|
|
96
|
+
|
|
97
|
+
There is no census kind for probe; it is not a lens, an attribute, a
|
|
98
|
+
rule-sweep, or a closer, so nothing balances here. The phase closes on the
|
|
99
|
+
artifacts existing and the status flip:
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
migrate init --source /abs/path/to/legacy --scope "user management module" \
|
|
103
|
+
--name nexus-workforce --source-stack aspnet-webforms \
|
|
104
|
+
--target-stack "dotnet-10 + vue3" --basis runnable
|
|
105
|
+
migrate phase probe --status done
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
`init` exits 1 if `config.toml` already exists, and 2 if `--source` is
|
|
109
|
+
missing, is not a directory, or `--basis` is not `runnable` or
|
|
110
|
+
`source-only`. Confirm the write with `migrate status`, which prints the
|
|
111
|
+
detected stack and basis on its first line.
|
|
112
|
+
|
|
113
|
+
Running `migrate check --phase probe` here will not come back clean: the
|
|
114
|
+
census gate reads the whole store regardless of `--phase`, so it reports
|
|
115
|
+
every declared surface's lens record and every declared closer's record as
|
|
116
|
+
missing, correctly, because none of them exist yet. That is not a probe
|
|
117
|
+
defect; it is the same "other nine gates read the whole store" behavior
|
|
118
|
+
`SKILL.md` describes, and it is why probe's own close is the status flip
|
|
119
|
+
above, not a clean `check`.
|
|
120
|
+
|
|
121
|
+
## Degradation
|
|
122
|
+
|
|
123
|
+
| Absent | Record |
|
|
124
|
+
|---|---|
|
|
125
|
+
| No VCS in the source | `vcs = "none"`. `init` detects this from the absence of `.git` and writes it for you; nothing to hand-edit. |
|
|
126
|
+
| No runnable environment | `basis = "source-only"`, plus the blocking evidence (missing SDK, a dependency that will not install, an environment nothing here can reach) written to `parity-basis.md`. This is the fact the runtime lens and the parity phase both read later: getting it right once here is the point of moving basis detection to phase 0 at all. |
|
|
127
|
+
| No documentation | Note it in `parity-basis.md` now (no `docs/` tree, no wiki export, nothing beyond a generated README). This does not close anything by itself, but it means the enumerate phase's docs lens can open with `not-applicable:no-documentation` immediately instead of re-discovering the same absence. |
|
|
128
|
+
|
|
129
|
+
## Commands
|
|
130
|
+
|
|
131
|
+
```
|
|
132
|
+
migrate init --source <path> --scope "<text>" --name <target> \
|
|
133
|
+
[--source-stack <s>] [--target-stack <s>] [--basis <runnable|source-only>]
|
|
134
|
+
migrate phase probe --status done
|
|
135
|
+
```
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
# Phase 5: Queue
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
Carry forward, for an owner to adjudicate, everything any phase could not
|
|
6
|
+
resolve on its own: evidence, the real options, and a recommendation.
|
|
7
|
+
Exit condition: every item filed anywhere in the run so far is
|
|
8
|
+
grammatically valid, every id the referential-integrity gate actually
|
|
9
|
+
checks resolves to a real queue file, and `migrate phase queue --status
|
|
10
|
+
done` has run. It is not "the queue is empty": nothing in this milestone
|
|
11
|
+
adjudicates an item, so a healthy run through this phase still ends with
|
|
12
|
+
open items, deliberately.
|
|
13
|
+
|
|
14
|
+
## Inputs
|
|
15
|
+
|
|
16
|
+
- The store: `.migrate/queue/`, already holding whatever `migrate queue
|
|
17
|
+
add` has filed from any earlier phase. This phase reads what already
|
|
18
|
+
exists; it does not start a new file of its own the way `elements.jsonl`
|
|
19
|
+
or `requirements.jsonl` does.
|
|
20
|
+
- `templates/queue-item.md`: the skeleton every filed item should start
|
|
21
|
+
from. It carries the same three fields and three headings this manual's
|
|
22
|
+
grammar section states below, no more and no fewer.
|
|
23
|
+
|
|
24
|
+
## Procedure
|
|
25
|
+
|
|
26
|
+
**The queue is cross-cutting, populated from any phase, not a phase that
|
|
27
|
+
runs once.** Every earlier manual in this set files items directly:
|
|
28
|
+
enumerate.md's zero-modularity escalation, extract.md's attribute and
|
|
29
|
+
rule-sweep and closer findings, parity.md's sub-high rubrics. This phase's
|
|
30
|
+
job is not to invent new items; it is to make sure everything already filed
|
|
31
|
+
is well-formed and everything the gate can check actually resolves, and
|
|
32
|
+
then to close.
|
|
33
|
+
|
|
34
|
+
**The grammar, stated once, before any example.** A queue item is a
|
|
35
|
+
markdown file whose stem matches its own `id`. Frontmatter carries `id`
|
|
36
|
+
(`q-` plus a lowercase kebab-case slug), `severity` (`critical`,
|
|
37
|
+
`moderate`, or `minor`), and `status` (`open`, or `adjudicated` with a
|
|
38
|
+
`ruling`). The body carries exactly three level-two headings, in any
|
|
39
|
+
order, case-sensitive and line-anchored (`## Evidence`, `## Options`,
|
|
40
|
+
`## Recommendation`), and **all three sections must be non-empty**. Missing
|
|
41
|
+
and empty are reported as distinguishable errors, not folded into one
|
|
42
|
+
generic complaint, so the fix is obvious from the message alone.
|
|
43
|
+
|
|
44
|
+
A worked example, the same file extract.md filed (built, in turn, on
|
|
45
|
+
`templates/queue-item.md`), run against a real store:
|
|
46
|
+
|
|
47
|
+
```markdown
|
|
48
|
+
---
|
|
49
|
+
id: q-reset-token-verify-missing
|
|
50
|
+
severity: critical
|
|
51
|
+
status: open
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Evidence
|
|
55
|
+
|
|
56
|
+
`read-write-symmetry` checked every write path against a matching read
|
|
57
|
+
path. `ResetPassword` writes a reset token via `GenerateResetToken` and
|
|
58
|
+
emails it, but no controller in the source reads or verifies a submitted
|
|
59
|
+
token: there is no `POST /api/password-reset/confirm` or equivalent. Either
|
|
60
|
+
the verification endpoint exists somewhere this pass did not look, or reset
|
|
61
|
+
tokens are issued and never checked.
|
|
62
|
+
|
|
63
|
+
## Options
|
|
64
|
+
|
|
65
|
+
(a) Widen the search (other controllers, an area folder, a separate
|
|
66
|
+
service) before concluding it is missing. (b) Treat it as a real gap and
|
|
67
|
+
flag it for the target to fix, not replicate. (c) Ask the operator directly
|
|
68
|
+
whether reset ever worked end-to-end in production.
|
|
69
|
+
|
|
70
|
+
## Recommendation
|
|
71
|
+
|
|
72
|
+
Recommend (c); a write with no matching read is exactly what this closer
|
|
73
|
+
exists to catch, and only the operator can say whether it is a real defect
|
|
74
|
+
or evidence this pass has not looked far enough yet.
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
`migrate queue add q-reset-token-verify-missing.md` accepts this and prints
|
|
78
|
+
`queue add: q-reset-token-verify-missing [critical]`.
|
|
79
|
+
|
|
80
|
+
### What the grammar rejects
|
|
81
|
+
|
|
82
|
+
Each of these, run against a real store, is refused before the file is ever
|
|
83
|
+
copied into `.migrate/queue/`; a rejected `queue add` never leaves a
|
|
84
|
+
half-written file behind.
|
|
85
|
+
|
|
86
|
+
- **Filename does not match `id`.** A file named `q-bad-mismatch.md` whose
|
|
87
|
+
frontmatter says `id: q-something-else`:
|
|
88
|
+
`filename q-bad-mismatch does not match id q-something-else`, exit 1.
|
|
89
|
+
- **A section is missing entirely.** No `## Options` heading anywhere in
|
|
90
|
+
the body: `missing ## Options section (a line reading exactly "##
|
|
91
|
+
Options", case-sensitive)`, exit 1.
|
|
92
|
+
- **A section is present but empty.** A `## Options` heading with nothing
|
|
93
|
+
before the next heading: `## Options section is empty`, exit 1.
|
|
94
|
+
- **No frontmatter block at all.** A file that never opens with `---\n`:
|
|
95
|
+
`missing --- frontmatter block`, exit **2**, not 1. This is the one
|
|
96
|
+
grammar failure that is a usage error rather than a content failure: the
|
|
97
|
+
file never resolved to a queue item in the first place, the same class as
|
|
98
|
+
a missing file or an unreadable one.
|
|
99
|
+
- **An invalid severity.** `severity: urgent`: `severity must be one of
|
|
100
|
+
critical, moderate, minor, got urgent`, exit 1.
|
|
101
|
+
|
|
102
|
+
Two more exist that are just as real but need a longer setup to trigger
|
|
103
|
+
faithfully rather than trust secondhand: an `id` that is not `q-` plus a
|
|
104
|
+
lowercase kebab-case slug, and a duplicate `## Evidence` heading (reported
|
|
105
|
+
as a duplicate, never silently taking the first and dropping the rest).
|
|
106
|
+
Both are enforced the same way, by name, before the file is copied.
|
|
107
|
+
|
|
108
|
+
### Severity, and why the list is ordered
|
|
109
|
+
|
|
110
|
+
**`queue list` sorts by severity first (`critical`, `moderate`, `minor`, in
|
|
111
|
+
that order), then by id.** This is not cosmetic: the queue is meant to be
|
|
112
|
+
adjudicated top to bottom in one sitting, and an owner working that way
|
|
113
|
+
should see the item that most needs a decision first, every time, not
|
|
114
|
+
whatever happened to be filed most recently. Write each item short enough
|
|
115
|
+
that one pass through the whole list is actually plausible; a queue item
|
|
116
|
+
that takes a page to explain a one-line decision has failed its own point
|
|
117
|
+
just as much as one with no evidence at all.
|
|
118
|
+
|
|
119
|
+
A worked example: `migrate queue list`, run against a real store with five
|
|
120
|
+
items filed across extract.md and parity.md's examples, prints:
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
q-reset-token-verify-missing critical open
|
|
124
|
+
q-account-lockout-scope moderate open
|
|
125
|
+
q-parity-um-003-reset-flow moderate open
|
|
126
|
+
q-users-islocked-semantics moderate open
|
|
127
|
+
q-legacy-admin-tool minor open
|
|
128
|
+
5 item(s)
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
The three `moderate` items sort by id alone (`account-lockout-scope` before
|
|
132
|
+
`parity-um-003-reset-flow` before `users-islocked-semantics`), since
|
|
133
|
+
severity does not separate them. When genuinely unsure which severity
|
|
134
|
+
fits, lean toward the one that puts the item in front of the owner sooner:
|
|
135
|
+
a real ambiguity mislabeled `minor` can sit unread far longer than the same
|
|
136
|
+
ambiguity mislabeled one tier too high ever costs.
|
|
137
|
+
|
|
138
|
+
### Referential integrity
|
|
139
|
+
|
|
140
|
+
**The gate checks exactly three fields against real queue files, by name,
|
|
141
|
+
and no others: `confidence.queue` on a requirement whose `confidence.kind`
|
|
142
|
+
is `queued`; `disposition.queue` on an element whose `disposition.kind` is
|
|
143
|
+
`out-of-scope`; and `parity.queue` on a requirement whose `parity.kind` is
|
|
144
|
+
`rubric` at any level below `high`.** State this before relying on it for
|
|
145
|
+
anything else, because the obvious-sounding generalization is wrong: a
|
|
146
|
+
census record's own `queued` array (on a `lens`, `attribute`, `rule-sweep`,
|
|
147
|
+
or `closer` record) is never cross-checked against a real queue file by any
|
|
148
|
+
gate. Verified on a disposable copy of the store, taken before extract.md's
|
|
149
|
+
own queue items were filed: a census record whose `queued` array names an
|
|
150
|
+
id with no file behind it still passes `migrate check` with zero `refs`
|
|
151
|
+
violations for that id, on that copy. Filing the file anyway is still this
|
|
152
|
+
manual's discipline, exactly as extract.md says, even though nothing
|
|
153
|
+
downstream will ever catch you if you skip it there.
|
|
154
|
+
|
|
155
|
+
A worked example of what the gate does check, run on a disposable copy so
|
|
156
|
+
the extra requirement and queue item below never enter the running example
|
|
157
|
+
(which by this point already has all five of its own items filed and would
|
|
158
|
+
otherwise read as six): a requirement with `confidence: {"kind": "queued",
|
|
159
|
+
"queue": "q-bulk-import-scope"}` and no such file on disk yet.
|
|
160
|
+
|
|
161
|
+
```
|
|
162
|
+
refs:
|
|
163
|
+
UM-005 references queue item q-bulk-import-scope via confidence.queue, which does not exist
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
`migrate queue add q-bulk-import-scope.md`, on that same disposable copy,
|
|
167
|
+
files the missing item; the very next `migrate check` no longer names it,
|
|
168
|
+
with no other change to that copy. The message names which field the
|
|
169
|
+
reference came from (`disposition.queue`, `confidence.queue`, or
|
|
170
|
+
`parity.queue`) precisely so that one requirement dangling from two
|
|
171
|
+
different fields at once reads as two separate things to fix, not one
|
|
172
|
+
ambiguous-looking duplicate.
|
|
173
|
+
|
|
174
|
+
## What closes it
|
|
175
|
+
|
|
176
|
+
There is no verb that empties the queue in this milestone; closing this
|
|
177
|
+
phase means every item filed so far is well-formed and every reference the
|
|
178
|
+
gate checks resolves, not that adjudication has happened. Run for real:
|
|
179
|
+
|
|
180
|
+
```
|
|
181
|
+
migrate phase queue --status done
|
|
182
|
+
phase: queue is now done
|
|
183
|
+
|
|
184
|
+
migrate check --phase queue
|
|
185
|
+
4/5 mapped, 1 out-of-scope, 0 unaccounted
|
|
186
|
+
|
|
187
|
+
Violations (6):
|
|
188
|
+
census:
|
|
189
|
+
declared surface jobs has no lens census record; the lens did not run or did not close
|
|
190
|
+
declared surface reports has no lens census record; the lens did not run or did not close
|
|
191
|
+
declared surface screens has no lens census record; the lens did not run or did not close
|
|
192
|
+
declared surface integrations has no lens census record; the lens did not run or did not close
|
|
193
|
+
declared surface workflows has no lens census record; the lens did not run or did not close
|
|
194
|
+
declared surface settings has no lens census record; the lens did not run or did not close
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
The six remaining lines are the same census noise every earlier manual in
|
|
198
|
+
this set already explains, not a queue defect: those six surfaces were
|
|
199
|
+
never enumerated in this scratch run. Closed for real, on the same store
|
|
200
|
+
with a zero-finding lens record recorded for each: `migrate check --phase
|
|
201
|
+
queue` exits 0 with no violations at all, confirming this phase's own
|
|
202
|
+
gates (`queue`, and the three `refs` fields above) were clean the whole
|
|
203
|
+
time and only the unrelated census gap was ever holding exit 0 back.
|
|
204
|
+
|
|
205
|
+
Plain `migrate check`, with no `--phase`, still cannot reach exit 0 in this
|
|
206
|
+
version, exactly as `SKILL.md` says: `adjudicate` and `handoff` have no
|
|
207
|
+
verb yet, so their phases stay `pending` forever this milestone, and
|
|
208
|
+
`run-state` names both by hand:
|
|
209
|
+
|
|
210
|
+
```
|
|
211
|
+
run-state:
|
|
212
|
+
phase adjudicate is pending; every phase through handoff must be done
|
|
213
|
+
phase handoff is pending; every phase through handoff must be done
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
`migrate check --phase queue` is the real terminus this milestone offers;
|
|
217
|
+
`migrate status` afterward is the plainer read, and it is what actually
|
|
218
|
+
hands off to phase 6: `5 open queue item(s) of 5`, `resume: adjudicate, no
|
|
219
|
+
batches yet`.
|
|
220
|
+
|
|
221
|
+
## Degradation
|
|
222
|
+
|
|
223
|
+
- **One malformed item among many well-formed ones.** `queue list`,
|
|
224
|
+
`queue show`, `check`, and `status` all keep going past it and report the
|
|
225
|
+
rest; one bad file never hides an entire directory's worth of good ones.
|
|
226
|
+
- **Genuinely unsure which severity to file under.** Covered above: lean
|
|
227
|
+
toward escalating rather than downgrading when truly unsure, since the
|
|
228
|
+
cost of a false escalation (an owner glances at it sooner than strictly
|
|
229
|
+
needed) is smaller than the cost of a false de-escalation (a real problem
|
|
230
|
+
waits at the bottom of the list).
|
|
231
|
+
- **A census record's own `queued` ids with no queue file behind them.**
|
|
232
|
+
Not caught by any gate, covered above; file them anyway, since a reviewer
|
|
233
|
+
reading this run against this manual will expect to find one.
|
|
234
|
+
|
|
235
|
+
## Commands
|
|
236
|
+
|
|
237
|
+
```
|
|
238
|
+
migrate queue add <item.md>
|
|
239
|
+
migrate queue list [--open]
|
|
240
|
+
migrate queue show <id>
|
|
241
|
+
migrate phase queue --status done
|
|
242
|
+
```
|