@mmerterden/multi-agent-pipeline 12.7.0 → 12.8.0

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 (244) hide show
  1. package/CHANGELOG.md +126 -0
  2. package/install/_common.mjs +48 -0
  3. package/install/_dev-only-files.mjs +125 -5
  4. package/install/claude.mjs +14 -8
  5. package/install/copilot.mjs +5 -8
  6. package/package.json +17 -2
  7. package/pipeline/commands/multi-agent/analysis/SKILL.md +1 -1
  8. package/pipeline/lib/credential-store.sh +20 -0
  9. package/pipeline/multi-agent-refs/_account-picker.md +1 -1
  10. package/pipeline/multi-agent-refs/_dev-context.md +1 -1
  11. package/pipeline/multi-agent-refs/_repo-picker.md +1 -1
  12. package/pipeline/multi-agent-refs/phases/operations.md +28 -0
  13. package/pipeline/multi-agent-refs/phases/phase-0-init.md +1 -0
  14. package/pipeline/multi-agent-refs/phases/phase-2-planning.md +1 -1
  15. package/pipeline/multi-agent-refs/phases/phase-3-dev.md +1 -2
  16. package/pipeline/multi-agent-refs/phases/phase-4-review.md +49 -4
  17. package/pipeline/schemas/prefs.schema.json +6 -0
  18. package/pipeline/scripts/_smoke-root.sh +61 -0
  19. package/pipeline/scripts/audit-log.sh +25 -0
  20. package/pipeline/scripts/smoke-cross-cli-behavior.sh +21 -7
  21. package/pipeline/eval/golden-tasks/01-ios-bugfix-darkmode/expected/phase-1-analysis.json +0 -25
  22. package/pipeline/eval/golden-tasks/01-ios-bugfix-darkmode/expected/phase-2-plan.json +0 -30
  23. package/pipeline/eval/golden-tasks/01-ios-bugfix-darkmode/expected/phase-4-review.json +0 -20
  24. package/pipeline/eval/golden-tasks/01-ios-bugfix-darkmode/expected/phase-4-triage.json +0 -15
  25. package/pipeline/eval/golden-tasks/01-ios-bugfix-darkmode/metadata.json +0 -14
  26. package/pipeline/eval/golden-tasks/01-ios-bugfix-darkmode/task.json +0 -12
  27. package/pipeline/eval/golden-tasks/02-android-feature-compose/expected/phase-1-analysis.json +0 -29
  28. package/pipeline/eval/golden-tasks/02-android-feature-compose/expected/phase-2-plan.json +0 -43
  29. package/pipeline/eval/golden-tasks/02-android-feature-compose/expected/phase-4-review.json +0 -35
  30. package/pipeline/eval/golden-tasks/02-android-feature-compose/expected/phase-4-triage.json +0 -35
  31. package/pipeline/eval/golden-tasks/02-android-feature-compose/metadata.json +0 -14
  32. package/pipeline/eval/golden-tasks/02-android-feature-compose/task.json +0 -12
  33. package/pipeline/eval/golden-tasks/03-backend-python-ratelimit/expected/phase-1-analysis.json +0 -29
  34. package/pipeline/eval/golden-tasks/03-backend-python-ratelimit/expected/phase-2-plan.json +0 -42
  35. package/pipeline/eval/golden-tasks/03-backend-python-ratelimit/expected/phase-4-review.json +0 -20
  36. package/pipeline/eval/golden-tasks/03-backend-python-ratelimit/expected/phase-4-triage.json +0 -15
  37. package/pipeline/eval/golden-tasks/03-backend-python-ratelimit/metadata.json +0 -14
  38. package/pipeline/eval/golden-tasks/03-backend-python-ratelimit/task.json +0 -12
  39. package/pipeline/eval/golden-tasks/04-frontend-next-hydration/expected/phase-1-analysis.json +0 -29
  40. package/pipeline/eval/golden-tasks/04-frontend-next-hydration/expected/phase-2-plan.json +0 -40
  41. package/pipeline/eval/golden-tasks/04-frontend-next-hydration/expected/phase-4-review.json +0 -20
  42. package/pipeline/eval/golden-tasks/04-frontend-next-hydration/expected/phase-4-triage.json +0 -15
  43. package/pipeline/eval/golden-tasks/04-frontend-next-hydration/metadata.json +0 -14
  44. package/pipeline/eval/golden-tasks/04-frontend-next-hydration/task.json +0 -12
  45. package/pipeline/eval/golden-tasks/05-ios-security-keychain/expected/phase-1-analysis.json +0 -29
  46. package/pipeline/eval/golden-tasks/05-ios-security-keychain/expected/phase-2-plan.json +0 -42
  47. package/pipeline/eval/golden-tasks/05-ios-security-keychain/expected/phase-4-review.json +0 -28
  48. package/pipeline/eval/golden-tasks/05-ios-security-keychain/expected/phase-4-triage.json +0 -27
  49. package/pipeline/eval/golden-tasks/05-ios-security-keychain/metadata.json +0 -14
  50. package/pipeline/eval/golden-tasks/05-ios-security-keychain/task.json +0 -12
  51. package/pipeline/eval/golden-tasks/06-android-refactor-usecase/expected/phase-1-analysis.json +0 -29
  52. package/pipeline/eval/golden-tasks/06-android-refactor-usecase/expected/phase-2-plan.json +0 -41
  53. package/pipeline/eval/golden-tasks/06-android-refactor-usecase/expected/phase-4-review.json +0 -12
  54. package/pipeline/eval/golden-tasks/06-android-refactor-usecase/expected/phase-4-triage.json +0 -6
  55. package/pipeline/eval/golden-tasks/06-android-refactor-usecase/metadata.json +0 -14
  56. package/pipeline/eval/golden-tasks/06-android-refactor-usecase/task.json +0 -12
  57. package/pipeline/eval/golden-tasks/07-backend-node-idempotency/expected/phase-1-analysis.json +0 -29
  58. package/pipeline/eval/golden-tasks/07-backend-node-idempotency/expected/phase-2-plan.json +0 -42
  59. package/pipeline/eval/golden-tasks/07-backend-node-idempotency/expected/phase-4-review.json +0 -28
  60. package/pipeline/eval/golden-tasks/07-backend-node-idempotency/expected/phase-4-triage.json +0 -27
  61. package/pipeline/eval/golden-tasks/07-backend-node-idempotency/metadata.json +0 -14
  62. package/pipeline/eval/golden-tasks/07-backend-node-idempotency/task.json +0 -12
  63. package/pipeline/eval/golden-tasks/08-ios-auth-consensus-unverified/expected/phase-1-analysis.json +0 -25
  64. package/pipeline/eval/golden-tasks/08-ios-auth-consensus-unverified/expected/phase-2-plan.json +0 -31
  65. package/pipeline/eval/golden-tasks/08-ios-auth-consensus-unverified/expected/phase-4-review.json +0 -12
  66. package/pipeline/eval/golden-tasks/08-ios-auth-consensus-unverified/expected/phase-4-triage.json +0 -18
  67. package/pipeline/eval/golden-tasks/08-ios-auth-consensus-unverified/metadata.json +0 -14
  68. package/pipeline/eval/golden-tasks/08-ios-auth-consensus-unverified/task.json +0 -12
  69. package/pipeline/eval/golden-tasks/README.md +0 -65
  70. package/pipeline/eval/intent-cases.json +0 -40
  71. package/pipeline/eval/run-metrics-fixture.json +0 -93
  72. package/pipeline/eval/triage/01-empty-findings/expected.json +0 -6
  73. package/pipeline/eval/triage/01-empty-findings/input.json +0 -5
  74. package/pipeline/eval/triage/01-empty-findings/notes.md +0 -7
  75. package/pipeline/eval/triage/02-real-blocker/expected.json +0 -15
  76. package/pipeline/eval/triage/02-real-blocker/input.json +0 -14
  77. package/pipeline/eval/triage/02-real-blocker/notes.md +0 -7
  78. package/pipeline/eval/triage/03-out-of-scope-defer/expected.json +0 -18
  79. package/pipeline/eval/triage/03-out-of-scope-defer/input.json +0 -14
  80. package/pipeline/eval/triage/03-out-of-scope-defer/notes.md +0 -10
  81. package/pipeline/eval/triage/04-false-positive-reject/expected.json +0 -18
  82. package/pipeline/eval/triage/04-false-positive-reject/input.json +0 -14
  83. package/pipeline/eval/triage/04-false-positive-reject/notes.md +0 -10
  84. package/pipeline/eval/triage/05-mixed-classification/expected.json +0 -43
  85. package/pipeline/eval/triage/05-mixed-classification/input.json +0 -38
  86. package/pipeline/eval/triage/05-mixed-classification/notes.md +0 -17
  87. package/pipeline/eval/triage/06-severity-mismatch/expected.json +0 -15
  88. package/pipeline/eval/triage/06-severity-mismatch/input.json +0 -14
  89. package/pipeline/eval/triage/06-severity-mismatch/notes.md +0 -9
  90. package/pipeline/eval/triage/07-duplicate-reviewers/expected.json +0 -27
  91. package/pipeline/eval/triage/07-duplicate-reviewers/input.json +0 -22
  92. package/pipeline/eval/triage/07-duplicate-reviewers/notes.md +0 -9
  93. package/pipeline/eval/triage/08-style-misclassified/expected.json +0 -18
  94. package/pipeline/eval/triage/08-style-misclassified/input.json +0 -14
  95. package/pipeline/eval/triage/08-style-misclassified/notes.md +0 -9
  96. package/pipeline/eval/triage/09-cascading-finding/expected.json +0 -23
  97. package/pipeline/eval/triage/09-cascading-finding/input.json +0 -22
  98. package/pipeline/eval/triage/09-cascading-finding/notes.md +0 -9
  99. package/pipeline/eval/triage/10-deferred-crossref/expected.json +0 -18
  100. package/pipeline/eval/triage/10-deferred-crossref/input.json +0 -14
  101. package/pipeline/eval/triage/10-deferred-crossref/notes.md +0 -9
  102. package/pipeline/eval/triage/11-vercel-token-leak-blocker/expected.json +0 -27
  103. package/pipeline/eval/triage/11-vercel-token-leak-blocker/input.json +0 -22
  104. package/pipeline/eval/triage/11-vercel-token-leak-blocker/notes.md +0 -14
  105. package/pipeline/eval/triage/README.md +0 -54
  106. package/pipeline/scripts/benchmark-phase-0.sh +0 -128
  107. package/pipeline/scripts/check-md-links.mjs +0 -88
  108. package/pipeline/scripts/eval-golden-tasks-live.mjs +0 -302
  109. package/pipeline/scripts/eval-golden-tasks.mjs +0 -224
  110. package/pipeline/scripts/eval-intent.mjs +0 -107
  111. package/pipeline/scripts/eval-mine-corpus.mjs +0 -211
  112. package/pipeline/scripts/eval-triage.mjs +0 -171
  113. package/pipeline/scripts/fixtures/diff-risk-android.diff +0 -40
  114. package/pipeline/scripts/fixtures/diff-risk-ios.diff +0 -48
  115. package/pipeline/scripts/fixtures/diff-risk-test-removal.diff +0 -40
  116. package/pipeline/scripts/fixtures/install-layout.tsv +0 -19
  117. package/pipeline/scripts/fixtures/pack-expected-count.txt +0 -1
  118. package/pipeline/scripts/fixtures/test-gap-node.diff +0 -30
  119. package/pipeline/scripts/fixtures/test-gap-python.diff +0 -32
  120. package/pipeline/scripts/lint-mcp-refs.mjs +0 -218
  121. package/pipeline/scripts/lint-skills.mjs +0 -154
  122. package/pipeline/scripts/run-smokes.mjs +0 -130
  123. package/pipeline/scripts/scorecard.mjs +0 -258
  124. package/pipeline/scripts/smoke-add-detail.sh +0 -137
  125. package/pipeline/scripts/smoke-agent-guard.sh +0 -74
  126. package/pipeline/scripts/smoke-agent-log-cost.sh +0 -262
  127. package/pipeline/scripts/smoke-agent-model-routing.sh +0 -87
  128. package/pipeline/scripts/smoke-ask-choice.sh +0 -42
  129. package/pipeline/scripts/smoke-autopilot-circuit-breaker.sh +0 -36
  130. package/pipeline/scripts/smoke-bitbucket-contract.sh +0 -255
  131. package/pipeline/scripts/smoke-changelog-version.sh +0 -47
  132. package/pipeline/scripts/smoke-channels-approval-gate.sh +0 -60
  133. package/pipeline/scripts/smoke-channels-flow.sh +0 -130
  134. package/pipeline/scripts/smoke-ci-workflows.sh +0 -88
  135. package/pipeline/scripts/smoke-clarify.sh +0 -148
  136. package/pipeline/scripts/smoke-command-inventory.sh +0 -81
  137. package/pipeline/scripts/smoke-commands-skills-parity.sh +0 -87
  138. package/pipeline/scripts/smoke-community-gates.sh +0 -75
  139. package/pipeline/scripts/smoke-compliance-skills.sh +0 -119
  140. package/pipeline/scripts/smoke-config-hygiene.sh +0 -58
  141. package/pipeline/scripts/smoke-context-budget.sh +0 -72
  142. package/pipeline/scripts/smoke-cost-budget.sh +0 -70
  143. package/pipeline/scripts/smoke-cost-summary.sh +0 -139
  144. package/pipeline/scripts/smoke-cross-phase-cohesion.sh +0 -128
  145. package/pipeline/scripts/smoke-description-tr.sh +0 -82
  146. package/pipeline/scripts/smoke-dev-critic.sh +0 -144
  147. package/pipeline/scripts/smoke-diff-explain.sh +0 -147
  148. package/pipeline/scripts/smoke-diff-risk.sh +0 -190
  149. package/pipeline/scripts/smoke-dynamic-skill-loading.sh +0 -160
  150. package/pipeline/scripts/smoke-eval-live.sh +0 -136
  151. package/pipeline/scripts/smoke-evidence-gate.sh +0 -93
  152. package/pipeline/scripts/smoke-extract-conventions.sh +0 -163
  153. package/pipeline/scripts/smoke-fetchers-offline.sh +0 -448
  154. package/pipeline/scripts/smoke-figma-dispatch.sh +0 -112
  155. package/pipeline/scripts/smoke-gate-hooks.sh +0 -74
  156. package/pipeline/scripts/smoke-gc-tmp.sh +0 -130
  157. package/pipeline/scripts/smoke-gc-worktrees.sh +0 -125
  158. package/pipeline/scripts/smoke-generate-issue.sh +0 -120
  159. package/pipeline/scripts/smoke-handoff-contract.sh +0 -92
  160. package/pipeline/scripts/smoke-identity-isolation.sh +0 -70
  161. package/pipeline/scripts/smoke-install-layout.sh +0 -248
  162. package/pipeline/scripts/smoke-intent-guard.sh +0 -86
  163. package/pipeline/scripts/smoke-issue-comment-template.sh +0 -86
  164. package/pipeline/scripts/smoke-issue-jira-triad.sh +0 -120
  165. package/pipeline/scripts/smoke-keychain.sh +0 -158
  166. package/pipeline/scripts/smoke-language-axis.sh +0 -109
  167. package/pipeline/scripts/smoke-learning-curve.sh +0 -61
  168. package/pipeline/scripts/smoke-learnings-ledger.sh +0 -86
  169. package/pipeline/scripts/smoke-lib-scripts.sh +0 -448
  170. package/pipeline/scripts/smoke-mcp-gate.sh +0 -68
  171. package/pipeline/scripts/smoke-md-links.sh +0 -8
  172. package/pipeline/scripts/smoke-md2confluence.sh +0 -126
  173. package/pipeline/scripts/smoke-metrics-cache-ratio.sh +0 -72
  174. package/pipeline/scripts/smoke-migrate-state.sh +0 -102
  175. package/pipeline/scripts/smoke-mode-dispatch-drift.sh +0 -161
  176. package/pipeline/scripts/smoke-model-fallback.sh +0 -89
  177. package/pipeline/scripts/smoke-multi-repo-integration.sh +0 -116
  178. package/pipeline/scripts/smoke-multi-repo-worktree.sh +0 -61
  179. package/pipeline/scripts/smoke-no-mcp-in-dev-phases.sh +0 -194
  180. package/pipeline/scripts/smoke-no-token-prompt.sh +0 -85
  181. package/pipeline/scripts/smoke-own-punctuation.sh +0 -103
  182. package/pipeline/scripts/smoke-pack-contents.sh +0 -140
  183. package/pipeline/scripts/smoke-pat-audit.sh +0 -128
  184. package/pipeline/scripts/smoke-per-repo-memory.sh +0 -156
  185. package/pipeline/scripts/smoke-phase-0-multi-repo.sh +0 -170
  186. package/pipeline/scripts/smoke-phase-6-multi.sh +0 -79
  187. package/pipeline/scripts/smoke-phase-banner.sh +0 -101
  188. package/pipeline/scripts/smoke-phase-tracker.sh +0 -324
  189. package/pipeline/scripts/smoke-phase0-bridge-contract.sh +0 -241
  190. package/pipeline/scripts/smoke-phase4-gates.sh +0 -45
  191. package/pipeline/scripts/smoke-phase4-triage.sh +0 -229
  192. package/pipeline/scripts/smoke-plan-approval-gate.sh +0 -71
  193. package/pipeline/scripts/smoke-plan-safety.sh +0 -139
  194. package/pipeline/scripts/smoke-plan-todos.sh +0 -196
  195. package/pipeline/scripts/smoke-pr-review-actions.sh +0 -152
  196. package/pipeline/scripts/smoke-pre-commit.sh +0 -170
  197. package/pipeline/scripts/smoke-pref-migration.sh +0 -226
  198. package/pipeline/scripts/smoke-prefs-language.sh +0 -134
  199. package/pipeline/scripts/smoke-progress-contract.sh +0 -127
  200. package/pipeline/scripts/smoke-prune-logs.sh +0 -137
  201. package/pipeline/scripts/smoke-purge.sh +0 -138
  202. package/pipeline/scripts/smoke-push-retry.sh +0 -75
  203. package/pipeline/scripts/smoke-repo-map.sh +0 -300
  204. package/pipeline/scripts/smoke-review-readiness.sh +0 -92
  205. package/pipeline/scripts/smoke-review-watch.sh +0 -146
  206. package/pipeline/scripts/smoke-routines.sh +0 -84
  207. package/pipeline/scripts/smoke-run-aggregator.sh +0 -216
  208. package/pipeline/scripts/smoke-run-metrics.sh +0 -50
  209. package/pipeline/scripts/smoke-search.sh +0 -187
  210. package/pipeline/scripts/smoke-shadow-git.sh +0 -224
  211. package/pipeline/scripts/smoke-skill-authoring.sh +0 -137
  212. package/pipeline/scripts/smoke-skill-language.sh +0 -83
  213. package/pipeline/scripts/smoke-skill-manifest.sh +0 -138
  214. package/pipeline/scripts/smoke-skill-scan.sh +0 -198
  215. package/pipeline/scripts/smoke-source-parity.sh +0 -85
  216. package/pipeline/scripts/smoke-subagent-validators.sh +0 -108
  217. package/pipeline/scripts/smoke-sync-parity.sh +0 -92
  218. package/pipeline/scripts/smoke-tasklist-ordering.sh +0 -112
  219. package/pipeline/scripts/smoke-telemetry.sh +0 -147
  220. package/pipeline/scripts/smoke-test-gap.sh +0 -183
  221. package/pipeline/scripts/smoke-token-budget.sh +0 -67
  222. package/pipeline/scripts/smoke-token-preflight.sh +0 -82
  223. package/pipeline/scripts/smoke-tracker-contract.sh +0 -191
  224. package/pipeline/scripts/smoke-tracker-tokens-invocation.sh +0 -73
  225. package/pipeline/scripts/smoke-triage-memory.sh +0 -174
  226. package/pipeline/scripts/smoke-update-check.sh +0 -135
  227. package/pipeline/scripts/smoke-url-enrichment.sh +0 -70
  228. package/pipeline/scripts/smoke-validate-analysis-doc.sh +0 -161
  229. package/pipeline/scripts/smoke-validator-contradiction.sh +0 -67
  230. package/pipeline/scripts/smoke-validator-gates.sh +0 -164
  231. package/pipeline/scripts/smoke-vercel-deploy-redact.sh +0 -129
  232. package/pipeline/scripts/smoke-verify-by-test.sh +0 -148
  233. package/pipeline/scripts/smoke-wiki-integration.sh +0 -122
  234. package/pipeline/scripts/smoke-work-summary.sh +0 -163
  235. package/pipeline/scripts/smoke-workflow-audit.sh +0 -101
  236. package/pipeline/scripts/smoke-worktree-path-convention.sh +0 -86
  237. package/pipeline/scripts/smoke-wrapper-preservation.sh +0 -68
  238. package/pipeline/scripts/smoke-write-state.sh +0 -159
  239. package/pipeline/scripts/sync-parity-check.sh +0 -135
  240. package/pipeline/scripts/test-gap-rules/android.json +0 -25
  241. package/pipeline/scripts/test-gap-rules/ios.json +0 -34
  242. package/pipeline/scripts/test-gap-rules/node.json +0 -29
  243. package/pipeline/scripts/test-gap-rules/python.json +0 -25
  244. package/pipeline/scripts/validate-schemas.mjs +0 -88
@@ -1,127 +0,0 @@
1
- #!/usr/bin/env bash
2
- # smoke-progress-contract.sh - enforce the progress-line contract across phase docs.
3
- #
4
- # Verifies:
5
- # 1. Contract doc exists at refs/progress-contract.md with the required sections.
6
- # 2. Line shape example is present in the doc (so downstream consumers have a
7
- # canonical pattern to grep).
8
- # 3. progressVerbosity field exists in prefs.schema.json with enum {quiet, normal, verbose}.
9
- # 4. Adoption marker `<!-- progress-contract: applied -->` count across phase docs
10
- # is reported (advisory in v5.0.0 development; will flip to blocking at
11
- # v5.0.0 release once every phase has opted in).
12
- # 5. Phases that DO carry the marker actually emit at least one `→ <verb>` line
13
- # or reference the contract explicitly.
14
-
15
- set -euo pipefail
16
-
17
- HERE="$(cd "$(dirname "$0")" && pwd)"
18
- ROOT="$(cd "$HERE/../.." && pwd)"
19
- CONTRACT="$ROOT/pipeline/multi-agent-refs/progress-contract.md"
20
- PREFS="$ROOT/pipeline/schemas/prefs.schema.json"
21
- PHASE_DIR="$ROOT/pipeline/multi-agent-refs/phases"
22
-
23
- # Flip to "true" to make missing adoption markers blocking. Today: advisory.
24
- BLOCKING_ADOPTION="${PROGRESS_CONTRACT_BLOCKING:-false}"
25
-
26
- PASS=0
27
- FAIL=0
28
- WARN=0
29
- pass() { PASS=$((PASS+1)); echo " ✓ $1"; }
30
- fail() { FAIL=$((FAIL+1)); echo " ✗ $1"; }
31
- warn() { WARN=$((WARN+1)); echo " ⚠ $1"; }
32
-
33
- need() { command -v "$1" >/dev/null 2>&1 || { echo "error: $1 required" >&2; exit 127; }; }
34
- need jq
35
- need grep
36
-
37
- [ -f "$CONTRACT" ] || { echo "error: contract not found at $CONTRACT" >&2; exit 1; }
38
- [ -f "$PREFS" ] || { echo "error: prefs schema not found at $PREFS" >&2; exit 1; }
39
- [ -d "$PHASE_DIR" ] || { echo "error: phase docs dir not found at $PHASE_DIR" >&2; exit 1; }
40
-
41
- echo "→ 1. contract doc has required sections"
42
- for section in "## Line shape" "## When to emit" "## Verbosity" "## Telemetry" "## Phase adoption marker" "## Cross-CLI parity"; do
43
- if grep -Fq "$section" "$CONTRACT"; then
44
- pass "section present: $section"
45
- else
46
- fail "section missing: $section"
47
- fi
48
- done
49
-
50
- echo ""
51
- echo "→ 2. canonical line-shape template present"
52
- # The doc should show: ` → <verb> <object>[ <target>]`
53
- if grep -qE '→ <verb> <object>' "$CONTRACT"; then
54
- pass "canonical shape '→ <verb> <object>' present"
55
- else
56
- fail "canonical shape missing"
57
- fi
58
-
59
- echo ""
60
- echo "→ 3. prefs schema declares progressVerbosity with correct enum"
61
- VERBOSITY_ENUM=$(jq -c '.properties.global.properties.progressVerbosity.enum' "$PREFS")
62
- if [ "$VERBOSITY_ENUM" = '["quiet","normal","verbose"]' ]; then
63
- pass "progressVerbosity.enum = [quiet, normal, verbose]"
64
- else
65
- fail "progressVerbosity.enum wrong: $VERBOSITY_ENUM"
66
- fi
67
- DEFAULT=$(jq -r '.properties.global.properties.progressVerbosity.default' "$PREFS")
68
- [ "$DEFAULT" = "normal" ] && pass "default = normal" || fail "default should be normal, got '$DEFAULT'"
69
-
70
- echo ""
71
- echo "→ 4. phase adoption marker inventory"
72
- TOTAL_PHASES=0
73
- ADOPTED=0
74
- MISSING=()
75
- for doc in "$PHASE_DIR"/phase-*.md; do
76
- [ -f "$doc" ] || continue
77
- TOTAL_PHASES=$((TOTAL_PHASES+1))
78
- if grep -Fq "<!-- progress-contract: applied -->" "$doc"; then
79
- ADOPTED=$((ADOPTED+1))
80
- else
81
- MISSING+=("$(basename "$doc")")
82
- fi
83
- done
84
- echo " phases scanned: $TOTAL_PHASES"
85
- echo " adopted: $ADOPTED"
86
- if [ "${#MISSING[@]}" -eq 0 ]; then
87
- pass "all phases have the adoption marker"
88
- else
89
- if [ "$BLOCKING_ADOPTION" = "true" ]; then
90
- fail "missing adoption in ${#MISSING[@]} phases: ${MISSING[*]}"
91
- else
92
- warn "advisory - missing adoption in ${#MISSING[@]} phases: ${MISSING[*]}"
93
- fi
94
- fi
95
-
96
- echo ""
97
- echo "→ 5. phases that DO adopt the marker actually emit progress lines"
98
- BROKEN_ADOPTIONS=()
99
- for doc in "$PHASE_DIR"/phase-*.md; do
100
- [ -f "$doc" ] || continue
101
- if grep -Fq "<!-- progress-contract: applied -->" "$doc"; then
102
- # Must reference the contract OR show at least one sample `→ <verb>` line.
103
- if grep -qE '→ (fetching|reading|running|writing|posting|waiting|dispatching|retrying|building|committing|checking) ' "$doc" \
104
- || grep -Fq "refs/progress-contract.md" "$doc"; then
105
- pass "$(basename "$doc") carries marker + shows progress usage"
106
- else
107
- fail "$(basename "$doc") has marker but no sample progress line or contract link"
108
- BROKEN_ADOPTIONS+=("$(basename "$doc")")
109
- fi
110
- fi
111
- done
112
- if [ "$ADOPTED" -eq 0 ]; then
113
- warn "no phases have adopted yet - this is expected until WS-4/5/6 land"
114
- fi
115
-
116
- echo ""
117
- echo "→ Live mirror cross-link (tracker coupling)"
118
- if grep -q "Live mirror to the phase tracker" "$CONTRACT" \
119
- && grep -q "phase-tracker.sh now" "$CONTRACT"; then
120
- pass "contract cross-links the tracker mirror rule"
121
- else
122
- fail "contract missing the live-mirror cross-link to tracker-contract.md"
123
- fi
124
-
125
- echo ""
126
- echo "══ progress-contract smoke: $PASS passed, $WARN warnings, $FAIL failed ══"
127
- [ "$FAIL" -eq 0 ]
@@ -1,137 +0,0 @@
1
- #!/usr/bin/env bash
2
- # smoke-prune-logs.sh - prune-logs.sh removes per-task log dirs, honors the
3
- # project/task/age filters, is dry-run by default, NEVER deletes the audit
4
- # trail or metrics corpus (even under adversarial dir names), refuses unsafe
5
- # log roots, and spares active task dirs.
6
- #
7
- # Exit 0 = all pass, 1 = any failure.
8
-
9
- set -uo pipefail
10
-
11
- ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
12
- PL="$ROOT/pipeline/scripts/prune-logs.sh"
13
- PASS=0
14
- FAIL=0
15
- pass() {
16
- PASS=$((PASS + 1))
17
- echo " ✓ $1"
18
- }
19
- fail() {
20
- FAIL=$((FAIL + 1))
21
- echo " ✗ $1"
22
- }
23
- [ -f "$PL" ] || {
24
- echo "FAIL: prune-logs.sh missing" >&2
25
- exit 1
26
- }
27
-
28
- LR="$(mktemp -d)"
29
- trap 'rm -rf "$LR"' EXIT
30
-
31
- seed() {
32
- rm -rf "${LR:?}"/*
33
- mkdir -p "$LR/my-ios-app/PROJ-1" "$LR/my-ios-app/PROJ-2" "$LR/other/PROJ-9"
34
- echo '{}' >"$LR/my-ios-app/PROJ-1/agent-state.json"
35
- echo '{}' >"$LR/my-ios-app/PROJ-2/tracker-state.json"
36
- echo '{}' >"$LR/other/PROJ-9/agent-log.md"
37
- echo 'audit' >"$LR/audit.jsonl"
38
- echo 'metric' >"$LR/metrics.jsonl"
39
- echo '5' >"$LR/my-ios-app/.counter"
40
- }
41
-
42
- echo "→ 1. dry-run lists task dirs and deletes nothing"
43
- seed
44
- out=$(PRUNE_LOG_ROOT="$LR" PRUNE_GRACE_MIN=0 bash "$PL" 2>&1)
45
- echo "$out" | grep -q "DRY-RUN" && pass "dry-run banner shown" || fail "dry-run banner missing"
46
- [ -f "$LR/my-ios-app/PROJ-1/agent-state.json" ] && pass "dry-run kept task dirs" || fail "dry-run deleted a task dir"
47
- echo "$out" | grep -qi "preserved" && pass "dry-run states audit/metrics are preserved" || fail "no preservation note"
48
-
49
- echo ""
50
- echo "→ 2. --yes deletes task dirs but preserves audit + metrics + .counter"
51
- seed
52
- PRUNE_LOG_ROOT="$LR" PRUNE_GRACE_MIN=0 bash "$PL" --yes >/dev/null 2>&1
53
- [ -f "$LR/audit.jsonl" ] && pass "audit.jsonl preserved" || fail "audit.jsonl was deleted"
54
- [ -f "$LR/metrics.jsonl" ] && pass "metrics.jsonl preserved" || fail "metrics.jsonl was deleted"
55
- [ -f "$LR/my-ios-app/.counter" ] && pass ".counter preserved" || fail ".counter was deleted"
56
- [ ! -e "$LR/my-ios-app/PROJ-1" ] && pass "task dir PROJ-1 removed" || fail "task dir PROJ-1 survived"
57
- [ ! -e "$LR/other/PROJ-9" ] && pass "task dir PROJ-9 removed" || fail "task dir PROJ-9 survived"
58
-
59
- echo ""
60
- echo "→ 3. --project scopes deletion to one project"
61
- seed
62
- PRUNE_LOG_ROOT="$LR" PRUNE_GRACE_MIN=0 bash "$PL" --project=my-ios-app --yes >/dev/null 2>&1
63
- [ ! -e "$LR/my-ios-app/PROJ-1" ] && pass "my-ios-app task removed" || fail "my-ios-app task survived"
64
- [ -f "$LR/other/PROJ-9/agent-log.md" ] && pass "other project untouched" || fail "other project was deleted"
65
-
66
- echo ""
67
- echo "→ 4. --task scopes deletion to one task dir"
68
- seed
69
- PRUNE_LOG_ROOT="$LR" PRUNE_GRACE_MIN=0 bash "$PL" --task=PROJ-1 --yes >/dev/null 2>&1
70
- [ ! -e "$LR/my-ios-app/PROJ-1" ] && pass "PROJ-1 removed" || fail "PROJ-1 survived"
71
- [ -f "$LR/my-ios-app/PROJ-2/tracker-state.json" ] && pass "PROJ-2 untouched" || fail "PROJ-2 was deleted"
72
-
73
- echo ""
74
- echo "→ 5. --older-than excludes fresh task dirs"
75
- seed
76
- out=$(PRUNE_LOG_ROOT="$LR" PRUNE_GRACE_MIN=0 bash "$PL" --older-than=1 2>&1)
77
- echo "$out" | grep -q "nothing" && pass "freshly-created dirs excluded by --older-than=1" || fail "--older-than did not exclude fresh dirs"
78
-
79
- echo ""
80
- echo "→ 6. usage errors + empty root"
81
- PRUNE_LOG_ROOT="$LR" bash "$PL" --bogus >/dev/null 2>&1
82
- [ "$?" = "2" ] && pass "unknown argument exits 2" || fail "unknown argument did not exit 2"
83
- PRUNE_LOG_ROOT="/nonexistent-$$-dir" bash "$PL" >/dev/null 2>&1
84
- [ "$?" = "0" ] && pass "missing log root exits 0 (no-op)" || fail "missing log root did not exit 0"
85
-
86
- echo ""
87
- echo "→ 7. adversarial dirs named like preserved files survive --yes"
88
- rm -rf "${LR:?}"/*
89
- mkdir -p "$LR/audit.jsonl" "$LR/proj/metrics.jsonl" "$LR/proj/metrics-summary.md" "$LR/proj/.counter" "$LR/proj/PROJ-5"
90
- echo '{}' >"$LR/audit.jsonl/agent-state.json"
91
- echo '{}' >"$LR/proj/metrics.jsonl/agent-log.md"
92
- echo '{}' >"$LR/proj/metrics-summary.md/tracker-state.json"
93
- echo '{}' >"$LR/proj/.counter/agent-state.json"
94
- echo '{}' >"$LR/proj/PROJ-5/agent-state.json"
95
- PRUNE_LOG_ROOT="$LR" PRUNE_GRACE_MIN=0 bash "$PL" --yes >/dev/null 2>&1
96
- [ -d "$LR/audit.jsonl" ] && pass "dir named audit.jsonl spared" || fail "dir named audit.jsonl deleted"
97
- [ -d "$LR/proj/metrics.jsonl" ] && pass "dir named metrics.jsonl spared" || fail "dir named metrics.jsonl deleted"
98
- [ -d "$LR/proj/metrics-summary.md" ] && pass "dir named metrics-summary.md spared" || fail "dir named metrics-summary.md deleted"
99
- [ -d "$LR/proj/.counter" ] && pass "dir named .counter spared" || fail "dir named .counter deleted"
100
- [ ! -e "$LR/proj/PROJ-5" ] && pass "normal task dir beside them still removed" || fail "normal task dir survived"
101
-
102
- echo ""
103
- echo "→ 8. unsafe log roots are refused (exit 2, dry-run only)"
104
- PRUNE_LOG_ROOT="$HOME" bash "$PL" >/dev/null 2>&1
105
- [ "$?" = "2" ] && pass "\$HOME as log root refused" || fail "\$HOME as log root not refused"
106
- GITROOT="$(mktemp -d)"
107
- mkdir -p "$GITROOT/.git"
108
- PRUNE_LOG_ROOT="$GITROOT" bash "$PL" --yes >/dev/null 2>&1
109
- rc=$?
110
- rm -rf "$GITROOT"
111
- [ "$rc" = "2" ] && pass "git work tree as log root refused" || fail "git work tree as log root not refused"
112
-
113
- echo ""
114
- echo "→ 9. default grace spares freshly-touched (active) task dirs"
115
- seed
116
- out=$(PRUNE_LOG_ROOT="$LR" bash "$PL" --yes 2>&1)
117
- rc=$?
118
- [ "$rc" = "0" ] && pass "grace run exits 0" || fail "grace run exited $rc"
119
- [ -f "$LR/my-ios-app/PROJ-1/agent-state.json" ] && pass "active task dir spared by default grace" || fail "default grace deleted an active task dir"
120
- echo "$out" | grep -qi "spared" && pass "output mentions spared active dirs" || fail "no spared-active note in output"
121
- PRUNE_LOG_ROOT="$LR" bash "$PL" --task=PROJ-1 --yes >/dev/null 2>&1
122
- [ ! -e "$LR/my-ios-app/PROJ-1" ] && pass "explicit --task bypasses the grace" || fail "--task did not bypass the grace"
123
-
124
- echo ""
125
- echo "→ 10. traversal-shaped --task/--project values are rejected"
126
- PRUNE_LOG_ROOT="$LR" bash "$PL" "--task=../evil" >/dev/null 2>&1
127
- [ "$?" = "2" ] && pass "--task=../evil exits 2" || fail "--task=../evil accepted"
128
- PRUNE_LOG_ROOT="$LR" bash "$PL" "--task=.counter" >/dev/null 2>&1
129
- [ "$?" = "2" ] && pass "--task=.counter (leading dot) exits 2" || fail "--task=.counter accepted"
130
- PRUNE_LOG_ROOT="$LR" bash "$PL" "--project=a/b" >/dev/null 2>&1
131
- [ "$?" = "2" ] && pass "--project=a/b exits 2" || fail "--project=a/b accepted"
132
- PRUNE_LOG_ROOT="$LR" bash "$PL" "--task=" >/dev/null 2>&1
133
- [ "$?" = "2" ] && pass "empty --task exits 2" || fail "empty --task accepted"
134
-
135
- echo ""
136
- echo "══ prune-logs smoke: $PASS passed, $FAIL failed ══"
137
- [ "$FAIL" -eq 0 ]
@@ -1,138 +0,0 @@
1
- #!/usr/bin/env bash
2
- # smoke-purge.sh - purge.sh wipes .worktrees/ worktrees (registered and
3
- # orphaned), their local branches, and the project task counter; is dry-run
4
- # by default; preserves the main worktree, protected branches, and the
5
- # audit/metrics corpus; and never follows symlinks out of .worktrees/.
6
- #
7
- # Exit 0 = all pass, 1 = any failure.
8
-
9
- set -uo pipefail
10
-
11
- ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
12
- PG="$ROOT/pipeline/scripts/purge.sh"
13
- PASS=0
14
- FAIL=0
15
- pass() {
16
- PASS=$((PASS + 1))
17
- echo " ✓ $1"
18
- }
19
- fail() {
20
- FAIL=$((FAIL + 1))
21
- echo " ✗ $1"
22
- }
23
- [ -f "$PG" ] || {
24
- echo "FAIL: purge.sh missing" >&2
25
- exit 1
26
- }
27
-
28
- SB="$(cd "$(mktemp -d)" && pwd -P)"
29
- trap 'rm -rf "$SB"' EXIT
30
-
31
- REPO="$SB/repo"
32
- LR="$SB/logs"
33
- VICTIM="$SB/victim"
34
-
35
- seed() {
36
- rm -rf "$REPO" "$LR" "$VICTIM"
37
- mkdir -p "$REPO" "$LR/repo" "$VICTIM"
38
- echo keep >"$VICTIM/keep.txt"
39
- git -C "$REPO" init -q -b main
40
- git -C "$REPO" -c user.email=t@t.t -c user.name=t commit -q --allow-empty -m init
41
- git -C "$REPO" worktree add -q -b feature/PROJ-1-x "$REPO/.worktrees/PROJ-1" >/dev/null 2>&1
42
- git -C "$REPO" worktree add -q -b bugfix/PROJ-2-y "$REPO/.worktrees/PROJ-2" >/dev/null 2>&1
43
- mkdir -p "$REPO/.worktrees/PROJ-9" # orphan: dir git no longer registers
44
- echo '{}' >"$REPO/.worktrees/PROJ-9/agent-state.json"
45
- ln -s "$VICTIM" "$REPO/.worktrees/evil-link" # symlink escape attempt
46
- echo '7' >"$LR/repo/.counter"
47
- echo audit >"$LR/audit.jsonl"
48
- echo metric >"$LR/metrics.jsonl"
49
- }
50
-
51
- has_branch() {
52
- git -C "$REPO" show-ref --verify -q "refs/heads/$1"
53
- }
54
-
55
- echo "→ 1. dry-run lists everything and deletes nothing"
56
- seed
57
- out=$(PURGE_LOG_ROOT="$LR" bash "$PG" --repo "$REPO" 2>&1)
58
- rc=$?
59
- [ "$rc" = "0" ] && pass "dry-run exits 0" || fail "dry-run exited $rc"
60
- echo "$out" | grep -q "DRY-RUN" && pass "dry-run banner shown" || fail "dry-run banner missing"
61
- echo "$out" | grep -q "PROJ-1" && pass "worktree PROJ-1 listed" || fail "worktree PROJ-1 not listed"
62
- echo "$out" | grep -q "feature/PROJ-1-x" && pass "branch listed" || fail "branch not listed"
63
- echo "$out" | grep -q ".counter" && pass "counter listed" || fail "counter not listed"
64
- [ -d "$REPO/.worktrees/PROJ-1" ] && pass "dry-run kept worktrees" || fail "dry-run deleted a worktree"
65
- [ -f "$LR/repo/.counter" ] && pass "dry-run kept the counter" || fail "dry-run deleted the counter"
66
- has_branch feature/PROJ-1-x && pass "dry-run kept branches" || fail "dry-run deleted a branch"
67
-
68
- echo ""
69
- echo "→ 2. --yes wipes worktrees + branches + counter, preserves the rest"
70
- seed
71
- PURGE_LOG_ROOT="$LR" bash "$PG" --repo "$REPO" --yes >/dev/null 2>&1
72
- rc=$?
73
- [ "$rc" = "0" ] && pass "--yes exits 0" || fail "--yes exited $rc"
74
- [ ! -e "$REPO/.worktrees/PROJ-1" ] && pass "registered worktree PROJ-1 removed" || fail "PROJ-1 survived"
75
- [ ! -e "$REPO/.worktrees/PROJ-2" ] && pass "registered worktree PROJ-2 removed" || fail "PROJ-2 survived"
76
- [ ! -e "$REPO/.worktrees/PROJ-9" ] && pass "orphan worktree dir removed" || fail "orphan PROJ-9 survived"
77
- ! has_branch feature/PROJ-1-x && pass "branch feature/PROJ-1-x deleted" || fail "feature/PROJ-1-x survived"
78
- ! has_branch bugfix/PROJ-2-y && pass "branch bugfix/PROJ-2-y deleted" || fail "bugfix/PROJ-2-y survived"
79
- has_branch main && pass "main branch preserved" || fail "main branch was deleted"
80
- git -C "$REPO" rev-parse --is-inside-work-tree >/dev/null 2>&1 && pass "main worktree still a git repo" || fail "main worktree destroyed"
81
- wt_count=$(git -C "$REPO" worktree list 2>/dev/null | wc -l | tr -d ' ')
82
- [ "$wt_count" = "1" ] && pass "only the main worktree remains registered" || fail "expected 1 registered worktree, got $wt_count"
83
- [ ! -e "$LR/repo/.counter" ] && pass "task counter removed" || fail "task counter survived"
84
- [ -f "$LR/audit.jsonl" ] && pass "audit.jsonl preserved" || fail "audit.jsonl was deleted"
85
- [ -f "$LR/metrics.jsonl" ] && pass "metrics.jsonl preserved" || fail "metrics.jsonl was deleted"
86
- [ -f "$VICTIM/keep.txt" ] && pass "symlink target outside repo untouched" || fail "symlink target was deleted"
87
-
88
- echo ""
89
- echo "→ 3. protected branch carried by a worktree survives, worktree still removed"
90
- seed
91
- git -C "$REPO" worktree add -q -b develop "$REPO/.worktrees/DEV-1" >/dev/null 2>&1
92
- PURGE_LOG_ROOT="$LR" bash "$PG" --repo "$REPO" --yes >/dev/null 2>&1
93
- [ ! -e "$REPO/.worktrees/DEV-1" ] && pass "develop worktree removed" || fail "develop worktree survived"
94
- has_branch develop && pass "develop branch preserved" || fail "develop branch was deleted"
95
-
96
- echo ""
97
- echo "→ 4. clean repo and non-repo are no-ops (exit 0)"
98
- CLEAN="$SB/clean"
99
- mkdir -p "$CLEAN"
100
- git -C "$CLEAN" init -q -b main
101
- out=$(PURGE_LOG_ROOT="$LR" bash "$PG" --repo "$CLEAN" 2>&1)
102
- rc=$?
103
- { [ "$rc" = "0" ] && echo "$out" | grep -q "nothing to do"; } && pass "clean repo is a no-op" || fail "clean repo not a clean no-op (rc=$rc)"
104
- PLAIN="$SB/plain"
105
- mkdir -p "$PLAIN"
106
- out=$(bash "$PG" --repo "$PLAIN" 2>&1)
107
- rc=$?
108
- { [ "$rc" = "0" ] && echo "$out" | grep -q "not a git work tree"; } && pass "non-repo dir is a no-op" || fail "non-repo dir not a clean no-op (rc=$rc)"
109
-
110
- echo ""
111
- echo "→ 5. usage errors exit 2"
112
- bash "$PG" --bogus >/dev/null 2>&1
113
- [ "$?" = "2" ] && pass "unknown argument exits 2" || fail "unknown argument did not exit 2"
114
- bash "$PG" --repo >/dev/null 2>&1
115
- [ "$?" = "2" ] && pass "--repo without a path exits 2" || fail "--repo without a path did not exit 2"
116
-
117
- echo ""
118
- echo "→ 6. --delete-remote without a remote warns but does not fail"
119
- seed
120
- out=$(PURGE_LOG_ROOT="$LR" bash "$PG" --repo "$REPO" --delete-remote 2>&1)
121
- echo "$out" | grep -q "remote branch origin/feature/PROJ-1-x" && pass "dry-run lists remote branch deletion" || fail "dry-run missing remote branch line"
122
- out=$(PURGE_LOG_ROOT="$LR" bash "$PG" --repo "$REPO" --delete-remote --yes 2>&1)
123
- rc=$?
124
- [ "$rc" = "0" ] && pass "--delete-remote --yes exits 0 without a remote" || fail "--delete-remote --yes exited $rc"
125
- echo "$out" | grep -qi "warning" && pass "missing remote surfaces a warning" || fail "no warning for missing remote"
126
-
127
- echo ""
128
- echo "→ 7. purge from inside a linked worktree still anchors on the main repo"
129
- seed
130
- out=$(PURGE_LOG_ROOT="$LR" bash "$PG" --repo "$REPO/.worktrees/PROJ-1" --yes 2>&1)
131
- rc=$?
132
- [ "$rc" = "0" ] && pass "run from linked worktree exits 0" || fail "run from linked worktree exited $rc"
133
- [ ! -e "$REPO/.worktrees/PROJ-1" ] && pass "worktrees removed when invoked from inside one" || fail "worktrees survived"
134
- git -C "$REPO" rev-parse --is-inside-work-tree >/dev/null 2>&1 && pass "main repo intact" || fail "main repo destroyed"
135
-
136
- echo ""
137
- echo "══ purge smoke: $PASS passed, $FAIL failed ══"
138
- [ "$FAIL" -eq 0 ]
@@ -1,75 +0,0 @@
1
- #!/usr/bin/env bash
2
- # smoke-push-retry.sh - asserts the push-must-succeed policy is documented
3
- # correctly in Phase 6 and gated by settings.pushMustSucceed.
4
-
5
- set -uo pipefail
6
-
7
- PHASE6="$HOME/.claude/multi-agent-refs/phases/phase-6-commit.md"
8
- PREFS_SCHEMA="$HOME/.claude/schemas/prefs.schema.json"
9
-
10
- PASS=0; FAIL=0
11
- pass() { PASS=$((PASS+1)); echo " ✓ $1"; }
12
- fail() { FAIL=$((FAIL+1)); echo " ✗ $1"; }
13
-
14
- if [ ! -f "$PHASE6" ]; then
15
- fail "phase-6-commit.md missing"; echo "══ aborted ══"; exit 2
16
- fi
17
-
18
- echo "→ 1. Push-must-succeed gate flag"
19
- grep -q "settings.pushMustSucceed" "$PHASE6" \
20
- && pass "Phase 6 references settings.pushMustSucceed gate" \
21
- || fail "settings.pushMustSucceed gate missing in Phase 6"
22
- [ -f "$PREFS_SCHEMA" ] && grep -q '"pushMustSucceed"' "$PREFS_SCHEMA" \
23
- && pass "Schema declares settings.pushMustSucceed" \
24
- || fail "Schema missing settings.pushMustSucceed"
25
-
26
- echo "→ 2. Retry budget"
27
- grep -q "settings.pushRetryMax" "$PHASE6" \
28
- && pass "Phase 6 references settings.pushRetryMax" \
29
- || fail "settings.pushRetryMax reference missing"
30
- [ -f "$PREFS_SCHEMA" ] && grep -q '"pushRetryMax"' "$PREFS_SCHEMA" \
31
- && pass "Schema declares settings.pushRetryMax" \
32
- || fail "Schema missing settings.pushRetryMax"
33
- grep -q "default 5\|default \`5\`" "$PHASE6" \
34
- && pass "Default retry budget 5 documented" \
35
- || fail "Default retry budget 5 missing"
36
-
37
- echo "→ 3. Rebase before push"
38
- grep -q "git -C \"\$WT_PATH\" fetch origin" "$PHASE6" \
39
- && pass "Re-fetch origin before push" \
40
- || fail "Re-fetch step missing"
41
- grep -q "git -C \"\$WT_PATH\" rebase" "$PHASE6" \
42
- && pass "Rebase on advancing base" \
43
- || fail "Rebase step missing"
44
- grep -q "rebase conflict: abort" "$PHASE6" \
45
- && pass "Rebase-conflict aborts cleanly" \
46
- || fail "Rebase-conflict abort missing"
47
-
48
- echo "→ 4. Back-off between attempts"
49
- grep -q "sleep" "$PHASE6" \
50
- && pass "Back-off sleep between push attempts" \
51
- || fail "Back-off sleep missing"
52
- grep -qE "back-off:\s*2,4,6,8" "$PHASE6" \
53
- && pass "Documented back-off cadence (2,4,6,8s)" \
54
- || fail "Back-off cadence not documented"
55
-
56
- echo "→ 5. Final-fail user prompt (4 options)"
57
- for opt in "Resolve conflict manually" "different base branch" "Skip this repo" "Pause Phase 6"; do
58
- grep -q "$opt" "$PHASE6" \
59
- && pass "Final-fail option present: $opt" \
60
- || fail "Final-fail option missing: $opt"
61
- done
62
-
63
- echo "→ 6. Push status persistence"
64
- grep -q "state.projects\[i\].pushStatus" "$PHASE6" \
65
- && pass "pushStatus persisted to state" \
66
- || fail "pushStatus persistence missing"
67
- for v in '"pushed"' '"rebase-pushed"' '"skipped"' '"paused"'; do
68
- grep -q "$v" "$PHASE6" \
69
- && pass "pushStatus enum value: $v" \
70
- || fail "pushStatus enum value missing: $v"
71
- done
72
-
73
- echo ""
74
- echo "══ push-retry smoke: $PASS passed, $FAIL failed ══"
75
- [ "$FAIL" -eq 0 ]