its-magic 0.1.2-31 → 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 +12 -5
- package/bin/its-magic.js +4 -3
- package/installer.ps1 +1 -0
- package/installer.py +59 -11
- package/installer.sh +1 -0
- package/package.json +1 -1
- package/template/.cursor/scratchpad.local.example.md +24 -14
- package/template/.cursor/scratchpad.md +8 -0
- package/template/README.md +12 -5
- package/template/docs/engineering/context/installer-owned-paths.manifest +5 -0
- package/template/docs/engineering/runbook.md +9 -4
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`.
|
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
|
@@ -664,6 +664,7 @@ if ($mode -eq "upgrade") {
|
|
|
664
664
|
Write-Host " Preserved (user): $preserved files"
|
|
665
665
|
if ($scratchpadExampleStatus -eq 'not-seen') { $scratchpadExampleStatus = 'not-in-manifest' }
|
|
666
666
|
Write-Host " Scratchpad example: $scratchpadExampleStatus (.cursor/scratchpad.local.example.md)"
|
|
667
|
+
Write-Host " Scratchpad layers: post-install refreshed example-first, then baseline (see [SCRATCHPAD_LAYER] lines)."
|
|
667
668
|
if (Test-Path (Join-Path $targetRoot '.cursor/scratchpad.local.md') -PathType Leaf) {
|
|
668
669
|
Write-Host " User local file: preserved (.cursor/scratchpad.local.md)"
|
|
669
670
|
}
|
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,53 @@ 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
|
|
|
247
283
|
def run_scratchpad_postinstall(target_root, source_root, mode, print_ok=True):
|
|
248
|
-
if not
|
|
284
|
+
if not materialize_scratchpad_example(target_root, source_root, print_ok=print_ok):
|
|
285
|
+
return False
|
|
286
|
+
if not materialize_scratchpad_baseline(target_root, source_root, mode, print_ok=print_ok):
|
|
249
287
|
return False
|
|
250
288
|
ok, diagnostics = validate_merged_scratchpad(target_root)
|
|
251
289
|
for line in diagnostics:
|
|
252
290
|
print(line)
|
|
253
291
|
if ok and print_ok:
|
|
292
|
+
loc = os.path.join(target_root, SCRATCHPAD_LOCAL_REL)
|
|
293
|
+
if os.path.isfile(loc):
|
|
294
|
+
print(
|
|
295
|
+
"[SCRATCHPAD_LAYER] user_local: preserved "
|
|
296
|
+
f"{SCRATCHPAD_LOCAL_REL} (merge precedence unchanged)."
|
|
297
|
+
)
|
|
254
298
|
print(
|
|
255
|
-
"[SCRATCHPAD_POSTINSTALL_OK] Model B:
|
|
256
|
-
"
|
|
299
|
+
"[SCRATCHPAD_POSTINSTALL_OK] Model B: example refreshed, baseline handled, "
|
|
300
|
+
"merged scratchpad validation passed."
|
|
257
301
|
)
|
|
258
302
|
return ok
|
|
259
303
|
|
|
@@ -749,6 +793,10 @@ def main():
|
|
|
749
793
|
if scratchpad_example_status == "not-seen":
|
|
750
794
|
scratchpad_example_status = "not-in-manifest"
|
|
751
795
|
print(f" Scratchpad example: {scratchpad_example_status} (.cursor/scratchpad.local.example.md)")
|
|
796
|
+
print(
|
|
797
|
+
" Scratchpad layers: post-install refreshed example-first, then baseline "
|
|
798
|
+
"(see [SCRATCHPAD_LAYER] lines)."
|
|
799
|
+
)
|
|
752
800
|
if os.path.isfile(os.path.join(target_root, ".cursor", "scratchpad.local.md")):
|
|
753
801
|
print(" User local file: preserved (.cursor/scratchpad.local.md)")
|
|
754
802
|
if review:
|
package/installer.sh
CHANGED
|
@@ -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
|
@@ -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,19 @@ 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
|
|
@@ -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)
|
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`.
|
|
@@ -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
|
|
@@ -1235,16 +1235,21 @@ Use this matrix to validate end-to-end installer/CLI lifecycle behavior:
|
|
|
1235
1235
|
| Negative path | invalid mode/args | `tests/run-tests.ps1`, `tests/run-tests.sh` | Deterministic non-zero fail-fast behavior |
|
|
1236
1236
|
| Platform parity subset | npm/brew/choco CI jobs | `.github/workflows/ci.yml` | Lifecycle subset passes on all three runners |
|
|
1237
1237
|
|
|
1238
|
-
## Scratchpad example upgrade contract (US-0057 / DEC-0039)
|
|
1238
|
+
## Scratchpad example upgrade contract (US-0057 / DEC-0039 / DEC-0057)
|
|
1239
1239
|
|
|
1240
1240
|
`its-magic --mode upgrade` treats `.cursor/scratchpad.local.example.md` as
|
|
1241
1241
|
framework-owned and `.cursor/scratchpad.local.md` as user-owned.
|
|
1242
1242
|
|
|
1243
1243
|
Expected deterministic outcome:
|
|
1244
|
-
- 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).
|
|
1245
1246
|
- User local scratchpad remains preserved without overwrite.
|
|
1246
|
-
- Installer output reports
|
|
1247
|
-
(`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**).
|
|
1248
1253
|
|
|
1249
1254
|
## Scratchpad delivery Model B (US-0073 / DEC-0055)
|
|
1250
1255
|
|