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 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) and Model B baseline rules below.
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 on `--mode upgrade`.
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 (legacy parity).
225
- - Installer output includes scratchpad example refresh status and local-preserved signal.
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
- materialized when missing; PowerShell/bash installers require Python 3
123
- on PATH for merged scratchpad validation. Recovery:
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 materialize_scratchpad_baseline(target_root, source_root, mode):
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
- return True
235
- if mode == "upgrade":
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
- return True
240
- # missing, interactive
241
- if not os.path.isfile(dst):
242
- ensure_parent(dst)
243
- shutil.copy2(src, dst)
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 materialize_scratchpad_baseline(target_root, source_root, mode):
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: materialized baseline (if required) "
256
- "and merged scratchpad validation passed."
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "its-magic",
3
- "version": "0.1.2-31",
3
+ "version": "0.1.2-32",
4
4
  "description": "its-magic - AI dev team workflow for Cursor.",
5
5
  "license": "MIT",
6
6
  "bin": {
@@ -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 / intake
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 / PO_TO_TL_HOT_MAX_SECTIONS (handoff hot caps)
132
- # - ARCH_HOT_MAX_LINES / ARCH_HOT_MAX_STORY_SECTIONS (architecture hot caps)
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
- # Compatibility observability
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 scope
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 docs packs
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)
@@ -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) and Model B baseline rules below.
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 on `--mode upgrade`.
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 (legacy parity).
225
- - Installer output includes scratchpad example refresh status and local-preserved signal.
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 scratchpad example refresh status
1247
- (`added|updated|unchanged`) and preservation signal for user local file.
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