its-magic 0.1.2-29 → 0.1.2-32
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 +72 -16
- package/bin/its-magic.js +5 -0
- package/installer.ps1 +28 -7
- package/installer.py +218 -5
- package/installer.sh +28 -2
- package/package.json +1 -1
- package/template/.cursor/commands/architecture.md +8 -0
- package/template/.cursor/commands/auto.md +266 -11
- package/template/.cursor/commands/discovery.md +11 -0
- package/template/.cursor/commands/execute.md +23 -0
- package/template/.cursor/commands/intake.md +8 -0
- package/template/.cursor/commands/qa.md +6 -0
- package/template/.cursor/commands/refresh-context.md +18 -8
- package/template/.cursor/commands/release.md +9 -1
- package/template/.cursor/rules/quality.mdc +7 -0
- package/template/.cursor/scratchpad.local.example.md +50 -13
- package/template/.cursor/scratchpad.md +47 -10
- package/template/README.md +74 -20
- package/template/docs/engineering/context/installer-owned-paths.manifest +5 -1
- package/template/docs/engineering/phase-context.md +16 -0
- package/template/docs/engineering/runbook.md +234 -14
|
@@ -14,9 +14,9 @@
|
|
|
14
14
|
# - AUTO_PAUSE_POLICY: after_task|after_phase (safe stop boundary)
|
|
15
15
|
# - DONE: 0|1 (stop hook loops)
|
|
16
16
|
MAGIC_CONTEXT_STRICT=1
|
|
17
|
-
LOOP_UNTIL_GREEN=
|
|
17
|
+
LOOP_UNTIL_GREEN=1
|
|
18
18
|
RUN_TESTS_ON_EDIT=0
|
|
19
|
-
AUTO_IMPLEMENTATION_LOOP=
|
|
19
|
+
AUTO_IMPLEMENTATION_LOOP=1
|
|
20
20
|
AUTO_LOOP_MAX_CYCLES=5
|
|
21
21
|
AUTO_PAUSE_REQUEST=0
|
|
22
22
|
AUTO_PAUSE_POLICY=after_phase
|
|
@@ -42,9 +42,9 @@ MAGIC_BENCH_SESSION=
|
|
|
42
42
|
# - AUTO_EXECUTE_SELECTION: planned_then_priority
|
|
43
43
|
# - AUTO_TEAM_SCOPE_ENFORCE: 0|1 (when TEAM_MODE=1, enforce TEAM_MEMBER + ACTIVE_TASK_IDS)
|
|
44
44
|
AUTO_FLOW_MODE=auto_until_decision
|
|
45
|
-
PHASE_MODE=
|
|
46
|
-
PERMISSION_MODE=
|
|
47
|
-
AUTO_INSTALL_DEPS=
|
|
45
|
+
PHASE_MODE=auto
|
|
46
|
+
PERMISSION_MODE=auto
|
|
47
|
+
AUTO_INSTALL_DEPS=1
|
|
48
48
|
AUTO_RELEASE_NOTES=1
|
|
49
49
|
AUTO_BACKLOG_DRAIN=0
|
|
50
50
|
AUTO_BACKLOG_MAX_STORIES=1
|
|
@@ -56,6 +56,31 @@ AUTO_EXECUTE_ON_BLOCK=stop
|
|
|
56
56
|
AUTO_EXECUTE_SELECTION=planned_then_priority
|
|
57
57
|
AUTO_TEAM_SCOPE_ENFORCE=1
|
|
58
58
|
#
|
|
59
|
+
# `/auto` phase role policy (US-0069 / DEC-0051)
|
|
60
|
+
# - AUTO_ROLE_RESEARCH: po|tech-lead (empty -> default tech-lead)
|
|
61
|
+
# - AUTO_ROLE_PLAN_VERIFY: qa|tech-lead (empty -> default qa)
|
|
62
|
+
# - AUTO_ROLE_REFRESH_CONTEXT: curator|po (empty -> default curator)
|
|
63
|
+
# - AUTO_EXECUTE_ROLE_OVERRIDE: empty or allowed_non_dev_execute (execute default is dev)
|
|
64
|
+
# - EXECUTE_OVERRIDE_GOVERNANCE_REF: parseable waiver pointer (DEC-xxxx / state anchor) when override set
|
|
65
|
+
AUTO_ROLE_RESEARCH=
|
|
66
|
+
AUTO_ROLE_PLAN_VERIFY=
|
|
67
|
+
AUTO_ROLE_REFRESH_CONTEXT=
|
|
68
|
+
AUTO_EXECUTE_ROLE_OVERRIDE=
|
|
69
|
+
EXECUTE_OVERRIDE_GOVERNANCE_REF=
|
|
70
|
+
#
|
|
71
|
+
# `/auto` phase selection policy (US-0070 / DEC-0052)
|
|
72
|
+
# Exactly one active mode after merge; conflict -> PHASE_POLICY_CONFLICT (no plan).
|
|
73
|
+
# - AUTO_PHASE_PLAN: unset or full (default full canonical lifecycle)
|
|
74
|
+
# - AUTO_PHASE_EXCLUDE: csv of canonical phase ids (exclude from full)
|
|
75
|
+
# - AUTO_PHASE_INCLUDE: csv of canonical phase ids (re-sorted to canonical order)
|
|
76
|
+
# - AUTO_PHASE_PROFILE: named profile (see /auto + DEC-0052; unknown -> fail closed)
|
|
77
|
+
# - AUTO_PHASE_HIGH_RISK_ACK: required token when a high-risk profile demands it
|
|
78
|
+
AUTO_PHASE_PLAN=
|
|
79
|
+
AUTO_PHASE_EXCLUDE=
|
|
80
|
+
AUTO_PHASE_INCLUDE=
|
|
81
|
+
AUTO_PHASE_PROFILE=
|
|
82
|
+
AUTO_PHASE_HIGH_RISK_ACK=
|
|
83
|
+
#
|
|
59
84
|
# Team mode
|
|
60
85
|
# - TEAM_MODE: 0|1 (enable task/member scoped team workflow)
|
|
61
86
|
# - TEAM_MEMBER: short id for current developer
|
|
@@ -94,7 +119,7 @@ SYNC_CUSTOM_PHASES=
|
|
|
94
119
|
ALLOW_AUTO_PUSH=0
|
|
95
120
|
AUTO_PUSH_BRANCH_ALLOWLIST=
|
|
96
121
|
#
|
|
97
|
-
# Knowledge curation
|
|
122
|
+
# Knowledge curation
|
|
98
123
|
# - EARLY_RESEARCH: 0|1 (PO/TL search web during intake/architecture)
|
|
99
124
|
# - INTAKE_GUIDED_MODE: 0|1 (guided intake follow-up/options/research behavior)
|
|
100
125
|
# - INTAKE_SUBAGENT_FALLBACK: deny|allow (deny by default; when deny, missing
|
|
@@ -108,6 +133,10 @@ AUTO_PUSH_BRANCH_ALLOWLIST=
|
|
|
108
133
|
# archival rollover checks)
|
|
109
134
|
# - STATE_HOT_MAX_CHECKPOINTS: integer >= 10 (max recent checkpoints to retain
|
|
110
135
|
# in `state.md` after rollover)
|
|
136
|
+
# - PO_TO_TL_HOT_MAX_LINES: integer >= 200 (handoff hot-surface line cap)
|
|
137
|
+
# - PO_TO_TL_HOT_MAX_SECTIONS: integer >= 10 (max top-level ## sections retained)
|
|
138
|
+
# - ARCH_HOT_MAX_LINES: integer >= 500 (architecture hot-surface line cap)
|
|
139
|
+
# - ARCH_HOT_MAX_STORY_SECTIONS: integer >= 20 (max # US-xxxx story sections retained)
|
|
111
140
|
# - Manual-override precedence: explicit flag values in this file remain authoritative
|
|
112
141
|
# for that flag and override profile defaults.
|
|
113
142
|
EARLY_RESEARCH=1
|
|
@@ -117,8 +146,12 @@ ID_NAMESPACE_BOOTSTRAP=0
|
|
|
117
146
|
TOKEN_PROFILE=balanced
|
|
118
147
|
STATE_HOT_MAX_LINES=1200
|
|
119
148
|
STATE_HOT_MAX_CHECKPOINTS=80
|
|
149
|
+
PO_TO_TL_HOT_MAX_LINES=800
|
|
150
|
+
PO_TO_TL_HOT_MAX_SECTIONS=60
|
|
151
|
+
ARCH_HOT_MAX_LINES=3500
|
|
152
|
+
ARCH_HOT_MAX_STORY_SECTIONS=120
|
|
120
153
|
|
|
121
|
-
# Publish targets
|
|
154
|
+
# Publish targets (US-0054)
|
|
122
155
|
# - RELEASE_PUBLISH_MODE: disabled|confirm|auto
|
|
123
156
|
# - disabled: skip post-release publish target execution
|
|
124
157
|
# - confirm: require explicit operator confirmation before publish (default)
|
|
@@ -138,7 +171,7 @@ RELEASE_TARGETS_DEFAULT=
|
|
|
138
171
|
SECURITY_REVIEW=0
|
|
139
172
|
COMPLIANCE_PROFILES=GDPR
|
|
140
173
|
|
|
141
|
-
#
|
|
174
|
+
# Cross-repo compatibility observability
|
|
142
175
|
# - CROSS_REPO_OBSERVABILITY: 0|1 (enable compatibility visibility and checks)
|
|
143
176
|
# - COMPATIBILITY_GATE_ON_CRITICAL: 0|1 (when enabled, critical unresolved
|
|
144
177
|
# compatibility findings trigger decision gate before release)
|
|
@@ -148,15 +181,19 @@ CROSS_REPO_OBSERVABILITY=0
|
|
|
148
181
|
COMPATIBILITY_GATE_ON_CRITICAL=1
|
|
149
182
|
COMPATIBILITY_SOURCES=
|
|
150
183
|
|
|
151
|
-
# Component
|
|
184
|
+
# Component-scoped execution mode
|
|
152
185
|
# - COMPONENT_SCOPE_MODE: 0|1 (enable scoped planning/execution guardrails)
|
|
153
186
|
# - TARGET_COMPONENTS: comma-separated component IDs intended in scope
|
|
154
187
|
COMPONENT_SCOPE_MODE=0
|
|
155
188
|
TARGET_COMPONENTS=
|
|
156
189
|
|
|
157
|
-
# Optional
|
|
190
|
+
# Optional spec-pack documentation (US-0031)
|
|
158
191
|
# - SPEC_PACK_MODE: 0|1 (enable Design Concept, CRS, Technical Spec generation/validation; default 0)
|
|
159
192
|
# When 0, intake/architecture/release add no required spec-pack steps.
|
|
160
193
|
SPEC_PACK_MODE=0
|
|
194
|
+
|
|
195
|
+
# Optional user-guide documentation (US-0032)
|
|
196
|
+
# - USER_GUIDE_MODE: 0|1 (enable per-feature user guides at docs/user-guides/US-xxxx.md; default 0)
|
|
197
|
+
# When 0, intake/architecture/sprint-plan/execute/qa/release add no required user-guide steps or blocking checks.
|
|
161
198
|
USER_GUIDE_MODE=0
|
|
162
199
|
|
package/template/README.md
CHANGED
|
@@ -16,6 +16,8 @@ with pause/resume, decision gates, and persistent artifacts.
|
|
|
16
16
|
- Pause/resume with checkpoints (`handoffs/resume_brief.md`).
|
|
17
17
|
- Automated execute/QA loop with safety caps (optional).
|
|
18
18
|
- 3-layer quality chain: AI loop → local validate-and-push → CI auto-fix.
|
|
19
|
+
- User-visible metadata guard for operator-facing scripts/CLI (`US-0071` / `DEC-0053`):
|
|
20
|
+
`python scripts/check-user-visible-metadata.py` (see `docs/engineering/runbook.md`).
|
|
19
21
|
- CI/CD templates driven by `docs/engineering/runbook.md`.
|
|
20
22
|
- Team-friendly local overrides (`scratchpad.local.md`).
|
|
21
23
|
- Optional remote/docker execution and autonomous installs.
|
|
@@ -78,8 +80,13 @@ What upgrade does:
|
|
|
78
80
|
- **Framework files** (commands, rules, agents, hooks, skills, CI, scripts) are
|
|
79
81
|
updated to the latest version.
|
|
80
82
|
- **User data** (docs, sprints, handoffs, decisions, runbook) is never touched.
|
|
81
|
-
- **Mixed files** (
|
|
82
|
-
|
|
83
|
+
- **Mixed files** (`README.md`) are preserved. If the template version has new
|
|
84
|
+
content, a review notice is printed.
|
|
85
|
+
- **Scratchpad baseline (DEC-0055 / US-0073, Model B):** `.cursor/scratchpad.md`
|
|
86
|
+
is not copied as a manifest file; the installer **materializes** it from the
|
|
87
|
+
packaged template when missing and validates required merged keys (Python
|
|
88
|
+
required). Legacy repos that already committed `.cursor/scratchpad.md` keep it on
|
|
89
|
+
upgrade (not overwritten).
|
|
83
90
|
- A canonical version marker is stored at `its_magic/.its-magic-version` in your repo.
|
|
84
91
|
- Installer bootstrap is OS-aware + stack-aware for runbook command defaults
|
|
85
92
|
(`TEST_COMMAND`, optional `LINT_COMMAND`/`TYPECHECK_COMMAND`) and preserves
|
|
@@ -177,8 +184,8 @@ your-project/
|
|
|
177
184
|
.cursor/agents/ Subagent definitions
|
|
178
185
|
.cursor/skills/ Reusable skills
|
|
179
186
|
.cursor/hooks/ Automation hooks
|
|
180
|
-
.cursor/scratchpad.md
|
|
181
|
-
.cursor/scratchpad.local.example.md
|
|
187
|
+
.cursor/scratchpad.md Materialized shared defaults (Model B; not manifest-copied)
|
|
188
|
+
.cursor/scratchpad.local.example.md Framework default key catalog
|
|
182
189
|
docs/ Engineering & product docs, runbook
|
|
183
190
|
sprints/ Sprint tracking artifacts
|
|
184
191
|
handoffs/ Phase handoff artifacts
|
|
@@ -191,21 +198,38 @@ your-project/
|
|
|
191
198
|
|
|
192
199
|
### Team mode local overrides (recommended)
|
|
193
200
|
|
|
194
|
-
Use
|
|
201
|
+
Use three layers (merge precedence: **local > materialized baseline > example**,
|
|
202
|
+
`DEC-0055`):
|
|
195
203
|
|
|
196
|
-
-
|
|
197
|
-
-
|
|
204
|
+
- Framework catalog: `.cursor/scratchpad.local.example.md` (installed; refreshed on upgrade)
|
|
205
|
+
- Shared team baseline: `.cursor/scratchpad.md` (materialized on install when missing; commit as you prefer)
|
|
206
|
+
- Personal overrides: `.cursor/scratchpad.local.md` (gitignored; never overwritten by install/upgrade)
|
|
198
207
|
|
|
199
208
|
Setup:
|
|
200
209
|
|
|
201
|
-
1.
|
|
202
|
-
2.
|
|
203
|
-
3. Hook merges shared + local (local wins)
|
|
210
|
+
1. Run `its-magic` — baseline is materialized and merged validation runs (requires Python on PATH for `installer.ps1` / `installer.sh`).
|
|
211
|
+
2. Optionally copy `.cursor/scratchpad.local.example.md` to `.cursor/scratchpad.local.md` for personal values (`TEAM_MEMBER`, `ACTIVE_TASK_IDS`, …).
|
|
204
212
|
|
|
205
|
-
|
|
206
|
-
|
|
213
|
+
Recovery if `.cursor/scratchpad.md` is missing or merge validation fails:
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
python installer.py --scratchpad-postinstall --target . --mode missing
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
Upgrade behavior (US-0057 / DEC-0057):
|
|
220
|
+
- Aligns with **DEC-0039** (example vs local ownership), **DEC-0057** (example-first
|
|
221
|
+
ordering relative to baseline materialization), and Model B baseline rules below.
|
|
222
|
+
|
|
223
|
+
- `.cursor/scratchpad.local.example.md` is framework-owned and always refreshed from
|
|
224
|
+
the shipped template during post-install **before** baseline handling (`DEC-0057` **AC-1..AC-3**).
|
|
207
225
|
- `.cursor/scratchpad.local.md` is user-owned and preserved on `--mode upgrade`.
|
|
208
|
-
-
|
|
226
|
+
- Existing `.cursor/scratchpad.md` is left untouched on upgrade unless missing (then
|
|
227
|
+
materialized) or `overwrite` / fresh materialize paths apply (Model B).
|
|
228
|
+
- Installer output uses `[SCRATCHPAD_LAYER]` lines to distinguish example refresh,
|
|
229
|
+
baseline materialize/skip, and user-local preservation (`DEC-0057` **AC-5**).
|
|
230
|
+
- Paired catalog parity (baseline vs `.cursor/scratchpad.local.example.md`, active and
|
|
231
|
+
`template/`): `python scripts/check-scratchpad-pair-parity.py --repo .` (wired into
|
|
232
|
+
`tests/run-tests.ps1` / `tests/run-tests.sh`; **AC-11**).
|
|
209
233
|
|
|
210
234
|
Deterministic ordering behavior (US-0058):
|
|
211
235
|
- Mutable artifacts follow `docs/engineering/artifact-ordering-policy.md`.
|
|
@@ -383,9 +407,15 @@ Compaction behavior:
|
|
|
383
407
|
- Enforced rollover thresholds:
|
|
384
408
|
- `STATE_HOT_MAX_LINES` (default `1200`)
|
|
385
409
|
- `STATE_HOT_MAX_CHECKPOINTS` (default `80`)
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
410
|
+
- `PO_TO_TL_HOT_MAX_LINES` (default `800`)
|
|
411
|
+
- `PO_TO_TL_HOT_MAX_SECTIONS` (default `60`)
|
|
412
|
+
- `ARCH_HOT_MAX_LINES` (default `3500`)
|
|
413
|
+
- `ARCH_HOT_MAX_STORY_SECTIONS` (default `120`)
|
|
414
|
+
Triad hot surfaces (`state.md`, `handoffs/po_to_tl.md`,
|
|
415
|
+
`docs/engineering/architecture.md`) must stay within merged scratchpad caps.
|
|
416
|
+
Use `python scripts/enforce-triad-hot-surface.py --check` before completing a
|
|
417
|
+
phase that mutates them; use `--rollover` to archive oldest material into
|
|
418
|
+
deterministic packs when over cap (DEC-0054).
|
|
389
419
|
Archive verification mismatch fails with
|
|
390
420
|
`STATE_ARCHIVE_VERIFICATION_FAILED`.
|
|
391
421
|
|
|
@@ -545,12 +575,10 @@ Deterministic release semantics:
|
|
|
545
575
|
- Unresolved sprint identity or queue/notes mismatch fails closed with reason
|
|
546
576
|
codes and remediation guidance; no destructive reconciliation by default.
|
|
547
577
|
|
|
548
|
-
### Release gate chain (US-0039)
|
|
549
|
-
|
|
550
|
-
`/release` enforces mandatory gates in order: check-in test, QA completion, UAT completion, then finalization. Blank optional runbook keys do not block release. No bypass by default; override only via explicit decision gate.
|
|
551
|
-
|
|
552
578
|
### Post-QA release issue workflow (US-0042)
|
|
553
579
|
|
|
580
|
+
Release gate chain (US-0039): `/release` enforces mandatory gates in order — check-in test, QA completion, UAT completion — then finalization. Blank optional runbook keys (`LINT_COMMAND`, `TYPECHECK_COMMAND`) do not block release; they are reported as skipped.
|
|
581
|
+
|
|
554
582
|
If a problem appears **after QA** (during `/release`), record it separately from
|
|
555
583
|
QA findings:
|
|
556
584
|
|
|
@@ -621,6 +649,32 @@ Fail-closed reason codes:
|
|
|
621
649
|
`/auto`, `/verify-work`, and `/release` must validate these tuples before
|
|
622
650
|
continuation/finalization.
|
|
623
651
|
|
|
652
|
+
#### `/auto` phase→role enforcement (US-0069 / DEC-0051)
|
|
653
|
+
|
|
654
|
+
`/auto` uses a deterministic **phase→role matrix** plus scratchpad alternates
|
|
655
|
+
(`AUTO_ROLE_RESEARCH`, `AUTO_ROLE_PLAN_VERIFY`, `AUTO_ROLE_REFRESH_CONTEXT`).
|
|
656
|
+
Before each phase spawn it runs a **preflight capability gate**; missing
|
|
657
|
+
capability stops with `PHASE_ROLE_CAPABILITY_MISSING` (no unrelated-role
|
|
658
|
+
substitution). After each phase, isolation `role` and strict-proof `role` must
|
|
659
|
+
match the same expected role or the run stops with `PHASE_ROLE_MISMATCH`.
|
|
660
|
+
`execute` defaults to `dev`; non-`dev` requires
|
|
661
|
+
`AUTO_EXECUTE_ROLE_OVERRIDE=allowed_non_dev_execute` **and**
|
|
662
|
+
`EXECUTE_OVERRIDE_GOVERNANCE_REF` pointing to a parseable approved waiver. See
|
|
663
|
+
`docs/engineering/runbook.md` and `decisions/DEC-0051.md`.
|
|
664
|
+
|
|
665
|
+
#### `/auto` phase selection policy (US-0070 / DEC-0052)
|
|
666
|
+
|
|
667
|
+
`/auto` builds a **resolved phase plan** from scratchpad before spawning phases:
|
|
668
|
+
exactly one of `AUTO_PHASE_PLAN` (default `full`), `AUTO_PHASE_EXCLUDE`,
|
|
669
|
+
`AUTO_PHASE_INCLUDE`, or `AUTO_PHASE_PROFILE` applies; conflicting selectors
|
|
670
|
+
stop with `PHASE_POLICY_CONFLICT`. Non-skippable safety gates (`qa`,
|
|
671
|
+
`verify-work`, `release`) and evidence-chain closure reinstate omitted phases
|
|
672
|
+
with breadcrumb reasons such as `non_skippable_gate`. `start-from` and resume
|
|
673
|
+
anchors **intersect** with the plan (`START_FROM_PHASE_PLAN_EMPTY_INTERSECTION`
|
|
674
|
+
when empty). Backlog-drain, bulk execute, and team-mode runs **recompute** the
|
|
675
|
+
plan each boundary. See `/auto`, `docs/engineering/runbook.md`, and
|
|
676
|
+
`decisions/DEC-0052.md`.
|
|
677
|
+
|
|
624
678
|
### Lightweight interaction
|
|
625
679
|
|
|
626
680
|
Use `/ask` when you want to query the project without triggering the workflow:
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# its-magic installer ownership manifest
|
|
2
2
|
# Sections are line-based path lists.
|
|
3
|
+
#
|
|
4
|
+
# Model B baseline: materialized scratchpad (under .cursor/) is not manifest-copied;
|
|
5
|
+
# installers copy it from packaged template during post-install only. Framework-owned
|
|
6
|
+
# scratchpad.local.example (under .cursor/) refreshes from template before baseline
|
|
7
|
+
# handling in installer.py --scratchpad-postinstall (example-first ordering).
|
|
3
8
|
|
|
4
9
|
[install_include_paths]
|
|
5
10
|
.cursor/commands
|
|
@@ -8,7 +13,6 @@
|
|
|
8
13
|
.cursor/agents
|
|
9
14
|
.cursor/hooks
|
|
10
15
|
.cursor/hooks.json
|
|
11
|
-
.cursor/scratchpad.md
|
|
12
16
|
.cursor/scratchpad.local.example.md
|
|
13
17
|
docs
|
|
14
18
|
sprints
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Phase context pointers
|
|
2
|
+
|
|
3
|
+
Use this file as the **first** narrow read for workflow orientation. Expand to
|
|
4
|
+
linked hot or archive paths only when a question stays unresolved after the
|
|
5
|
+
default set (see minimal-read table in `docs/engineering/runbook.md`).
|
|
6
|
+
|
|
7
|
+
| Kind | Path | Notes |
|
|
8
|
+
|------|------|-------|
|
|
9
|
+
| Engineering state (hot) | `docs/engineering/state.md` | Recent checkpoints; archive under `docs/engineering/state-archive/` |
|
|
10
|
+
| Decisions index | `docs/engineering/decisions.md` | Compact index; full records under `decisions/` |
|
|
11
|
+
| PO → TL handoff (hot) | `handoffs/po_to_tl.md` | Narrative handoff; archive under `handoffs/archive/` |
|
|
12
|
+
| Architecture (hot) | `docs/engineering/architecture.md` | Story-shaped sections; archive under `docs/engineering/architecture-archive/` |
|
|
13
|
+
| Triad enforcement | `scripts/enforce-triad-hot-surface.py` | `--check` before phase completion when mutating triad surfaces |
|
|
14
|
+
|
|
15
|
+
Escalation: open the **named archive pack** cited in the latest rollover
|
|
16
|
+
verification tuple for the surface you need, not the entire archive tree.
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
TEST_COMMAND:
|
|
6
6
|
LINT_COMMAND:
|
|
7
7
|
TYPECHECK_COMMAND:
|
|
8
|
-
DEPLOY_STAGING_COMMAND:
|
|
9
|
-
DEPLOY_PROD_COMMAND:
|
|
8
|
+
DEPLOY_STAGING_COMMAND: echo "No staging deploy target configured for this repository"
|
|
9
|
+
DEPLOY_PROD_COMMAND: echo "No production deploy target configured for this repository"
|
|
10
10
|
|
|
11
11
|
LINT_FIX_COMMAND:
|
|
12
12
|
FORMAT_COMMAND:
|
|
@@ -26,9 +26,10 @@ TEST_TIMEOUT_SECONDS: 120
|
|
|
26
26
|
|
|
27
27
|
## Intentional empty commands (US-0015)
|
|
28
28
|
|
|
29
|
-
For this template/installer repository,
|
|
30
|
-
|
|
29
|
+
For this template/installer repository, the following command keys may be
|
|
30
|
+
intentionally empty in the shipped template; they are not configuration errors:
|
|
31
31
|
|
|
32
|
+
- `TEST_COMMAND` (blank until installer bootstrap per stack; **DEC-0056**)
|
|
32
33
|
- `LINT_COMMAND`
|
|
33
34
|
- `FORMAT_COMMAND`
|
|
34
35
|
- `TYPECHECK_COMMAND`
|
|
@@ -59,6 +60,60 @@ Remediation:
|
|
|
59
60
|
- define `TEST_COMMAND` explicitly in `docs/engineering/runbook.md`, or
|
|
60
61
|
- add detectable stack markers/scripts then rerun installer upgrade.
|
|
61
62
|
|
|
63
|
+
## User-visible internal metadata guard (US-0071 / DEC-0053)
|
|
64
|
+
|
|
65
|
+
**Goal:** keep planning-shaped identifiers out of **operator-visible software
|
|
66
|
+
channels** (CLI/installer/validate-and-push strings), while they remain valid in
|
|
67
|
+
internal documentation trees and in source comments that are not emitted to
|
|
68
|
+
users.
|
|
69
|
+
|
|
70
|
+
### Forbidden tokens (user-visible channels only)
|
|
71
|
+
|
|
72
|
+
Match planning-shaped tokens:
|
|
73
|
+
|
|
74
|
+
- `US-[0-9]{4}`
|
|
75
|
+
- `DEC-[0-9]{4}`
|
|
76
|
+
- `R-[0-9]{4}`
|
|
77
|
+
|
|
78
|
+
### Inclusive scan roots (deterministic)
|
|
79
|
+
|
|
80
|
+
From repository root, the checker walks **only**:
|
|
81
|
+
|
|
82
|
+
- `bin/**` (`*.js`)
|
|
83
|
+
- `installer.py`, `installer.ps1`, `installer.sh`
|
|
84
|
+
- `packaging/**` (`*.js`, `*.py`, `*.ps1`, `*.sh`)
|
|
85
|
+
- `scripts/validate-and-push.ps1`, `scripts/validate-and-push.sh`
|
|
86
|
+
|
|
87
|
+
Paths outside this set are **not** scanned by this tool (for example `docs/**`,
|
|
88
|
+
`.cursor/**`, `sprints/**`, `handoffs/**`, `decisions/**` remain free to use
|
|
89
|
+
story/decision/research IDs). If a new operator-visible deliverable is added
|
|
90
|
+
outside these roots, extend the scan list or you risk
|
|
91
|
+
`METADATA_SANITIZATION_SCOPE_AMBIGUOUS` classification during review.
|
|
92
|
+
|
|
93
|
+
### Command
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
python scripts/check-user-visible-metadata.py
|
|
97
|
+
python scripts/check-user-visible-metadata.py --json
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Reason codes (minimum)
|
|
101
|
+
|
|
102
|
+
- `USER_VISIBLE_INTERNAL_METADATA_DETECTED` — forbidden token matched inside a
|
|
103
|
+
scanned user-visible string/literal.
|
|
104
|
+
- `METADATA_SANITIZATION_POLICY_MISSING` — checker entrypoint missing or
|
|
105
|
+
unusable.
|
|
106
|
+
- `METADATA_SANITIZATION_SCOPE_AMBIGUOUS` — cannot classify whether a path
|
|
107
|
+
belongs in inclusive scan roots; treat as fail-closed until the runbook table
|
|
108
|
+
is updated.
|
|
109
|
+
|
|
110
|
+
### Findings / remediation (contract)
|
|
111
|
+
|
|
112
|
+
On failure, diagnostics must cite **evidence_ref** (`path:line:column` when
|
|
113
|
+
available), **token class** (`US` \| `DEC` \| `R`), and remediation: remove the
|
|
114
|
+
token from operator-visible strings; keep traceability in allowlisted internal
|
|
115
|
+
artifacts or non-emitting comments per `DEC-0053`.
|
|
116
|
+
|
|
62
117
|
## Guided intake mode (US-0033)
|
|
63
118
|
|
|
64
119
|
Intake interaction behavior is controlled by one switch in
|
|
@@ -212,15 +267,71 @@ Context compaction policy:
|
|
|
212
267
|
- Enforced rollover thresholds:
|
|
213
268
|
- `STATE_HOT_MAX_LINES` (default `1200`)
|
|
214
269
|
- `STATE_HOT_MAX_CHECKPOINTS` (default `80`)
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
270
|
+
- `PO_TO_TL_HOT_MAX_LINES` (default `800`)
|
|
271
|
+
- `PO_TO_TL_HOT_MAX_SECTIONS` (default `60`)
|
|
272
|
+
- `ARCH_HOT_MAX_LINES` (default `3500`)
|
|
273
|
+
- `ARCH_HOT_MAX_STORY_SECTIONS` (default `120`)
|
|
274
|
+
Thresholds resolve from merged `.cursor/scratchpad.md` +
|
|
275
|
+
`.cursor/scratchpad.local.md` (DEC-0054 triad contract).
|
|
276
|
+
When a cap is exceeded, the mutating phase must run rollover **before**
|
|
277
|
+
completion or fail closed (no successful completion with an oversize hot
|
|
278
|
+
surface).
|
|
279
|
+
|
|
280
|
+
### Triad hot-surface enforcement (DEC-0054)
|
|
281
|
+
|
|
282
|
+
Canonical hot/archive surfaces:
|
|
283
|
+
|
|
284
|
+
- `docs/engineering/state.md` → `docs/engineering/state-archive/state-pack-*.md`
|
|
285
|
+
- `handoffs/po_to_tl.md` → `handoffs/archive/po-to-tl-pack-*.md`
|
|
286
|
+
- `docs/engineering/architecture.md` →
|
|
287
|
+
`docs/engineering/architecture-archive/architecture-pack-*.md`
|
|
288
|
+
|
|
289
|
+
Operator commands:
|
|
290
|
+
|
|
291
|
+
```bash
|
|
292
|
+
python scripts/enforce-triad-hot-surface.py --check
|
|
293
|
+
python scripts/enforce-triad-hot-surface.py --rollover
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
- `--check` verifies all three surfaces are within policy (CI-safe).
|
|
297
|
+
- `--rollover` archives oldest contiguous units into the next deterministic pack
|
|
298
|
+
name; reruns are idempotent when already within caps.
|
|
299
|
+
- Successful rollover records a verification tuple:
|
|
300
|
+
`boundary`, `moved`, `retained` (counts / lines), `pack_ref`.
|
|
218
301
|
|
|
219
302
|
Rollover fail-safe reason codes:
|
|
220
303
|
|
|
221
304
|
- `STATE_ARCHIVE_BOUNDARY_AMBIGUOUS`
|
|
222
305
|
- `STATE_ARCHIVE_WRITE_FAILED`
|
|
223
306
|
- `STATE_ARCHIVE_VERIFICATION_FAILED`
|
|
307
|
+
- `STATE_ARCHIVE_REQUIRED`
|
|
308
|
+
- `ARTIFACT_HOT_SURFACE_OVERSIZE`
|
|
309
|
+
- `CONTEXT_BUDGET_EXCEEDED`
|
|
310
|
+
|
|
311
|
+
### Minimal-read defaults by phase (bounded escalation)
|
|
312
|
+
|
|
313
|
+
Read `docs/engineering/phase-context.md` first, then the **required** paths for
|
|
314
|
+
your phase. If unresolved, expand once to the **single** archive pack named in
|
|
315
|
+
the latest verification tuple for that surface. Do not load entire archive
|
|
316
|
+
directories by default.
|
|
317
|
+
|
|
318
|
+
| Phase | Required reads (default) | Combined line budget (guidance) |
|
|
319
|
+
|-------|--------------------------|----------------------------------|
|
|
320
|
+
| `/intake` | `phase-context.md`, target story in `docs/product/backlog.md`, `handoffs/po_to_tl.md` (tail) | ≤ 900 lines |
|
|
321
|
+
| `/discovery` | `phase-context.md`, `docs/product/vision.md` (story notes), `handoffs/po_to_tl.md` (tail) | ≤ 900 lines |
|
|
322
|
+
| `/research` | `phase-context.md`, `docs/engineering/research.md` (target entry), `docs/product/backlog.md` (target story) | ≤ 800 lines |
|
|
323
|
+
| `/architecture` | `phase-context.md`, `docs/engineering/architecture.md` (target story section), `docs/engineering/research.md` | ≤ 1200 lines |
|
|
324
|
+
| `/sprint-plan` | `phase-context.md`, `docs/engineering/architecture.md` (target story), `handoffs/tl_to_dev.md` | ≤ 1000 lines |
|
|
325
|
+
| `/plan-verify` | `phase-context.md`, `sprints/Sxxxx/tasks.md`, `docs/product/backlog.md` (ACs) | ≤ 900 lines |
|
|
326
|
+
| `/execute` | `phase-context.md`, `sprints/Sxxxx/tasks.md`, `handoffs/tl_to_dev.md` | ≤ 800 lines |
|
|
327
|
+
| `/qa` | `phase-context.md`, `sprints/Sxxxx/`, `tests/report.md` | ≤ 900 lines |
|
|
328
|
+
| `/verify-work` | `phase-context.md`, `sprints/Sxxxx/uat.json`, QA findings | ≤ 600 lines |
|
|
329
|
+
| `/release` | `phase-context.md`, release queue + sprint release findings | ≤ 700 lines |
|
|
330
|
+
| `/refresh-context` | `phase-context.md`, `docs/engineering/state.md` (tail), `docs/product/backlog.md` (status) | ≤ 900 lines |
|
|
331
|
+
| `/auto` (resolver) | `phase-context.md`, `handoffs/resume_brief.md`, `docs/engineering/state.md` (tail) | ≤ 700 lines |
|
|
332
|
+
|
|
333
|
+
If the default set is insufficient, escalate with an explicit note citing
|
|
334
|
+
`pack_ref`. Unbounded broad reads fail closed with `CONTEXT_BUDGET_EXCEEDED`.
|
|
224
335
|
|
|
225
336
|
`/ask` retrieval policy:
|
|
226
337
|
|
|
@@ -480,7 +591,7 @@ rewrite of unrelated backlog/acceptance/state/release artifacts.
|
|
|
480
591
|
- `BACKLOG_DONE_TRACEABILITY_MISSING` — Backlog DONE but traceability/state lacks entry.
|
|
481
592
|
Remediation: add traceability row in `docs/engineering/state.md` from backlog/release evidence or run backfill.
|
|
482
593
|
- `BACKLOG_DONE_RELEASE_ARTIFACT_MISSING` — Backlog DONE but release artifacts lack representation.
|
|
483
|
-
Remediation: ensure release notes or queue row exists for the story
|
|
594
|
+
Remediation: ensure release notes or queue row exists for the story’s sprint or run backfill.
|
|
484
595
|
|
|
485
596
|
**One-time backfill mode**: Explicit trigger (e.g. dedicated check or `/memory-audit`-related path).
|
|
486
597
|
- Run detection once over all DONE stories; for each legacy-drift story, perform
|
|
@@ -781,6 +892,86 @@ Boundary behavior:
|
|
|
781
892
|
isolation evidence checks.
|
|
782
893
|
- Pause/resume provenance must reference latest valid strict-proof boundary.
|
|
783
894
|
|
|
895
|
+
## Strict `/auto` phase→role enforcement (US-0069 / DEC-0051)
|
|
896
|
+
|
|
897
|
+
`/auto` must treat phase roles as a **fail-closed admission and checkpoint
|
|
898
|
+
contract** (see `decisions/DEC-0051.md` and `/auto` command text).
|
|
899
|
+
|
|
900
|
+
### Canonical matrix and scratchpad alternates
|
|
901
|
+
|
|
902
|
+
- Fixed phase→role defaults are documented in `/auto` (for example `execute` →
|
|
903
|
+
`dev`, `release` → `release`).
|
|
904
|
+
- Alternate phases resolve **one** expected role via scratchpad:
|
|
905
|
+
- `AUTO_ROLE_RESEARCH`: `po` \| `tech-lead` (empty → default `tech-lead`)
|
|
906
|
+
- `AUTO_ROLE_PLAN_VERIFY`: `qa` \| `tech-lead` (empty → default `qa`)
|
|
907
|
+
- `AUTO_ROLE_REFRESH_CONTEXT`: `curator` \| `po` (empty → default `curator`)
|
|
908
|
+
- Non-empty values outside the allowed set fail closed (no unrelated-role
|
|
909
|
+
substitution).
|
|
910
|
+
|
|
911
|
+
### Preflight and checkpoints
|
|
912
|
+
|
|
913
|
+
- **Preflight (before spawn)**: resolve expected role; verify the required
|
|
914
|
+
subagent capability exists. Missing capability → `PHASE_ROLE_CAPABILITY_MISSING`
|
|
915
|
+
with `phase_id`, expected role, observed result, remediation. Do not spawn a
|
|
916
|
+
substitute role.
|
|
917
|
+
- **Post-completion**: isolation evidence `role` and strict-proof `role` must
|
|
918
|
+
both match the same preflight-resolved role; else `PHASE_ROLE_MISMATCH`.
|
|
919
|
+
- **`proof_hash`**: SHA-256 over sorted-key JSON of the strict-proof tuple fields
|
|
920
|
+
(`orchestrator_run_id`, `runtime_proof_id`, `phase_id`, `role`,
|
|
921
|
+
`proof_issued_at`, `proof_ttl_seconds`).
|
|
922
|
+
|
|
923
|
+
### Execute default deny and rare override
|
|
924
|
+
|
|
925
|
+
- Default: `execute` requires `dev`.
|
|
926
|
+
- Override allowed only when **both** hold:
|
|
927
|
+
`AUTO_EXECUTE_ROLE_OVERRIDE=allowed_non_dev_execute` and
|
|
928
|
+
`EXECUTE_OVERRIDE_GOVERNANCE_REF` references a parseable approved exception (for
|
|
929
|
+
example `DEC-xxxx` or a documented state anchor).
|
|
930
|
+
|
|
931
|
+
### Continuation parity
|
|
932
|
+
|
|
933
|
+
- Every `/auto` run recomputes role policy and preflight; `start-from`, fresh
|
|
934
|
+
`resume_brief`, and `state.md` fallback cannot bypass the gate with stale role
|
|
935
|
+
intent alone.
|
|
936
|
+
|
|
937
|
+
## Configurable `/auto` phase plan (US-0070 / DEC-0052)
|
|
938
|
+
|
|
939
|
+
`/auto` schedules a **resolved ordered phase plan** from merged scratchpad
|
|
940
|
+
before any spawn. See `decisions/DEC-0052.md` and `/auto` command text.
|
|
941
|
+
|
|
942
|
+
### Selectors (exactly one active mode)
|
|
943
|
+
|
|
944
|
+
- `AUTO_PHASE_PLAN=full` (default when unset and no other selector is set)
|
|
945
|
+
- `AUTO_PHASE_EXCLUDE=<csv>` — remove listed canonical phase ids from `full`
|
|
946
|
+
- `AUTO_PHASE_INCLUDE=<csv>` — only listed ids, re-sorted into canonical lifecycle order
|
|
947
|
+
- `AUTO_PHASE_PROFILE=<name>` — expand a named profile (unknown → fail closed)
|
|
948
|
+
- `AUTO_PHASE_HIGH_RISK_ACK=<token>` — required when a documented high-risk profile demands acknowledgment
|
|
949
|
+
|
|
950
|
+
Conflicting selectors → `PHASE_POLICY_CONFLICT` (no plan materialization).
|
|
951
|
+
|
|
952
|
+
### Materialization and gates
|
|
953
|
+
|
|
954
|
+
- Expand → apply **non-skippable reinstatement** (`qa`, `verify-work`, `release`,
|
|
955
|
+
plus evidence-chain closure per `/auto`) → intersect **`start-from` / resume
|
|
956
|
+
anchor** with the plan → **empty intersection** →
|
|
957
|
+
`START_FROM_PHASE_PLAN_EMPTY_INTERSECTION`.
|
|
958
|
+
- Record `resolved_phase_plan`, `skipped_phases` (+ reasons such as
|
|
959
|
+
`policy_exclude`, `non_skippable_gate`), and **phase boundary status** entries
|
|
960
|
+
in continuation breadcrumbs (`docs/engineering/state.md`).
|
|
961
|
+
- **Backlog-drain**, **bulk execute**, and **team scope** paths must **reload**
|
|
962
|
+
scratchpad phase-selection inputs and **recompute** the plan at each bounded
|
|
963
|
+
boundary (no silent revival of omitted phases).
|
|
964
|
+
|
|
965
|
+
### Failure codes (deterministic)
|
|
966
|
+
|
|
967
|
+
- `PHASE_POLICY_CONFLICT`
|
|
968
|
+
- `PHASE_PLAN_UNKNOWN_PHASE`
|
|
969
|
+
- `PHASE_PLAN_EMPTY_INCLUDE`
|
|
970
|
+
- `PHASE_PLAN_UNKNOWN_PROFILE`
|
|
971
|
+
- `PHASE_PLAN_INVALID_AUTO_PHASE_PLAN`
|
|
972
|
+
- `PHASE_PLAN_HIGH_RISK_ACK_REQUIRED`
|
|
973
|
+
- `START_FROM_PHASE_PLAN_EMPTY_INTERSECTION`
|
|
974
|
+
|
|
784
975
|
## Optional backlog-drain auto mode (US-0044)
|
|
785
976
|
|
|
786
977
|
`/auto` can optionally continue across multiple planned stories when explicitly
|
|
@@ -927,9 +1118,17 @@ Deterministic mandatory gate order; no step may be skipped or reordered:
|
|
|
927
1118
|
|
|
928
1119
|
Default: no bypass. Override only via explicit decision gate with rationale and evidence (DEC-0019).
|
|
929
1120
|
|
|
930
|
-
**Optional-command compatibility (US-0039 / AC-10)**: Blank optional runbook keys (`LINT_COMMAND`, `TYPECHECK_COMMAND`) must not cause release to fail. Mandatory gates are check-in test + QA + UAT + isolation only.
|
|
1121
|
+
**Optional-command compatibility (US-0039 / AC-10)**: Blank optional runbook keys (`LINT_COMMAND`, `TYPECHECK_COMMAND`) must not cause release to fail. Mandatory gates are check-in test + QA + UAT + isolation only; optional checks run only when configured and are reported as `skipped` when not configured. Release does not require lint/typecheck evidence when those keys are blank.
|
|
1122
|
+
|
|
1123
|
+
**Per-gate audit verdict schema (US-0039)** — For TL/QA auditability, record per gate:
|
|
1124
|
+
|
|
1125
|
+
- `gate` (check-in_test | qa | uat | isolation | finalization)
|
|
1126
|
+
- `verdict` (pass | fail | override)
|
|
1127
|
+
- `reason_code` (e.g. RELEASE_TEST_FAILED, RELEASE_QA_BLOCKERS_OPEN, RELEASE_UAT_INCOMPLETE, RELEASE_GATE_OVERRIDE_APPROVED)
|
|
1128
|
+
- `remediation` (short remediation steps when fail/override)
|
|
1129
|
+
- `evidence_refs` (paths to tests/report.md, qa-findings.md, uat.json, release-findings.md, DEC-xxxx as applicable)
|
|
931
1130
|
|
|
932
|
-
|
|
1131
|
+
Record in `sprints/Sxxxx/release-findings.md` and/or `handoffs/release_queue.md` `gate_snapshot`; state checkpoint in `docs/engineering/state.md` may reference the same.
|
|
933
1132
|
|
|
934
1133
|
## Release queue and sprint notes contract (US-0040 / DEC-0020)
|
|
935
1134
|
|
|
@@ -1036,16 +1235,37 @@ Use this matrix to validate end-to-end installer/CLI lifecycle behavior:
|
|
|
1036
1235
|
| Negative path | invalid mode/args | `tests/run-tests.ps1`, `tests/run-tests.sh` | Deterministic non-zero fail-fast behavior |
|
|
1037
1236
|
| Platform parity subset | npm/brew/choco CI jobs | `.github/workflows/ci.yml` | Lifecycle subset passes on all three runners |
|
|
1038
1237
|
|
|
1039
|
-
## Scratchpad example upgrade contract (US-0057 / DEC-0039)
|
|
1238
|
+
## Scratchpad example upgrade contract (US-0057 / DEC-0039 / DEC-0057)
|
|
1040
1239
|
|
|
1041
1240
|
`its-magic --mode upgrade` treats `.cursor/scratchpad.local.example.md` as
|
|
1042
1241
|
framework-owned and `.cursor/scratchpad.local.md` as user-owned.
|
|
1043
1242
|
|
|
1044
1243
|
Expected deterministic outcome:
|
|
1045
|
-
- Framework-owned example is refreshed to latest release contract
|
|
1244
|
+
- Framework-owned example is refreshed to latest release contract **before** baseline
|
|
1245
|
+
materialization runs in `installer.py --scratchpad-postinstall` (**DEC-0057** ordering).
|
|
1046
1246
|
- User local scratchpad remains preserved without overwrite.
|
|
1047
|
-
- Installer output reports
|
|
1048
|
-
(`added|updated|unchanged`) and
|
|
1247
|
+
- Installer output reports manifest copy status for the example file where applicable
|
|
1248
|
+
(`added|updated|unchanged`) **and** `[SCRATCHPAD_LAYER]` diagnostics from post-install
|
|
1249
|
+
(`example_refresh`, `baseline_materialize` / `baseline_skip`, `user_local` preserved).
|
|
1250
|
+
- CI regression: `python scripts/check-scratchpad-pair-parity.py --repo <root>` exit `0`
|
|
1251
|
+
when active and `template/` baseline/example pairs share the same automation `KEY=`
|
|
1252
|
+
set and catalog `#` headers from `# Core behavior` (**US-0075** **AC-11**).
|
|
1253
|
+
|
|
1254
|
+
## Scratchpad delivery Model B (US-0073 / DEC-0055)
|
|
1255
|
+
|
|
1256
|
+
- Install manifest ships `.cursor/scratchpad.local.example.md` (framework catalog)
|
|
1257
|
+
but **does not** list `.cursor/scratchpad.md` as a copied file. The installer
|
|
1258
|
+
**materializes** `.cursor/scratchpad.md` from the packaged template when absent
|
|
1259
|
+
(`missing`, `interactive`, `upgrade`) or refreshes it on `overwrite`.
|
|
1260
|
+
- Merge precedence for automation readers: **local > materialized baseline > example**
|
|
1261
|
+
(same invariant as `DEC-0055`).
|
|
1262
|
+
- Post-install validation fails closed with `[SCRATCHPAD_MERGE_ERROR]` /
|
|
1263
|
+
`[SCRATCHPAD_MATERIALIZE_ERROR]` when layers are missing or required keys are
|
|
1264
|
+
empty after merge (`US-0073` `AC-4`).
|
|
1265
|
+
- `installer.ps1` / `installer.sh` delegate materialize+validate to
|
|
1266
|
+
`python installer.py --scratchpad-postinstall` (Python 3 required on PATH).
|
|
1267
|
+
- Recovery: `python installer.py --scratchpad-postinstall --target <repo> --mode missing`
|
|
1268
|
+
(or re-run a full install).
|
|
1049
1269
|
|
|
1050
1270
|
## Deterministic artifact ordering and write discipline (US-0058 / DEC-0040)
|
|
1051
1271
|
|