its-magic 0.1.2-31 → 0.1.2-33
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 +71 -16
- package/bin/its-magic.js +4 -3
- package/installer.ps1 +2 -0
- package/installer.py +78 -11
- package/installer.sh +2 -1
- package/package.json +1 -1
- package/template/.cursor/commands/execute.md +8 -1
- package/template/.cursor/rules/quality.mdc +1 -1
- package/template/.cursor/scratchpad.local.example.md +30 -14
- package/template/.cursor/scratchpad.md +14 -0
- package/template/.github/workflows/ci.yml +1 -1
- package/template/README.md +71 -16
- package/template/docs/developer/README.md +44 -0
- package/template/docs/engineering/context/installer-owned-paths.manifest +12 -0
- package/template/docs/engineering/runbook.md +72 -4
- package/template/scripts/doc_profile_lib.py +415 -0
- package/template/scripts/sync_push_gates.py +198 -0
- package/template/scripts/validate-and-push.ps1 +156 -56
- package/template/scripts/validate-and-push.sh +140 -60
- package/template/scripts/validate_doc_profile.py +103 -0
package/README.md
CHANGED
|
@@ -216,13 +216,20 @@ Recovery if `.cursor/scratchpad.md` is missing or merge validation fails:
|
|
|
216
216
|
python installer.py --scratchpad-postinstall --target . --mode missing
|
|
217
217
|
```
|
|
218
218
|
|
|
219
|
-
Upgrade behavior (US-0057):
|
|
220
|
-
- Aligns with **DEC-0039** (example vs local ownership)
|
|
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.
|
|
221
222
|
|
|
222
|
-
- `.cursor/scratchpad.local.example.md` is framework-owned and refreshed
|
|
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**).
|
|
223
225
|
- `.cursor/scratchpad.local.md` is user-owned and preserved on `--mode upgrade`.
|
|
224
|
-
- Existing `.cursor/scratchpad.md` is left untouched on upgrade (
|
|
225
|
-
|
|
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**).
|
|
226
233
|
|
|
227
234
|
Deterministic ordering behavior (US-0058):
|
|
228
235
|
- Mutable artifacts follow `docs/engineering/artifact-ordering-policy.md`.
|
|
@@ -273,7 +280,7 @@ Generated test scaffolding + auto-run behavior (US-0066):
|
|
|
273
280
|
- Static baseline test pass does not bypass runtime autopilot; runtime verdict
|
|
274
281
|
remains mandatory for QA PASS.
|
|
275
282
|
|
|
276
|
-
##
|
|
283
|
+
## Commands and workflow
|
|
277
284
|
|
|
278
285
|
### Core commands
|
|
279
286
|
|
|
@@ -1007,25 +1014,32 @@ the safety cap (`AUTO_LOOP_MAX_CYCLES`) is reached.
|
|
|
1007
1014
|
|
|
1008
1015
|
#### Layer 2: Local validate-and-push
|
|
1009
1016
|
|
|
1010
|
-
Run before pushing to catch anything the AI loop missed
|
|
1017
|
+
Run before pushing to catch anything the AI loop missed. **Merged scratchpad** (see
|
|
1018
|
+
`docs/engineering/runbook.md`, **Executable validate-and-push wiring (DEC-0058)**) gates
|
|
1019
|
+
**`git push`**: default **`SYNC_POLICY_MODE=manual`** and **`ALLOW_AUTO_PUSH=0`** exit early
|
|
1020
|
+
with a **reason code** (no push). Opt-in push requires an eligible mode, **`ALLOW_AUTO_PUSH=1`**,
|
|
1021
|
+
a non-empty **branch allowlist** match, passing **runbook** checks, and bounded **QA** rules.
|
|
1011
1022
|
|
|
1012
1023
|
```bash
|
|
1013
|
-
# Bash (Linux / macOS)
|
|
1014
|
-
|
|
1024
|
+
# Bash (Linux / macOS; bash required for this script)
|
|
1025
|
+
bash scripts/validate-and-push.sh
|
|
1015
1026
|
|
|
1016
1027
|
# PowerShell (Windows)
|
|
1017
1028
|
powershell scripts/validate-and-push.ps1
|
|
1018
1029
|
powershell scripts/validate-and-push.ps1 -MaxAttempts 3
|
|
1030
|
+
powershell scripts/validate-and-push.ps1 -DryRun
|
|
1019
1031
|
```
|
|
1020
1032
|
|
|
1021
1033
|
The script:
|
|
1022
|
-
1.
|
|
1023
|
-
2. Runs `
|
|
1024
|
-
3.
|
|
1025
|
-
4.
|
|
1026
|
-
5.
|
|
1034
|
+
1. Evaluates merged scratchpad policy via **`python scripts/sync_push_gates.py`** (Python 3 on PATH)
|
|
1035
|
+
2. Runs `FORMAT_COMMAND` and `LINT_FIX_COMMAND` to auto-fix what it can
|
|
1036
|
+
3. Runs `LINT_COMMAND`, optional `TYPECHECK_COMMAND`, and `TEST_COMMAND` to verify (with `TEST_TIMEOUT_SECONDS` when `timeout`/`gtimeout` is available on Unix)
|
|
1037
|
+
4. If checks fail, pauses and waits for you to fix
|
|
1038
|
+
5. Re-runs (up to 5 attempts, configurable)
|
|
1039
|
+
6. When green, re-checks allowlist + QA scan, then commits and pushes automatically (unless dry-run / no-commit)
|
|
1027
1040
|
|
|
1028
|
-
Use `-NoCommit` (PowerShell) or `false` as third arg (Bash) to skip
|
|
1041
|
+
Use `-NoCommit` (PowerShell), **`--dry-run`** first arg (Bash), or `false` as third arg (Bash) to skip **push**.
|
|
1042
|
+
**Policy-only** interpretation of scratchpad sync flags is **deprecated** for these scripts; see **`decisions/DEC-0058.md`** (policy semantics remain **`DEC-0018`** / **`US-0038`**).
|
|
1029
1043
|
|
|
1030
1044
|
#### Layer 3: CI auto-fix (GitHub Actions)
|
|
1031
1045
|
|
|
@@ -1055,7 +1069,7 @@ push / PR ──> checks ──> PASS ──> done
|
|
|
1055
1069
|
Auto-fix commits appear as `ci: auto-fix attempt N/3`. After 3 retries the
|
|
1056
1070
|
workflow stops and points you to `scripts/validate-and-push` for local fixing.
|
|
1057
1071
|
|
|
1058
|
-
##
|
|
1072
|
+
## Walkthrough examples
|
|
1059
1073
|
|
|
1060
1074
|
### Example 1: New feature from idea
|
|
1061
1075
|
|
|
@@ -1347,3 +1361,44 @@ flowchart TD
|
|
|
1347
1361
|
- `sprints/Sxxxx/*`: sprint scope, tasks, progress, QA findings, summary.
|
|
1348
1362
|
- `decisions/*`: decision records.
|
|
1349
1363
|
- `handoffs/*`: role-to-role transfer notes.
|
|
1364
|
+
|
|
1365
|
+
## Purpose
|
|
1366
|
+
|
|
1367
|
+
This repository publishes the **its-magic** workflow kit: commands, rules, skills, and
|
|
1368
|
+
documentation templates that teams install into their own repositories. The goal is a
|
|
1369
|
+
repeatable, file-backed lifecycle from intake through release.
|
|
1370
|
+
|
|
1371
|
+
## Quickstart
|
|
1372
|
+
|
|
1373
|
+
Use [Setup](#setup) for install commands. First-time install:
|
|
1374
|
+
|
|
1375
|
+
```bash
|
|
1376
|
+
npx its-magic --target . --mode missing --create
|
|
1377
|
+
```
|
|
1378
|
+
|
|
1379
|
+
## Examples
|
|
1380
|
+
|
|
1381
|
+
- Upgrade an existing repo: `its-magic --target . --mode upgrade`
|
|
1382
|
+
- Run check-in tests: use `TEST_COMMAND` from `docs/engineering/runbook.md` (often `sh tests/run-tests.sh`).
|
|
1383
|
+
|
|
1384
|
+
## Related documentation
|
|
1385
|
+
|
|
1386
|
+
- Operator commands and gates: `docs/engineering/runbook.md`
|
|
1387
|
+
- Architecture and story contracts: `docs/engineering/architecture.md`
|
|
1388
|
+
- Product backlog and acceptance: `docs/product/backlog.md`, `docs/product/acceptance.md`
|
|
1389
|
+
- Optional spec-pack mode (`SPEC_PACK_MODE=1`): engineering design artifacts under `docs/engineering/` when your team enables it
|
|
1390
|
+
- Optional user guides (`USER_GUIDE_MODE=1`): `docs/user-guides/` when enabled
|
|
1391
|
+
|
|
1392
|
+
## Limitations
|
|
1393
|
+
|
|
1394
|
+
- its-magic is a **process and documentation** framework; it does not replace your
|
|
1395
|
+
application runtime, hosting, or product-specific compliance work.
|
|
1396
|
+
- Mixed files such as `README.md` are preserved on upgrade; review notices may appear when
|
|
1397
|
+
the template adds new sections.
|
|
1398
|
+
- Documentation profile validation (`scripts/validate_doc_profile.py`) enforces audience and
|
|
1399
|
+
depth choices from the merged scratchpad (`DOC_AUDIENCE_PROFILE`, `DOC_DETAIL_LEVEL`).
|
|
1400
|
+
|
|
1401
|
+
## Contributing
|
|
1402
|
+
|
|
1403
|
+
Contributor-focused workflow and guardrails live in
|
|
1404
|
+
[`docs/developer/README.md`](docs/developer/README.md).
|
package/bin/its-magic.js
CHANGED
|
@@ -118,9 +118,10 @@ Install options:
|
|
|
118
118
|
Note: installer bootstraps runbook TEST/LINT/TYPECHECK commands from
|
|
119
119
|
OS+stack detection; unresolved TEST_COMMAND fails fast with
|
|
120
120
|
[RUNBOOK_BOOTSTRAP_ERROR] diagnostics.
|
|
121
|
-
Note: scratchpad Model B: .cursor/scratchpad.md is
|
|
122
|
-
|
|
123
|
-
|
|
121
|
+
Note: scratchpad Model B: .cursor/scratchpad.md is materialized when missing;
|
|
122
|
+
post-install always refreshes .cursor/scratchpad.local.example.md from the
|
|
123
|
+
template before baseline handling. PowerShell/bash installers require
|
|
124
|
+
Python 3 on PATH for merged scratchpad validation. Recovery:
|
|
124
125
|
python installer.py --scratchpad-postinstall --target <repo> --mode missing
|
|
125
126
|
|
|
126
127
|
Clean options:
|
package/installer.ps1
CHANGED
|
@@ -122,6 +122,7 @@ function Classify-File($RelPath) {
|
|
|
122
122
|
'.cursor/hooks/',
|
|
123
123
|
'.github/workflows/',
|
|
124
124
|
'scripts/validate-and-push',
|
|
125
|
+
'scripts/sync_push_gates',
|
|
125
126
|
'docs/engineering/context/',
|
|
126
127
|
'its_magic/'
|
|
127
128
|
)
|
|
@@ -664,6 +665,7 @@ if ($mode -eq "upgrade") {
|
|
|
664
665
|
Write-Host " Preserved (user): $preserved files"
|
|
665
666
|
if ($scratchpadExampleStatus -eq 'not-seen') { $scratchpadExampleStatus = 'not-in-manifest' }
|
|
666
667
|
Write-Host " Scratchpad example: $scratchpadExampleStatus (.cursor/scratchpad.local.example.md)"
|
|
668
|
+
Write-Host " Scratchpad layers: post-install refreshed example-first, then baseline (see [SCRATCHPAD_LAYER] lines)."
|
|
667
669
|
if (Test-Path (Join-Path $targetRoot '.cursor/scratchpad.local.md') -PathType Leaf) {
|
|
668
670
|
Write-Host " User local file: preserved (.cursor/scratchpad.local.md)"
|
|
669
671
|
}
|
package/installer.py
CHANGED
|
@@ -215,7 +215,30 @@ def validate_merged_scratchpad(target_root):
|
|
|
215
215
|
return ok, diagnostics
|
|
216
216
|
|
|
217
217
|
|
|
218
|
-
def
|
|
218
|
+
def materialize_scratchpad_example(target_root, source_root, print_ok=True):
|
|
219
|
+
"""
|
|
220
|
+
Always refresh framework-owned scratchpad.local.example from template first
|
|
221
|
+
(example-first ordering before baseline; never touches scratchpad.local.md).
|
|
222
|
+
"""
|
|
223
|
+
src = os.path.join(source_root, SCRATCHPAD_EXAMPLE_REL)
|
|
224
|
+
dst = os.path.join(target_root, SCRATCHPAD_EXAMPLE_REL)
|
|
225
|
+
if not os.path.isfile(src):
|
|
226
|
+
print(
|
|
227
|
+
"[SCRATCHPAD_EXAMPLE_ERROR] TEMPLATE_EXAMPLE_MISSING: "
|
|
228
|
+
f"expected template file at {src}. Reinstall its-magic package."
|
|
229
|
+
)
|
|
230
|
+
return False
|
|
231
|
+
ensure_parent(dst)
|
|
232
|
+
shutil.copy2(src, dst)
|
|
233
|
+
if print_ok:
|
|
234
|
+
print(
|
|
235
|
+
"[SCRATCHPAD_LAYER] example_refresh: copied template "
|
|
236
|
+
f"{SCRATCHPAD_EXAMPLE_REL} -> target (ordering: example before baseline)."
|
|
237
|
+
)
|
|
238
|
+
return True
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def materialize_scratchpad_baseline(target_root, source_root, mode, print_ok=True):
|
|
219
242
|
"""
|
|
220
243
|
Write stable baseline bytes from template when Model B requires it.
|
|
221
244
|
Never touches .cursor/scratchpad.local.md.
|
|
@@ -228,32 +251,72 @@ def materialize_scratchpad_baseline(target_root, source_root, mode):
|
|
|
228
251
|
f"expected template file at {src}. Reinstall its-magic package."
|
|
229
252
|
)
|
|
230
253
|
return False
|
|
254
|
+
wrote = False
|
|
231
255
|
if mode == "overwrite":
|
|
232
256
|
ensure_parent(dst)
|
|
233
257
|
shutil.copy2(src, dst)
|
|
234
|
-
|
|
235
|
-
|
|
258
|
+
wrote = True
|
|
259
|
+
elif mode == "upgrade":
|
|
236
260
|
if not os.path.isfile(dst):
|
|
237
261
|
ensure_parent(dst)
|
|
238
262
|
shutil.copy2(src, dst)
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
263
|
+
wrote = True
|
|
264
|
+
else:
|
|
265
|
+
# missing, interactive
|
|
266
|
+
if not os.path.isfile(dst):
|
|
267
|
+
ensure_parent(dst)
|
|
268
|
+
shutil.copy2(src, dst)
|
|
269
|
+
wrote = True
|
|
270
|
+
if wrote and print_ok:
|
|
271
|
+
print(
|
|
272
|
+
"[SCRATCHPAD_LAYER] baseline_materialize: wrote materialized "
|
|
273
|
+
f"{SCRATCHPAD_BASELINE_REL} from template (Model B)."
|
|
274
|
+
)
|
|
275
|
+
elif print_ok and os.path.isfile(dst):
|
|
276
|
+
print(
|
|
277
|
+
"[SCRATCHPAD_LAYER] baseline_skip: materialized baseline already present "
|
|
278
|
+
f"({SCRATCHPAD_BASELINE_REL}); not overwritten in this mode."
|
|
279
|
+
)
|
|
244
280
|
return True
|
|
245
281
|
|
|
246
282
|
|
|
283
|
+
def _doc_profile_sync(target_root, merged, print_ok=True):
|
|
284
|
+
"""Append missing normative README/developer doc sections from merged profile (non-destructive)."""
|
|
285
|
+
scripts_dir = os.path.join(normalize(os.path.dirname(__file__)), "scripts")
|
|
286
|
+
if scripts_dir not in sys.path:
|
|
287
|
+
sys.path.insert(0, scripts_dir)
|
|
288
|
+
import doc_profile_lib
|
|
289
|
+
|
|
290
|
+
notes = doc_profile_lib.ensure_doc_surfaces_merged(merged, target_root, print_ok=print_ok)
|
|
291
|
+
bad = [ln for ln in notes if ln.startswith("[DOC_PROFILE_INVALID]")]
|
|
292
|
+
return (not bad), notes
|
|
293
|
+
|
|
294
|
+
|
|
247
295
|
def run_scratchpad_postinstall(target_root, source_root, mode, print_ok=True):
|
|
248
|
-
if not
|
|
296
|
+
if not materialize_scratchpad_example(target_root, source_root, print_ok=print_ok):
|
|
297
|
+
return False
|
|
298
|
+
if not materialize_scratchpad_baseline(target_root, source_root, mode, print_ok=print_ok):
|
|
249
299
|
return False
|
|
250
300
|
ok, diagnostics = validate_merged_scratchpad(target_root)
|
|
251
301
|
for line in diagnostics:
|
|
252
302
|
print(line)
|
|
303
|
+
if ok:
|
|
304
|
+
merged, _paths = merge_scratchpad_layers(target_root)
|
|
305
|
+
dp_ok, dp_notes = _doc_profile_sync(target_root, merged, print_ok=print_ok)
|
|
306
|
+
for line in dp_notes:
|
|
307
|
+
print(line)
|
|
308
|
+
if not dp_ok:
|
|
309
|
+
ok = False
|
|
253
310
|
if ok and print_ok:
|
|
311
|
+
loc = os.path.join(target_root, SCRATCHPAD_LOCAL_REL)
|
|
312
|
+
if os.path.isfile(loc):
|
|
313
|
+
print(
|
|
314
|
+
"[SCRATCHPAD_LAYER] user_local: preserved "
|
|
315
|
+
f"{SCRATCHPAD_LOCAL_REL} (merge precedence unchanged)."
|
|
316
|
+
)
|
|
254
317
|
print(
|
|
255
|
-
"[SCRATCHPAD_POSTINSTALL_OK] Model B:
|
|
256
|
-
"
|
|
318
|
+
"[SCRATCHPAD_POSTINSTALL_OK] Model B: example refreshed, baseline handled, "
|
|
319
|
+
"merged scratchpad validation passed."
|
|
257
320
|
)
|
|
258
321
|
return ok
|
|
259
322
|
|
|
@@ -749,6 +812,10 @@ def main():
|
|
|
749
812
|
if scratchpad_example_status == "not-seen":
|
|
750
813
|
scratchpad_example_status = "not-in-manifest"
|
|
751
814
|
print(f" Scratchpad example: {scratchpad_example_status} (.cursor/scratchpad.local.example.md)")
|
|
815
|
+
print(
|
|
816
|
+
" Scratchpad layers: post-install refreshed example-first, then baseline "
|
|
817
|
+
"(see [SCRATCHPAD_LAYER] lines)."
|
|
818
|
+
)
|
|
752
819
|
if os.path.isfile(os.path.join(target_root, ".cursor", "scratchpad.local.md")):
|
|
753
820
|
print(" User local file: preserved (.cursor/scratchpad.local.md)")
|
|
754
821
|
if review:
|
package/installer.sh
CHANGED
|
@@ -157,7 +157,7 @@ classify_file() {
|
|
|
157
157
|
README.md) echo "mixed" ;;
|
|
158
158
|
.cursor/commands/*|.cursor/rules/*|.cursor/agents/*|.cursor/skills/*) echo "framework" ;;
|
|
159
159
|
.cursor/hooks/*|.cursor/hooks.json|.cursor/scratchpad.local.example.md) echo "framework" ;;
|
|
160
|
-
.github/workflows/*|scripts/validate-and-push*|docs/engineering/context/*|its_magic/*) echo "framework" ;;
|
|
160
|
+
.github/workflows/*|scripts/validate-and-push*|scripts/sync_push_gates.py|docs/engineering/context/*|its_magic/*) echo "framework" ;;
|
|
161
161
|
.its-magic-version|its_magic/.its-magic-version|its_magic/README.md) echo "framework" ;;
|
|
162
162
|
docs/product/*|docs/engineering/*|docs/user-guides/*) echo "user-data" ;;
|
|
163
163
|
sprints/*|handoffs/*|decisions/*) echo "user-data" ;;
|
|
@@ -556,6 +556,7 @@ if [ "$MODE" = "upgrade" ]; then
|
|
|
556
556
|
printf " Preserved (user): %s files\n" "$count_preserved"
|
|
557
557
|
[ "$scratchpad_example_status" = "not-seen" ] && scratchpad_example_status="not-in-manifest"
|
|
558
558
|
printf " Scratchpad example: %s (.cursor/scratchpad.local.example.md)\n" "$scratchpad_example_status"
|
|
559
|
+
printf " Scratchpad layers: post-install refreshed example-first, then baseline (see [SCRATCHPAD_LAYER] lines).\n"
|
|
559
560
|
[ -f "$TARGET_ROOT/.cursor/scratchpad.local.md" ] && printf " User local file: preserved (.cursor/scratchpad.local.md)\n"
|
|
560
561
|
if [ "$count_review" -gt 0 ]; then
|
|
561
562
|
printf "\n \033[1;35mReview recommended: %s files\033[0m\n" "$count_review"
|
package/package.json
CHANGED
|
@@ -193,7 +193,14 @@ Release gate semantics (US-0039): mandatory gates (check-in test, QA, UAT) and n
|
|
|
193
193
|
scan roots in `scripts/check-user-visible-metadata.py` **and** this runbook
|
|
194
194
|
section together or fail closed with `METADATA_SANITIZATION_SCOPE_AMBIGUOUS`
|
|
195
195
|
semantics at QA/release.
|
|
196
|
-
21.
|
|
196
|
+
21. Documentation profile validation (US-0077 / DEC-0059):
|
|
197
|
+
- When you change `README.md`, `docs/developer/README.md`, scratchpad profile keys
|
|
198
|
+
(`DOC_AUDIENCE_PROFILE`, `DOC_DETAIL_LEVEL`), or `scripts/doc_profile_lib.py` /
|
|
199
|
+
`scripts/validate_doc_profile.py`, run `python scripts/validate_doc_profile.py --repo <root>`.
|
|
200
|
+
- Fail closed on `DOC_PROFILE_INVALID`, `DOC_PROFILE_MERGE_ERROR`,
|
|
201
|
+
`DOC_SECTION_MISSING:*`, `DOC_SECTION_BUDGET_EXCEEDED`, or `DOC_TEMPLATE_PARITY_FAIL`
|
|
202
|
+
(see `docs/engineering/runbook.md`).
|
|
203
|
+
22. Triad hot-surface enforcement (DEC-0054):
|
|
197
204
|
- Before completing `/execute`, run
|
|
198
205
|
`python scripts/enforce-triad-hot-surface.py --check` from repository root
|
|
199
206
|
(or `--repo <root>`).
|
|
@@ -24,7 +24,7 @@ globs: ["**/*"]
|
|
|
24
24
|
(local pre-push) → CI auto-fix (GitHub Actions). Each layer catches issues
|
|
25
25
|
the previous layer missed.
|
|
26
26
|
- Before pushing, recommend running `scripts/validate-and-push.ps1` (Windows)
|
|
27
|
-
or `scripts/validate-and-push.sh` (Linux/Mac) to catch failures locally.
|
|
27
|
+
or `bash scripts/validate-and-push.sh` (Linux/Mac) to catch failures locally.
|
|
28
28
|
- `LINT_FIX_COMMAND` and `FORMAT_COMMAND` in the runbook enable automatic
|
|
29
29
|
formatting/lint fixes both locally and in CI.
|
|
30
30
|
- Remote config validation errors (when `REMOTE_EXECUTION=1`) must be fail-fast
|
|
@@ -60,8 +60,8 @@ AUTO_TEAM_SCOPE_ENFORCE=1
|
|
|
60
60
|
# - AUTO_ROLE_RESEARCH: po|tech-lead (empty -> default tech-lead)
|
|
61
61
|
# - AUTO_ROLE_PLAN_VERIFY: qa|tech-lead (empty -> default qa)
|
|
62
62
|
# - AUTO_ROLE_REFRESH_CONTEXT: curator|po (empty -> default curator)
|
|
63
|
-
# - AUTO_EXECUTE_ROLE_OVERRIDE: empty or allowed_non_dev_execute
|
|
64
|
-
# - EXECUTE_OVERRIDE_GOVERNANCE_REF: parseable waiver pointer when override set
|
|
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
65
|
AUTO_ROLE_RESEARCH=
|
|
66
66
|
AUTO_ROLE_PLAN_VERIFY=
|
|
67
67
|
AUTO_ROLE_REFRESH_CONTEXT=
|
|
@@ -70,6 +70,11 @@ EXECUTE_OVERRIDE_GOVERNANCE_REF=
|
|
|
70
70
|
#
|
|
71
71
|
# `/auto` phase selection policy (US-0070 / DEC-0052)
|
|
72
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
|
|
73
78
|
AUTO_PHASE_PLAN=
|
|
74
79
|
AUTO_PHASE_EXCLUDE=
|
|
75
80
|
AUTO_PHASE_INCLUDE=
|
|
@@ -114,7 +119,7 @@ SYNC_CUSTOM_PHASES=
|
|
|
114
119
|
ALLOW_AUTO_PUSH=0
|
|
115
120
|
AUTO_PUSH_BRANCH_ALLOWLIST=
|
|
116
121
|
#
|
|
117
|
-
# Knowledge curation
|
|
122
|
+
# Knowledge curation
|
|
118
123
|
# - EARLY_RESEARCH: 0|1 (PO/TL search web during intake/architecture)
|
|
119
124
|
# - INTAKE_GUIDED_MODE: 0|1 (guided intake follow-up/options/research behavior)
|
|
120
125
|
# - INTAKE_SUBAGENT_FALLBACK: deny|allow (deny by default; when deny, missing
|
|
@@ -128,8 +133,10 @@ AUTO_PUSH_BRANCH_ALLOWLIST=
|
|
|
128
133
|
# archival rollover checks)
|
|
129
134
|
# - STATE_HOT_MAX_CHECKPOINTS: integer >= 10 (max recent checkpoints to retain
|
|
130
135
|
# in `state.md` after rollover)
|
|
131
|
-
# - PO_TO_TL_HOT_MAX_LINES
|
|
132
|
-
# -
|
|
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)
|
|
133
140
|
# - Manual-override precedence: explicit flag values in this file remain authoritative
|
|
134
141
|
# for that flag and override profile defaults.
|
|
135
142
|
EARLY_RESEARCH=1
|
|
@@ -143,8 +150,8 @@ PO_TO_TL_HOT_MAX_LINES=800
|
|
|
143
150
|
PO_TO_TL_HOT_MAX_SECTIONS=60
|
|
144
151
|
ARCH_HOT_MAX_LINES=3500
|
|
145
152
|
ARCH_HOT_MAX_STORY_SECTIONS=120
|
|
146
|
-
|
|
147
|
-
# Publish targets
|
|
153
|
+
|
|
154
|
+
# Publish targets (US-0054)
|
|
148
155
|
# - RELEASE_PUBLISH_MODE: disabled|confirm|auto
|
|
149
156
|
# - disabled: skip post-release publish target execution
|
|
150
157
|
# - confirm: require explicit operator confirmation before publish (default)
|
|
@@ -154,6 +161,7 @@ ARCH_HOT_MAX_STORY_SECTIONS=120
|
|
|
154
161
|
RELEASE_PUBLISH_MODE=confirm
|
|
155
162
|
RELEASE_TARGETS_FILE=docs/engineering/release-targets.json
|
|
156
163
|
RELEASE_TARGETS_DEFAULT=
|
|
164
|
+
|
|
157
165
|
#
|
|
158
166
|
# Security review
|
|
159
167
|
# - SECURITY_REVIEW: 0|1 (enable optional security/compliance review; default off)
|
|
@@ -162,8 +170,8 @@ RELEASE_TARGETS_DEFAULT=
|
|
|
162
170
|
# When SECURITY_REVIEW=0, the workflow adds zero security-review overhead.
|
|
163
171
|
SECURITY_REVIEW=0
|
|
164
172
|
COMPLIANCE_PROFILES=GDPR
|
|
165
|
-
|
|
166
|
-
#
|
|
173
|
+
|
|
174
|
+
# Cross-repo compatibility observability
|
|
167
175
|
# - CROSS_REPO_OBSERVABILITY: 0|1 (enable compatibility visibility and checks)
|
|
168
176
|
# - COMPATIBILITY_GATE_ON_CRITICAL: 0|1 (when enabled, critical unresolved
|
|
169
177
|
# compatibility findings trigger decision gate before release)
|
|
@@ -172,17 +180,25 @@ COMPLIANCE_PROFILES=GDPR
|
|
|
172
180
|
CROSS_REPO_OBSERVABILITY=0
|
|
173
181
|
COMPATIBILITY_GATE_ON_CRITICAL=1
|
|
174
182
|
COMPATIBILITY_SOURCES=
|
|
175
|
-
|
|
176
|
-
# Component
|
|
183
|
+
|
|
184
|
+
# Component-scoped execution mode
|
|
177
185
|
# - COMPONENT_SCOPE_MODE: 0|1 (enable scoped planning/execution guardrails)
|
|
178
186
|
# - TARGET_COMPONENTS: comma-separated component IDs intended in scope
|
|
179
187
|
COMPONENT_SCOPE_MODE=0
|
|
180
188
|
TARGET_COMPONENTS=
|
|
181
|
-
|
|
182
|
-
# Optional
|
|
189
|
+
|
|
190
|
+
# Optional spec-pack documentation (US-0031)
|
|
183
191
|
# - SPEC_PACK_MODE: 0|1 (enable Design Concept, CRS, Technical Spec generation/validation; default 0)
|
|
184
192
|
# When 0, intake/architecture/release add no required spec-pack steps.
|
|
193
|
+
SPEC_PACK_MODE=0
|
|
194
|
+
|
|
195
|
+
# Optional user-guide documentation (US-0032)
|
|
185
196
|
# - USER_GUIDE_MODE: 0|1 (enable per-feature user guides at docs/user-guides/US-xxxx.md; default 0)
|
|
186
197
|
# When 0, intake/architecture/sprint-plan/execute/qa/release add no required user-guide steps or blocking checks.
|
|
187
|
-
SPEC_PACK_MODE=0
|
|
188
198
|
USER_GUIDE_MODE=0
|
|
199
|
+
|
|
200
|
+
# Documentation audience profile (DEC-0059)
|
|
201
|
+
# - DOC_AUDIENCE_PROFILE: user|developer|both (empty -> both during transition)
|
|
202
|
+
# - DOC_DETAIL_LEVEL: concise|balanced|technical-deep (empty -> balanced during transition)
|
|
203
|
+
DOC_AUDIENCE_PROFILE=both
|
|
204
|
+
DOC_DETAIL_LEVEL=balanced
|
|
@@ -81,6 +81,14 @@ AUTO_PHASE_INCLUDE=
|
|
|
81
81
|
AUTO_PHASE_PROFILE=
|
|
82
82
|
AUTO_PHASE_HIGH_RISK_ACK=
|
|
83
83
|
#
|
|
84
|
+
# Team mode
|
|
85
|
+
# - TEAM_MODE: 0|1 (enable task/member scoped team workflow)
|
|
86
|
+
# - TEAM_MEMBER: short id for current developer
|
|
87
|
+
# - ACTIVE_TASK_IDS: comma-separated task ids (for example T-12,T-13)
|
|
88
|
+
TEAM_MODE=0
|
|
89
|
+
TEAM_MEMBER=
|
|
90
|
+
ACTIVE_TASK_IDS=
|
|
91
|
+
#
|
|
84
92
|
# Sprint planning
|
|
85
93
|
# - SPRINT_MAX_TASKS: integer >= 1 (max atomic tasks per sprint, default 12)
|
|
86
94
|
# - SPRINT_AUTO_SPLIT: 0|1 (propose splitting when over threshold)
|
|
@@ -189,3 +197,9 @@ SPEC_PACK_MODE=0
|
|
|
189
197
|
# When 0, intake/architecture/sprint-plan/execute/qa/release add no required user-guide steps or blocking checks.
|
|
190
198
|
USER_GUIDE_MODE=0
|
|
191
199
|
|
|
200
|
+
# Documentation audience profile (DEC-0059)
|
|
201
|
+
# - DOC_AUDIENCE_PROFILE: user|developer|both (empty -> both during transition)
|
|
202
|
+
# - DOC_DETAIL_LEVEL: concise|balanced|technical-deep (empty -> balanced during transition)
|
|
203
|
+
DOC_AUDIENCE_PROFILE=both
|
|
204
|
+
DOC_DETAIL_LEVEL=balanced
|
|
205
|
+
|
|
@@ -186,7 +186,7 @@ jobs:
|
|
|
186
186
|
echo ""
|
|
187
187
|
echo "What to do next:"
|
|
188
188
|
echo " 1. Pull the latest changes"
|
|
189
|
-
echo " 2. Run:
|
|
189
|
+
echo " 2. Run: bash scripts/validate-and-push.sh"
|
|
190
190
|
echo " (or: powershell scripts/validate-and-push.ps1)"
|
|
191
191
|
echo " 3. Fix failures, the script loops until green, then pushes."
|
|
192
192
|
|
package/template/README.md
CHANGED
|
@@ -216,13 +216,20 @@ Recovery if `.cursor/scratchpad.md` is missing or merge validation fails:
|
|
|
216
216
|
python installer.py --scratchpad-postinstall --target . --mode missing
|
|
217
217
|
```
|
|
218
218
|
|
|
219
|
-
Upgrade behavior (US-0057):
|
|
220
|
-
- Aligns with **DEC-0039** (example vs local ownership)
|
|
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.
|
|
221
222
|
|
|
222
|
-
- `.cursor/scratchpad.local.example.md` is framework-owned and refreshed
|
|
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**).
|
|
223
225
|
- `.cursor/scratchpad.local.md` is user-owned and preserved on `--mode upgrade`.
|
|
224
|
-
- Existing `.cursor/scratchpad.md` is left untouched on upgrade (
|
|
225
|
-
|
|
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**).
|
|
226
233
|
|
|
227
234
|
Deterministic ordering behavior (US-0058):
|
|
228
235
|
- Mutable artifacts follow `docs/engineering/artifact-ordering-policy.md`.
|
|
@@ -273,7 +280,7 @@ Generated test scaffolding + auto-run behavior (US-0066):
|
|
|
273
280
|
- Static baseline test pass does not bypass runtime autopilot; runtime verdict
|
|
274
281
|
remains mandatory for QA PASS.
|
|
275
282
|
|
|
276
|
-
##
|
|
283
|
+
## Commands and workflow
|
|
277
284
|
|
|
278
285
|
### Core commands
|
|
279
286
|
|
|
@@ -1007,25 +1014,32 @@ the safety cap (`AUTO_LOOP_MAX_CYCLES`) is reached.
|
|
|
1007
1014
|
|
|
1008
1015
|
#### Layer 2: Local validate-and-push
|
|
1009
1016
|
|
|
1010
|
-
Run before pushing to catch anything the AI loop missed
|
|
1017
|
+
Run before pushing to catch anything the AI loop missed. **Merged scratchpad** (see
|
|
1018
|
+
`docs/engineering/runbook.md`, **Executable validate-and-push wiring (DEC-0058)**) gates
|
|
1019
|
+
**`git push`**: default **`SYNC_POLICY_MODE=manual`** and **`ALLOW_AUTO_PUSH=0`** exit early
|
|
1020
|
+
with a **reason code** (no push). Opt-in push requires an eligible mode, **`ALLOW_AUTO_PUSH=1`**,
|
|
1021
|
+
a non-empty **branch allowlist** match, passing **runbook** checks, and bounded **QA** rules.
|
|
1011
1022
|
|
|
1012
1023
|
```bash
|
|
1013
|
-
# Bash (Linux / macOS)
|
|
1014
|
-
|
|
1024
|
+
# Bash (Linux / macOS; bash required for this script)
|
|
1025
|
+
bash scripts/validate-and-push.sh
|
|
1015
1026
|
|
|
1016
1027
|
# PowerShell (Windows)
|
|
1017
1028
|
powershell scripts/validate-and-push.ps1
|
|
1018
1029
|
powershell scripts/validate-and-push.ps1 -MaxAttempts 3
|
|
1030
|
+
powershell scripts/validate-and-push.ps1 -DryRun
|
|
1019
1031
|
```
|
|
1020
1032
|
|
|
1021
1033
|
The script:
|
|
1022
|
-
1.
|
|
1023
|
-
2. Runs `
|
|
1024
|
-
3.
|
|
1025
|
-
4.
|
|
1026
|
-
5.
|
|
1034
|
+
1. Evaluates merged scratchpad policy via **`python scripts/sync_push_gates.py`** (Python 3 on PATH)
|
|
1035
|
+
2. Runs `FORMAT_COMMAND` and `LINT_FIX_COMMAND` to auto-fix what it can
|
|
1036
|
+
3. Runs `LINT_COMMAND`, optional `TYPECHECK_COMMAND`, and `TEST_COMMAND` to verify (with `TEST_TIMEOUT_SECONDS` when `timeout`/`gtimeout` is available on Unix)
|
|
1037
|
+
4. If checks fail, pauses and waits for you to fix
|
|
1038
|
+
5. Re-runs (up to 5 attempts, configurable)
|
|
1039
|
+
6. When green, re-checks allowlist + QA scan, then commits and pushes automatically (unless dry-run / no-commit)
|
|
1027
1040
|
|
|
1028
|
-
Use `-NoCommit` (PowerShell) or `false` as third arg (Bash) to skip
|
|
1041
|
+
Use `-NoCommit` (PowerShell), **`--dry-run`** first arg (Bash), or `false` as third arg (Bash) to skip **push**.
|
|
1042
|
+
**Policy-only** interpretation of scratchpad sync flags is **deprecated** for these scripts; see **`decisions/DEC-0058.md`** (policy semantics remain **`DEC-0018`** / **`US-0038`**).
|
|
1029
1043
|
|
|
1030
1044
|
#### Layer 3: CI auto-fix (GitHub Actions)
|
|
1031
1045
|
|
|
@@ -1055,7 +1069,7 @@ push / PR ──> checks ──> PASS ──> done
|
|
|
1055
1069
|
Auto-fix commits appear as `ci: auto-fix attempt N/3`. After 3 retries the
|
|
1056
1070
|
workflow stops and points you to `scripts/validate-and-push` for local fixing.
|
|
1057
1071
|
|
|
1058
|
-
##
|
|
1072
|
+
## Walkthrough examples
|
|
1059
1073
|
|
|
1060
1074
|
### Example 1: New feature from idea
|
|
1061
1075
|
|
|
@@ -1347,3 +1361,44 @@ flowchart TD
|
|
|
1347
1361
|
- `sprints/Sxxxx/*`: sprint scope, tasks, progress, QA findings, summary.
|
|
1348
1362
|
- `decisions/*`: decision records.
|
|
1349
1363
|
- `handoffs/*`: role-to-role transfer notes.
|
|
1364
|
+
|
|
1365
|
+
## Purpose
|
|
1366
|
+
|
|
1367
|
+
This repository publishes the **its-magic** workflow kit: commands, rules, skills, and
|
|
1368
|
+
documentation templates that teams install into their own repositories. The goal is a
|
|
1369
|
+
repeatable, file-backed lifecycle from intake through release.
|
|
1370
|
+
|
|
1371
|
+
## Quickstart
|
|
1372
|
+
|
|
1373
|
+
Use [Setup](#setup) for install commands. First-time install:
|
|
1374
|
+
|
|
1375
|
+
```bash
|
|
1376
|
+
npx its-magic --target . --mode missing --create
|
|
1377
|
+
```
|
|
1378
|
+
|
|
1379
|
+
## Examples
|
|
1380
|
+
|
|
1381
|
+
- Upgrade an existing repo: `its-magic --target . --mode upgrade`
|
|
1382
|
+
- Run check-in tests: use `TEST_COMMAND` from `docs/engineering/runbook.md` (often `sh tests/run-tests.sh`).
|
|
1383
|
+
|
|
1384
|
+
## Related documentation
|
|
1385
|
+
|
|
1386
|
+
- Operator commands and gates: `docs/engineering/runbook.md`
|
|
1387
|
+
- Architecture and story contracts: `docs/engineering/architecture.md`
|
|
1388
|
+
- Product backlog and acceptance: `docs/product/backlog.md`, `docs/product/acceptance.md`
|
|
1389
|
+
- Optional spec-pack mode (`SPEC_PACK_MODE=1`): engineering design artifacts under `docs/engineering/` when your team enables it
|
|
1390
|
+
- Optional user guides (`USER_GUIDE_MODE=1`): `docs/user-guides/` when enabled
|
|
1391
|
+
|
|
1392
|
+
## Limitations
|
|
1393
|
+
|
|
1394
|
+
- its-magic is a **process and documentation** framework; it does not replace your
|
|
1395
|
+
application runtime, hosting, or product-specific compliance work.
|
|
1396
|
+
- Mixed files such as `README.md` are preserved on upgrade; review notices may appear when
|
|
1397
|
+
the template adds new sections.
|
|
1398
|
+
- Documentation profile validation (`scripts/validate_doc_profile.py`) enforces audience and
|
|
1399
|
+
depth choices from the merged scratchpad (`DOC_AUDIENCE_PROFILE`, `DOC_DETAIL_LEVEL`).
|
|
1400
|
+
|
|
1401
|
+
## Contributing
|
|
1402
|
+
|
|
1403
|
+
Contributor-focused workflow and guardrails live in
|
|
1404
|
+
[`docs/developer/README.md`](docs/developer/README.md).
|