its-magic 0.1.2-9 → 0.1.2

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.
Files changed (232) hide show
  1. package/README.md +1602 -755
  2. package/bin/its-magic.js +121 -11
  3. package/bin/postinstall.js +21 -0
  4. package/installer.ps1 +759 -0
  5. package/installer.py +981 -0
  6. package/installer.sh +649 -0
  7. package/package.json +18 -14
  8. package/scripts/check_intake_template_parity.py +284 -0
  9. package/scripts/doc_profile_lib.py +415 -0
  10. package/scripts/guard_installer_publish.py +88 -0
  11. package/scripts/intake_bug_routing_guard.py +67 -0
  12. package/scripts/intake_evidence_lib.py +802 -0
  13. package/scripts/intake_evidence_validate.py +73 -0
  14. package/scripts/materialize_codebase_map.py +184 -0
  15. package/scripts/remote_config_summary.py +243 -0
  16. package/template/.cursor/agents/curator.mdc +35 -0
  17. package/template/.cursor/agents/dev.mdc +29 -0
  18. package/template/.cursor/agents/po.mdc +141 -0
  19. package/template/.cursor/agents/qa.mdc +28 -0
  20. package/template/.cursor/agents/release.mdc +28 -0
  21. package/template/.cursor/agents/security.mdc +98 -0
  22. package/template/.cursor/agents/tech-lead.mdc +57 -0
  23. package/template/.cursor/commands/architecture.md +127 -0
  24. package/template/.cursor/commands/ask.md +55 -0
  25. package/template/.cursor/commands/auto.md +533 -0
  26. package/template/.cursor/commands/discovery.md +47 -0
  27. package/template/.cursor/commands/execute.md +343 -0
  28. package/template/.cursor/commands/intake.md +323 -0
  29. package/template/.cursor/commands/map-codebase.md +46 -0
  30. package/template/.cursor/commands/memory-audit.md +175 -0
  31. package/template/.cursor/commands/milestone-complete.md +51 -0
  32. package/template/.cursor/commands/milestone-start.md +59 -0
  33. package/template/.cursor/commands/pause.md +64 -0
  34. package/{.cursor/commands/gsd-phase-context.md → template/.cursor/commands/phase-context.md} +6 -2
  35. package/template/.cursor/commands/plan-verify.md +34 -0
  36. package/template/.cursor/commands/qa.md +226 -0
  37. package/template/.cursor/commands/quick.md +41 -0
  38. package/template/.cursor/commands/refresh-context.md +82 -0
  39. package/template/.cursor/commands/release.md +505 -0
  40. package/template/.cursor/commands/research.md +49 -0
  41. package/template/.cursor/commands/resume.md +67 -0
  42. package/template/.cursor/commands/security-review.md +81 -0
  43. package/template/.cursor/commands/sprint-plan.md +103 -0
  44. package/template/.cursor/commands/status-reconcile.md +95 -0
  45. package/template/.cursor/commands/verify-work.md +152 -0
  46. package/template/.cursor/dev-environment.json.example +22 -0
  47. package/{.cursor → template/.cursor}/hooks/README.md +3 -2
  48. package/{.cursor/hooks/gsd-hook.py → template/.cursor/hooks/hook.py} +15 -6
  49. package/template/.cursor/hooks.json +26 -0
  50. package/template/.cursor/remote.json +31 -0
  51. package/template/.cursor/rules/caveman.mdc +184 -0
  52. package/template/.cursor/rules/coding-standards.mdc +39 -0
  53. package/template/.cursor/rules/core.mdc +111 -0
  54. package/template/.cursor/rules/handoffs.mdc +27 -0
  55. package/template/.cursor/rules/quality.mdc +49 -0
  56. package/template/.cursor/scratchpad.local.example.md +323 -0
  57. package/template/.cursor/scratchpad.md +324 -0
  58. package/{.cursor/skills/gsd-team → template/.cursor/skills/its-magic}/SKILL.md +2 -2
  59. package/template/.cursorignore +6 -0
  60. package/template/.env.example +28 -0
  61. package/template/.github/workflows/ci.yml +194 -0
  62. package/{.github → template/.github}/workflows/deploy.yml +5 -2
  63. package/template/.its-magic-version +1 -0
  64. package/template/README.md +1602 -0
  65. package/template/decisions/DEC-0001.md +11 -0
  66. package/template/decisions/DEC-0002.md +11 -0
  67. package/template/docs/developer/README.md +44 -0
  68. package/template/docs/engineering/architecture.md +9 -0
  69. package/template/docs/engineering/artifact-ordering-policy.md +48 -0
  70. package/template/docs/engineering/artifact-ownership-policy.md +57 -0
  71. package/template/docs/engineering/auto-orchestration-reference.md +1211 -0
  72. package/{docs → template/docs}/engineering/codebase-map.md +0 -5
  73. package/template/docs/engineering/compatibility-report.md +20 -0
  74. package/template/docs/engineering/compatibility-signals.md +7 -0
  75. package/template/docs/engineering/component-scope-report.md +16 -0
  76. package/template/docs/engineering/component-scope.md +19 -0
  77. package/template/docs/engineering/context/installer-owned-paths.manifest +96 -0
  78. package/template/docs/engineering/context/readme-section-affinity.json +30 -0
  79. package/template/docs/engineering/decisions.md +16 -0
  80. package/template/docs/engineering/legacy-drift-audit.md +21 -0
  81. package/template/docs/engineering/manifests/components/api-gateway.manifest.yaml +12 -0
  82. package/template/docs/engineering/manifests/registry.manifest.yaml +20 -0
  83. package/template/docs/engineering/manifests/repo.manifest.yaml +11 -0
  84. package/template/docs/engineering/phase-context.md +16 -0
  85. package/template/docs/engineering/release-targets.json +123 -0
  86. package/template/docs/engineering/research.md +29 -0
  87. package/template/docs/engineering/runbook.md +2320 -0
  88. package/template/docs/engineering/runtime-connectivity.md +81 -0
  89. package/template/docs/engineering/security-review.md +33 -0
  90. package/template/docs/engineering/spec-pack/README.md +20 -0
  91. package/template/docs/engineering/state-archive/README.md +15 -0
  92. package/template/docs/engineering/state.md +20 -0
  93. package/template/docs/engineering/status-normalization-report.md +19 -0
  94. package/template/docs/engineering/token-cost-parity-manifest.md +16 -0
  95. package/template/docs/engineering/us-0084-remote-e2e.md +44 -0
  96. package/template/docs/product/acceptance.md +1 -0
  97. package/template/docs/product/backlog.md +5 -0
  98. package/template/docs/product/vision.md +11 -0
  99. package/template/docs/user-guides/README.md +40 -0
  100. package/{handoffs → template/handoffs}/dev_to_qa.md +0 -3
  101. package/{handoffs → template/handoffs}/po_to_tl.md +0 -3
  102. package/{handoffs → template/handoffs}/qa_to_dev.md +1 -2
  103. package/template/handoffs/release_notes.md +51 -0
  104. package/template/handoffs/release_queue.md +47 -0
  105. package/template/handoffs/release_to_dev.md +31 -0
  106. package/template/handoffs/releases/Sxxxx-release-notes.md +62 -0
  107. package/template/handoffs/resume_brief.md +14 -0
  108. package/{handoffs → template/handoffs}/tl_to_dev.md +0 -2
  109. package/template/handoffs/token_cost_runs/README.md +26 -0
  110. package/template/its_magic/.its-magic-version +1 -0
  111. package/template/its_magic/README.md +9 -0
  112. package/template/scripts/auto_outer_driver.py +521 -0
  113. package/template/scripts/caveman_compress_input.py +903 -0
  114. package/template/scripts/check_downstream_ci_guard.py +67 -0
  115. package/template/scripts/check_intake_template_parity.py +284 -0
  116. package/template/scripts/check_token_cost_parity.py +69 -0
  117. package/template/scripts/dev_environment_lib.py +463 -0
  118. package/template/scripts/doc_profile_lib.py +415 -0
  119. package/template/scripts/downstream_ci_guard_lib.py +222 -0
  120. package/template/scripts/enforce-triad-hot-surface.py +753 -0
  121. package/template/scripts/guard_installer_publish.py +88 -0
  122. package/template/scripts/intake_bug_resume_brief_refresh.py +303 -0
  123. package/template/scripts/intake_bug_routing_guard.py +67 -0
  124. package/template/scripts/intake_evidence_lib.py +802 -0
  125. package/template/scripts/intake_evidence_validate.py +73 -0
  126. package/template/scripts/materialize_codebase_map.py +184 -0
  127. package/template/scripts/pack_json_validate.py +130 -0
  128. package/template/scripts/project_readme_coverage_lib.py +417 -0
  129. package/template/scripts/readme_feature_coverage_lib.py +608 -0
  130. package/template/scripts/remote_config_summary.py +243 -0
  131. package/template/scripts/sync_push_gates.py +198 -0
  132. package/template/scripts/token_cost_compare.py +40 -0
  133. package/template/scripts/token_cost_lib.py +108 -0
  134. package/template/scripts/uat_probe_lib.py +868 -0
  135. package/template/scripts/validate-and-push.ps1 +280 -0
  136. package/template/scripts/validate-and-push.sh +243 -0
  137. package/template/scripts/validate_doc_profile.py +103 -0
  138. package/template/scripts/validate_project_readme_coverage.py +151 -0
  139. package/template/scripts/validate_readme_feature_coverage.py +140 -0
  140. package/template/sprints/S0001/progress.md +1 -0
  141. package/template/sprints/S0001/qa-findings.md +9 -0
  142. package/template/sprints/S0001/release-findings.md +24 -0
  143. package/template/sprints/S0001/sprint.md +9 -0
  144. package/template/sprints/S0001/summary.md +7 -0
  145. package/template/sprints/S0001/tasks.md +1 -0
  146. package/template/sprints/S0001/uat.json +6 -0
  147. package/template/sprints/S0001/uat.md +5 -0
  148. package/template/sprints/quick/Q0001/summary.md +1 -0
  149. package/{sprints → template/sprints}/quick/Q0001/task.json +0 -1
  150. package/.cursor/agents/curator.mdc +0 -21
  151. package/.cursor/agents/dev.mdc +0 -20
  152. package/.cursor/agents/po.mdc +0 -19
  153. package/.cursor/agents/qa.mdc +0 -19
  154. package/.cursor/agents/release.mdc +0 -19
  155. package/.cursor/agents/tech-lead.mdc +0 -21
  156. package/.cursor/commands/gsd-architecture.md +0 -29
  157. package/.cursor/commands/gsd-auto.md +0 -27
  158. package/.cursor/commands/gsd-discovery.md +0 -27
  159. package/.cursor/commands/gsd-execute.md +0 -32
  160. package/.cursor/commands/gsd-intake.md +0 -28
  161. package/.cursor/commands/gsd-map-codebase.md +0 -25
  162. package/.cursor/commands/gsd-milestone-complete.md +0 -24
  163. package/.cursor/commands/gsd-milestone-start.md +0 -26
  164. package/.cursor/commands/gsd-pause.md +0 -25
  165. package/.cursor/commands/gsd-plan-verify.md +0 -26
  166. package/.cursor/commands/gsd-qa.md +0 -28
  167. package/.cursor/commands/gsd-quick.md +0 -24
  168. package/.cursor/commands/gsd-refresh-context.md +0 -26
  169. package/.cursor/commands/gsd-release.md +0 -29
  170. package/.cursor/commands/gsd-research.md +0 -28
  171. package/.cursor/commands/gsd-resume.md +0 -26
  172. package/.cursor/commands/gsd-sprint-plan.md +0 -30
  173. package/.cursor/commands/gsd-verify-work.md +0 -25
  174. package/.cursor/hooks.json +0 -26
  175. package/.cursor/plans/cursor-gsd-team-kit_8cfee9b8.plan.md +0 -57
  176. package/.cursor/remote.json +0 -18
  177. package/.cursor/rules/gsd-core.mdc +0 -18
  178. package/.cursor/rules/gsd-handoffs.mdc +0 -10
  179. package/.cursor/rules/gsd-quality.mdc +0 -15
  180. package/.cursor/scratchpad.md +0 -34
  181. package/.github/workflows/ci.yml +0 -47
  182. package/decisions/DEC-0001.md +0 -21
  183. package/decisions/DEC-0002.md +0 -21
  184. package/docs/engineering/architecture.md +0 -354
  185. package/docs/engineering/decisions.md +0 -6
  186. package/docs/engineering/research.md +0 -11
  187. package/docs/engineering/runbook.md +0 -32
  188. package/docs/engineering/state.md +0 -33
  189. package/docs/product/acceptance.md +0 -6
  190. package/docs/product/backlog.md +0 -7
  191. package/docs/product/vision.md +0 -46
  192. package/gsd-installer.ps1 +0 -189
  193. package/gsd-installer.py +0 -195
  194. package/gsd-installer.sh +0 -201
  195. package/handoffs/release_notes.md +0 -14
  196. package/handoffs/resume_brief.md +0 -8
  197. package/milestones/M0001/milestone.json +0 -7
  198. package/milestones/M0001/phases.json +0 -9
  199. package/milestones/M0001/progress.md +0 -3
  200. package/milestones/M0001/summary.md +0 -3
  201. package/scripts/generate-release-notes.ps1 +0 -74
  202. package/scripts/generate-release-notes.sh +0 -63
  203. package/scripts/release-all.ps1 +0 -423
  204. package/scripts/release-all.sh +0 -226
  205. package/sprints/S0001/progress.md +0 -4
  206. package/sprints/S0001/qa-findings.md +0 -113
  207. package/sprints/S0001/sprint.md +0 -70
  208. package/sprints/S0001/summary.md +0 -46
  209. package/sprints/S0001/tasks.md +0 -35
  210. package/sprints/S0001/uat.json +0 -8
  211. package/sprints/S0001/uat.md +0 -8
  212. package/sprints/quick/Q0001/summary.md +0 -3
  213. /package/{.cursor/rules/gsd-escalation.mdc → template/.cursor/rules/escalation.mdc} +0 -0
  214. /package/{.cursor/skills/gsd-team → template/.cursor/skills/its-magic}/templates/acceptance.json +0 -0
  215. /package/{.cursor/skills/gsd-team → template/.cursor/skills/its-magic}/templates/acceptance.md +0 -0
  216. /package/{.cursor/skills/gsd-team → template/.cursor/skills/its-magic}/templates/architecture.json +0 -0
  217. /package/{.cursor/skills/gsd-team → template/.cursor/skills/its-magic}/templates/architecture.md +0 -0
  218. /package/{.cursor/skills/gsd-team → template/.cursor/skills/its-magic}/templates/decision.json +0 -0
  219. /package/{.cursor/skills/gsd-team → template/.cursor/skills/its-magic}/templates/decision.md +0 -0
  220. /package/{.cursor/skills/gsd-team → template/.cursor/skills/its-magic}/templates/handoff.json +0 -0
  221. /package/{.cursor/skills/gsd-team → template/.cursor/skills/its-magic}/templates/handoff.md +0 -0
  222. /package/{.cursor/skills/gsd-team → template/.cursor/skills/its-magic}/templates/milestone.json +0 -0
  223. /package/{.cursor/skills/gsd-team → template/.cursor/skills/its-magic}/templates/phase-context.json +0 -0
  224. /package/{.cursor/skills/gsd-team → template/.cursor/skills/its-magic}/templates/plan-verify.json +0 -0
  225. /package/{.cursor/skills/gsd-team → template/.cursor/skills/its-magic}/templates/sprint.json +0 -0
  226. /package/{.cursor/skills/gsd-team → template/.cursor/skills/its-magic}/templates/sprint.md +0 -0
  227. /package/{.cursor/skills/gsd-team → template/.cursor/skills/its-magic}/templates/story.json +0 -0
  228. /package/{.cursor/skills/gsd-team → template/.cursor/skills/its-magic}/templates/story.md +0 -0
  229. /package/{.cursor/skills/gsd-team → template/.cursor/skills/its-magic}/templates/uat.json +0 -0
  230. /package/{docs → template/docs}/engineering/context/phase-template.json +0 -0
  231. /package/{docs → template/docs}/engineering/dependencies.json +0 -0
  232. /package/{sprints → template/sprints}/S0001/plan-verify.json +0 -0
@@ -0,0 +1,28 @@
1
+ # .env.example — operator-local secret values (US-0085 / DEC-0071)
2
+ # Copy to .env, fill in values, source before remote/SSH/release ops.
3
+ # .env is gitignored and must NEVER be committed.
4
+ # This file lists names only — no secret values.
5
+
6
+ # ── From template/.cursor/remote.json (Cursor dev/remote targets) ──
7
+ REMOTE_DOCKER_TOKEN=
8
+ REMOTE_SSH_USER=
9
+ REMOTE_SSH_KEY_PATH=
10
+
11
+ # ── From docs/engineering/release-targets.json (release/QA targets) ──
12
+ PUBLIC_DOMAIN=
13
+ CHOCO_API_KEY=
14
+ GITHUB_TOKEN=
15
+ DOCKER_TOKEN=
16
+ DOCKER_RUNTIME_HOST=
17
+ AWS_PROFILE=
18
+ APP_DOMAIN=
19
+ APP_IP=
20
+ CUSTOM_DOMAIN=
21
+ CUSTOM_IP=
22
+ SSH_HOST=
23
+ SSH_USER=
24
+ SSH_PRIVATE_KEY=
25
+ RUNTIME_DOMAIN=
26
+ RUNTIME_IP=
27
+ DOCKER_HOST=
28
+ DOCKER_CONTEXT=
@@ -0,0 +1,194 @@
1
+ name: ci
2
+
3
+ on:
4
+ push:
5
+ branches: ["main"]
6
+ pull_request:
7
+ workflow_dispatch:
8
+ inputs:
9
+ retry_count:
10
+ description: "Internal retry counter (do not set manually)"
11
+ required: false
12
+ default: "0"
13
+
14
+ permissions:
15
+ contents: write
16
+ pull-requests: write
17
+
18
+ env:
19
+ MAX_CI_RETRIES: 3
20
+
21
+ jobs:
22
+ # ── Unit / structure tests (from runbook) ──────────────────────────
23
+ checks:
24
+ runs-on: ubuntu-latest
25
+ outputs:
26
+ test_result: ${{ steps.test.outcome }}
27
+ lint_result: ${{ steps.lint.outcome }}
28
+ ci_auto_fix: ${{ steps.runbook.outputs.CI_AUTO_FIX }}
29
+ steps:
30
+ - uses: actions/checkout@v4
31
+ with:
32
+ ref: ${{ github.head_ref || github.ref_name }}
33
+ token: ${{ secrets.GITHUB_TOKEN }}
34
+
35
+ - id: runbook
36
+ name: Read runbook commands
37
+ run: |
38
+ python3 - <<'PY'
39
+ import os, pathlib, re
40
+ text = pathlib.Path("docs/engineering/runbook.md").read_text(encoding="utf-8")
41
+ command_section = text.split("## Notes", 1)[0]
42
+ def get(key):
43
+ m = re.search(rf"^{re.escape(key)}:[ \t]*(.*)$", command_section, re.M)
44
+ if not m:
45
+ return ""
46
+ val = m.group(1).strip()
47
+ if val in ("", "...", "<...>", "TODO", key, f"{key}:"):
48
+ return ""
49
+ if val.startswith(f"{key}:"):
50
+ return ""
51
+ return val
52
+ keys = ["TEST_COMMAND", "LINT_COMMAND", "TYPECHECK_COMMAND", "CI_AUTO_FIX"]
53
+ with open(os.environ["GITHUB_OUTPUT"], "a") as f:
54
+ for key in keys:
55
+ val = get(key)
56
+ if val:
57
+ f.write(f"{key}={val}\n")
58
+ print(f" {key} = '{val}'")
59
+ else:
60
+ print(f" {key} = (skipped, empty)")
61
+ PY
62
+
63
+ - name: Test
64
+ id: test
65
+ if: ${{ steps.runbook.outputs.TEST_COMMAND != '' }}
66
+ continue-on-error: true
67
+ run: ${{ steps.runbook.outputs.TEST_COMMAND }}
68
+
69
+ - name: Lint
70
+ id: lint
71
+ if: ${{ steps.runbook.outputs.LINT_COMMAND != '' }}
72
+ continue-on-error: true
73
+ run: ${{ steps.runbook.outputs.LINT_COMMAND }}
74
+
75
+ - name: Typecheck
76
+ id: typecheck
77
+ if: ${{ steps.runbook.outputs.TYPECHECK_COMMAND != '' }}
78
+ run: ${{ steps.runbook.outputs.TYPECHECK_COMMAND }}
79
+
80
+ - name: No commands set
81
+ if: ${{ steps.runbook.outputs.TEST_COMMAND == '' && steps.runbook.outputs.LINT_COMMAND == '' && steps.runbook.outputs.TYPECHECK_COMMAND == '' }}
82
+ run: echo "no tests configured yet"
83
+
84
+ - name: Summarise results
85
+ if: always()
86
+ run: |
87
+ echo "### CI Results" >> "$GITHUB_STEP_SUMMARY"
88
+ if [ "${{ steps.runbook.outputs.TEST_COMMAND }}" = "" ] && [ "${{ steps.runbook.outputs.LINT_COMMAND }}" = "" ] && [ "${{ steps.runbook.outputs.TYPECHECK_COMMAND }}" = "" ]; then
89
+ echo "**no tests configured yet**" >> "$GITHUB_STEP_SUMMARY"
90
+ fi
91
+ echo "| Step | Result |" >> "$GITHUB_STEP_SUMMARY"
92
+ echo "|------|--------|" >> "$GITHUB_STEP_SUMMARY"
93
+ echo "| Test | ${{ steps.test.outcome || 'skipped' }} |" >> "$GITHUB_STEP_SUMMARY"
94
+ echo "| Lint | ${{ steps.lint.outcome || 'skipped' }} |" >> "$GITHUB_STEP_SUMMARY"
95
+ echo "| Typecheck | ${{ steps.typecheck.outcome || 'skipped' }} |" >> "$GITHUB_STEP_SUMMARY"
96
+
97
+ - name: Fail if tests or lint failed
98
+ if: ${{ steps.test.outcome == 'failure' || steps.lint.outcome == 'failure' }}
99
+ run: |
100
+ echo "::error::Tests or lint failed. See summary above."
101
+ exit 1
102
+
103
+ # ── Auto-fix attempt (runs only when checks fail) ─────────────────
104
+ auto-fix:
105
+ needs: checks
106
+ if: ${{ failure() && needs.checks.outputs.ci_auto_fix == 'true' && (github.event_name == 'push' || github.event_name == 'pull_request') }}
107
+ runs-on: ubuntu-latest
108
+ steps:
109
+ - uses: actions/checkout@v4
110
+ with:
111
+ ref: ${{ github.head_ref || github.ref_name }}
112
+ fetch-depth: 0
113
+ token: ${{ secrets.GITHUB_TOKEN }}
114
+
115
+ - name: Determine retry count
116
+ id: retry
117
+ run: |
118
+ COUNT="${{ github.event.inputs.retry_count || '0' }}"
119
+ echo "count=$COUNT" >> "$GITHUB_OUTPUT"
120
+ echo "Current retry: $COUNT / ${{ env.MAX_CI_RETRIES }}"
121
+ if [ "$COUNT" -ge "${{ env.MAX_CI_RETRIES }}" ]; then
122
+ echo "skip=true" >> "$GITHUB_OUTPUT"
123
+ echo "::warning::Max CI retries (${{ env.MAX_CI_RETRIES }}) reached. Manual intervention required."
124
+ else
125
+ echo "skip=false" >> "$GITHUB_OUTPUT"
126
+ fi
127
+
128
+ - name: Read runbook for fix commands
129
+ id: runbook
130
+ if: ${{ steps.retry.outputs.skip != 'true' }}
131
+ run: |
132
+ python3 - <<'PY'
133
+ import os, pathlib, re
134
+ text = pathlib.Path("docs/engineering/runbook.md").read_text(encoding="utf-8")
135
+ command_section = text.split("## Notes", 1)[0]
136
+ def get(key):
137
+ m = re.search(rf"^{re.escape(key)}:[ \t]*(.*)$", command_section, re.M)
138
+ if not m:
139
+ return ""
140
+ val = m.group(1).strip()
141
+ if val in ("", "...", "<...>", "TODO", key, f"{key}:"):
142
+ return ""
143
+ if val.startswith(f"{key}:"):
144
+ return ""
145
+ return val
146
+ keys = ["LINT_FIX_COMMAND", "FORMAT_COMMAND"]
147
+ with open(os.environ["GITHUB_OUTPUT"], "a") as f:
148
+ for key in keys:
149
+ val = get(key)
150
+ if val:
151
+ f.write(f"{key}={val}\n")
152
+ print(f" {key} = '{val}'")
153
+ else:
154
+ print(f" {key} = (not set)")
155
+ PY
156
+
157
+ - name: Run lint auto-fix
158
+ if: ${{ steps.retry.outputs.skip != 'true' && steps.runbook.outputs.LINT_FIX_COMMAND != '' }}
159
+ continue-on-error: true
160
+ run: ${{ steps.runbook.outputs.LINT_FIX_COMMAND }}
161
+
162
+ - name: Run formatter
163
+ if: ${{ steps.retry.outputs.skip != 'true' && steps.runbook.outputs.FORMAT_COMMAND != '' }}
164
+ continue-on-error: true
165
+ run: ${{ steps.runbook.outputs.FORMAT_COMMAND }}
166
+
167
+ - name: Check for changes and commit
168
+ if: ${{ steps.retry.outputs.skip != 'true' }}
169
+ id: commit
170
+ run: |
171
+ git config user.name "its-magic[bot]"
172
+ git config user.email "its-magic[bot]@users.noreply.github.com"
173
+ if git diff --quiet && git diff --cached --quiet; then
174
+ echo "No auto-fix changes to commit."
175
+ echo "has_changes=false" >> "$GITHUB_OUTPUT"
176
+ else
177
+ NEXT=$(( ${{ steps.retry.outputs.count }} + 1 ))
178
+ git add -A
179
+ git commit -m "ci: auto-fix attempt $NEXT/${{ env.MAX_CI_RETRIES }}"
180
+ git push
181
+ echo "has_changes=true" >> "$GITHUB_OUTPUT"
182
+ echo "Fixes committed and pushed. CI will re-run automatically."
183
+ fi
184
+
185
+ - name: Post failure summary
186
+ if: ${{ steps.retry.outputs.skip == 'true' || steps.commit.outputs.has_changes == 'false' }}
187
+ run: |
188
+ echo "::error::CI failed and auto-fix could not resolve it."
189
+ echo ""
190
+ echo "What to do next:"
191
+ echo " 1. Pull the latest changes"
192
+ echo " 2. Run: bash scripts/validate-and-push.sh"
193
+ echo " (or: powershell scripts/validate-and-push.ps1)"
194
+ echo " 3. Fix failures, the script loops until green, then pushes."
@@ -25,11 +25,14 @@ jobs:
25
25
  import re
26
26
 
27
27
  text = pathlib.Path("docs/engineering/runbook.md").read_text()
28
+ command_section = text.split("## Notes", 1)[0]
28
29
 
29
30
  def get(key):
30
- m = re.search(rf"^{key}:\s*(.*)$", text, re.M)
31
+ m = re.search(rf"^{re.escape(key)}:[ \t]*(.*)$", command_section, re.M)
31
32
  val = (m.group(1) or "").strip() if m else ""
32
- if val in ("", "...", "<...>", "TODO"):
33
+ if val in ("", "...", "<...>", "TODO", key, f"{key}:"):
34
+ return ""
35
+ if val.startswith(f"{key}:"):
33
36
  return ""
34
37
  return val
35
38
 
@@ -0,0 +1 @@
1
+ 0.0.0