@glrs-dev/cli 0.0.1 → 0.1.1

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 (173) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/README.md +14 -15
  3. package/dist/chunk-3RG5ZIWI.js +10 -0
  4. package/dist/chunk-6RHN2EDH.js +93 -0
  5. package/dist/chunk-DEODG2LC.js +55 -0
  6. package/dist/chunk-FSAGM22T.js +17 -0
  7. package/dist/chunk-GQBZREK5.js +136 -0
  8. package/dist/chunk-HWMRY35D.js +139 -0
  9. package/dist/chunk-LMRDQ4GW.js +129 -0
  10. package/dist/chunk-NLPX2KOF.js +149 -0
  11. package/dist/chunk-P7PRH4I3.js +177 -0
  12. package/dist/chunk-VCN7RNLU.js +60 -0
  13. package/dist/chunk-VJFNIKQJ.js +120 -0
  14. package/dist/chunk-W37UX3U2.js +35 -0
  15. package/dist/chunk-YBCA3IP6.js +25 -0
  16. package/dist/chunk-YGNDPKIW.js +99 -0
  17. package/dist/cli.d.ts +1 -1
  18. package/dist/cli.js +89 -36
  19. package/dist/commands/cleanup.d.ts +19 -0
  20. package/dist/commands/cleanup.js +11 -0
  21. package/dist/commands/create.d.ts +17 -0
  22. package/dist/commands/create.js +12 -0
  23. package/dist/commands/delete.d.ts +17 -0
  24. package/dist/commands/delete.js +12 -0
  25. package/dist/commands/go.d.ts +4 -0
  26. package/dist/commands/go.js +11 -0
  27. package/dist/commands/list.d.ts +15 -0
  28. package/dist/commands/list.js +12 -0
  29. package/dist/commands/switch.d.ts +11 -0
  30. package/dist/commands/switch.js +12 -0
  31. package/dist/commands/types.d.ts +10 -0
  32. package/dist/commands/types.js +0 -0
  33. package/dist/index.d.ts +16 -19
  34. package/dist/index.js +4 -1
  35. package/dist/lib/config.d.ts +14 -0
  36. package/dist/lib/config.js +14 -0
  37. package/dist/lib/fmt.d.ts +12 -0
  38. package/dist/lib/fmt.js +25 -0
  39. package/dist/lib/git.d.ts +26 -0
  40. package/dist/lib/git.js +25 -0
  41. package/dist/lib/registry.d.ts +14 -0
  42. package/dist/lib/registry.js +13 -0
  43. package/dist/lib/select.d.ts +21 -0
  44. package/dist/lib/select.js +10 -0
  45. package/dist/lib/worktree.d.ts +35 -0
  46. package/dist/lib/worktree.js +17 -0
  47. package/dist/vendor/harness-opencode/dist/agents/prompts/agents-md-writer.md +89 -0
  48. package/dist/vendor/harness-opencode/dist/agents/prompts/architecture-advisor.md +46 -0
  49. package/dist/vendor/harness-opencode/dist/agents/prompts/build.md +93 -0
  50. package/dist/vendor/harness-opencode/dist/agents/prompts/code-searcher.md +54 -0
  51. package/dist/vendor/harness-opencode/dist/agents/prompts/docs-maintainer.md +128 -0
  52. package/dist/vendor/harness-opencode/dist/agents/prompts/gap-analyzer.md +44 -0
  53. package/dist/vendor/harness-opencode/dist/agents/prompts/lib-reader.md +39 -0
  54. package/dist/vendor/harness-opencode/dist/agents/prompts/pilot-builder.md +107 -0
  55. package/dist/vendor/harness-opencode/dist/agents/prompts/pilot-planner.md +153 -0
  56. package/dist/vendor/harness-opencode/dist/agents/prompts/plan-reviewer.md +49 -0
  57. package/dist/vendor/harness-opencode/dist/agents/prompts/plan.md +144 -0
  58. package/dist/vendor/harness-opencode/dist/agents/prompts/prime.md +374 -0
  59. package/dist/vendor/harness-opencode/dist/agents/prompts/qa-reviewer.md +68 -0
  60. package/dist/vendor/harness-opencode/dist/agents/prompts/qa-thorough.md +63 -0
  61. package/dist/vendor/harness-opencode/dist/agents/prompts/research.md +138 -0
  62. package/dist/vendor/harness-opencode/dist/agents/shared/index.ts +26 -0
  63. package/dist/vendor/harness-opencode/dist/agents/shared/workflow-mechanics.md +32 -0
  64. package/dist/vendor/harness-opencode/dist/bin/memory-mcp-launcher.sh +145 -0
  65. package/dist/vendor/harness-opencode/dist/bin/plan-check.sh +255 -0
  66. package/dist/vendor/harness-opencode/dist/chunk-VJUETC6A.js +205 -0
  67. package/dist/vendor/harness-opencode/dist/chunk-VVMP6QWS.js +731 -0
  68. package/dist/vendor/harness-opencode/dist/chunk-XCZ3NOXR.js +703 -0
  69. package/dist/vendor/harness-opencode/dist/cli.d.ts +1 -0
  70. package/dist/vendor/harness-opencode/dist/cli.js +5096 -0
  71. package/dist/vendor/harness-opencode/dist/commands/prompts/autopilot.md +96 -0
  72. package/dist/vendor/harness-opencode/dist/commands/prompts/costs.md +94 -0
  73. package/dist/vendor/harness-opencode/dist/commands/prompts/fresh.md +382 -0
  74. package/dist/vendor/harness-opencode/dist/commands/prompts/init-deep.md +196 -0
  75. package/dist/vendor/harness-opencode/dist/commands/prompts/research.md +27 -0
  76. package/dist/vendor/harness-opencode/dist/commands/prompts/review.md +96 -0
  77. package/dist/vendor/harness-opencode/dist/commands/prompts/ship.md +104 -0
  78. package/dist/vendor/harness-opencode/dist/index.d.ts +21 -0
  79. package/dist/vendor/harness-opencode/dist/index.js +2092 -0
  80. package/dist/vendor/harness-opencode/dist/install-4EYR56OR.js +9 -0
  81. package/dist/vendor/harness-opencode/dist/skills/agent-estimation/SKILL.md +159 -0
  82. package/dist/vendor/harness-opencode/dist/skills/paths.ts +18 -0
  83. package/dist/vendor/harness-opencode/dist/skills/pilot-planning/SKILL.md +49 -0
  84. package/dist/vendor/harness-opencode/dist/skills/pilot-planning/rules/dag-shape.md +47 -0
  85. package/dist/vendor/harness-opencode/dist/skills/pilot-planning/rules/decomposition.md +36 -0
  86. package/dist/vendor/harness-opencode/dist/skills/pilot-planning/rules/first-principles.md +29 -0
  87. package/dist/vendor/harness-opencode/dist/skills/pilot-planning/rules/milestones.md +57 -0
  88. package/dist/vendor/harness-opencode/dist/skills/pilot-planning/rules/self-review.md +46 -0
  89. package/dist/vendor/harness-opencode/dist/skills/pilot-planning/rules/task-context.md +47 -0
  90. package/dist/vendor/harness-opencode/dist/skills/pilot-planning/rules/touches-scope.md +47 -0
  91. package/dist/vendor/harness-opencode/dist/skills/pilot-planning/rules/verify-design.md +53 -0
  92. package/dist/vendor/harness-opencode/dist/skills/research/SKILL.md +350 -0
  93. package/dist/vendor/harness-opencode/dist/skills/research-auto/SKILL.md +283 -0
  94. package/dist/vendor/harness-opencode/dist/skills/research-local/SKILL.md +268 -0
  95. package/dist/vendor/harness-opencode/dist/skills/research-web/SKILL.md +119 -0
  96. package/dist/vendor/harness-opencode/dist/skills/review-plan/SKILL.md +32 -0
  97. package/dist/vendor/harness-opencode/dist/skills/vercel-composition-patterns/AGENTS.md +946 -0
  98. package/dist/vendor/harness-opencode/dist/skills/vercel-composition-patterns/README.md +60 -0
  99. package/dist/vendor/harness-opencode/dist/skills/vercel-composition-patterns/SKILL.md +89 -0
  100. package/dist/vendor/harness-opencode/dist/skills/vercel-composition-patterns/rules/architecture-avoid-boolean-props.md +100 -0
  101. package/dist/vendor/harness-opencode/dist/skills/vercel-composition-patterns/rules/architecture-compound-components.md +112 -0
  102. package/dist/vendor/harness-opencode/dist/skills/vercel-composition-patterns/rules/patterns-children-over-render-props.md +87 -0
  103. package/dist/vendor/harness-opencode/dist/skills/vercel-composition-patterns/rules/patterns-explicit-variants.md +100 -0
  104. package/dist/vendor/harness-opencode/dist/skills/vercel-composition-patterns/rules/react19-no-forwardref.md +42 -0
  105. package/dist/vendor/harness-opencode/dist/skills/vercel-composition-patterns/rules/state-context-interface.md +191 -0
  106. package/dist/vendor/harness-opencode/dist/skills/vercel-composition-patterns/rules/state-decouple-implementation.md +113 -0
  107. package/dist/vendor/harness-opencode/dist/skills/vercel-composition-patterns/rules/state-lift-state.md +125 -0
  108. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/AGENTS.md +2975 -0
  109. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/README.md +123 -0
  110. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/SKILL.md +137 -0
  111. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  112. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/advanced-init-once.md +42 -0
  113. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/advanced-use-latest.md +39 -0
  114. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/async-api-routes.md +38 -0
  115. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/async-defer-await.md +80 -0
  116. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/async-dependencies.md +51 -0
  117. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/async-parallel.md +28 -0
  118. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md +99 -0
  119. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md +59 -0
  120. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/bundle-conditional.md +31 -0
  121. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md +49 -0
  122. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md +35 -0
  123. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/bundle-preload.md +50 -0
  124. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/client-event-listeners.md +74 -0
  125. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/client-localstorage-schema.md +71 -0
  126. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md +48 -0
  127. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/client-swr-dedup.md +56 -0
  128. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/js-batch-dom-css.md +107 -0
  129. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/js-cache-function-results.md +80 -0
  130. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/js-cache-property-access.md +28 -0
  131. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/js-cache-storage.md +70 -0
  132. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/js-combine-iterations.md +32 -0
  133. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/js-early-exit.md +50 -0
  134. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/js-hoist-regexp.md +45 -0
  135. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/js-index-maps.md +37 -0
  136. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/js-length-check-first.md +49 -0
  137. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/js-min-max-loop.md +82 -0
  138. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/js-set-map-lookups.md +24 -0
  139. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md +57 -0
  140. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/rendering-activity.md +26 -0
  141. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
  142. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/rendering-conditional-render.md +40 -0
  143. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/rendering-content-visibility.md +38 -0
  144. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md +46 -0
  145. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
  146. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -0
  147. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/rendering-svg-precision.md +28 -0
  148. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/rendering-usetransition-loading.md +75 -0
  149. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/rerender-defer-reads.md +39 -0
  150. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/rerender-dependencies.md +45 -0
  151. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
  152. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/rerender-derived-state.md +29 -0
  153. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md +74 -0
  154. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md +58 -0
  155. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/rerender-memo-with-default-value.md +38 -0
  156. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/rerender-memo.md +44 -0
  157. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
  158. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
  159. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/rerender-transitions.md +40 -0
  160. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
  161. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/server-after-nonblocking.md +73 -0
  162. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/server-auth-actions.md +96 -0
  163. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/server-cache-lru.md +41 -0
  164. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/server-cache-react.md +76 -0
  165. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/server-dedup-props.md +65 -0
  166. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/server-hoist-static-io.md +142 -0
  167. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/server-parallel-fetching.md +83 -0
  168. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/server-serialization.md +38 -0
  169. package/dist/vendor/harness-opencode/dist/skills/web-design-guidelines/SKILL.md +39 -0
  170. package/dist/vendor/harness-opencode/package.json +11 -0
  171. package/package.json +20 -15
  172. package/LICENSE +0 -21
  173. package/dist/chunk-TU23AE2F.js +0 -69
@@ -0,0 +1,96 @@
1
+ ---
2
+ description: Self-driving PRIME run. Accepts an issue-tracker reference, a free-form task description, or a question.
3
+ ---
4
+
5
+ This invocation is in AUTOPILOT mode. You are the PRIME, running hands-off: the user invoked `/autopilot` intending to walk away. Work through the normal five-phase workflow (see `prime.md`) until the plan's `## Acceptance criteria` boxes are all checked, then print the Phase 5 handoff and stop. The user runs `/ship` manually — that's the human gate.
6
+
7
+ **Activation signal.** The literal phrase `AUTOPILOT mode` above is what the autopilot plugin scans for in the session's FIRST user message. Do not remove the phrase or the plugin will not enable nudges for this session.
8
+
9
+ **Keep going on idle.** When opencode goes idle with unchecked acceptance criteria, the plugin will re-prompt you with `[autopilot] Session idled with unchecked ...`. Treat that as a "keep going" signal, not a command to restart from scratch. Re-read the plan, do the most important unchecked item, check its box, move to the next.
10
+
11
+ **Stop conditions.**
12
+ - All `## Acceptance criteria` boxes are `[x]` → print the Phase 5 handoff message and stop. The plugin sees zero unchecked boxes and stops firing nudges.
13
+ - Max 20 iterations → the plugin sends one "stopped, something's stuck" message. If this fires, something is genuinely wrong — the user reviews manually. Do not try to pre-empt the cap by cutting corners.
14
+ - User types anything → iteration counter resets; treat the user's message as a correction or halt instruction.
15
+ - Plan is classified as umbrella / measurement-gated / opted-out → plugin stops nudging silently for this session (see "Plan shape contract" below).
16
+ - Current branch doesn't contain the Linear ID cited in the plan's `## Goal` → plugin stops nudging (branch mismatch — work belongs on another branch).
17
+ - The current branch has a merged PR → plugin stops nudging (work is shipped).
18
+ - File `.agent/autopilot-disable` exists in the worktree → plugin stops nudging (kill switch). Create this file with `touch .agent/autopilot-disable` to stop autopilot from any terminal; delete it to re-enable future sessions.
19
+ - Two consecutive STOP reports from you (messages starting with `STOP:` or `STOP —`) → plugin stops nudging (you've signaled a structural block; nudging through it is counterproductive).
20
+
21
+ **No special tokens.** You do not emit `<promise>DONE</promise>`, `<autopilot>EXIT</autopilot>`, or any other sentinel. You do not delegate to `@autopilot-verifier`. Completion is visible: the plan's boxes are all `[x]` on disk. That's the contract.
22
+
23
+ **Plan shape contract.** The autopilot plugin only nudges on **unit plans** — single-goal, single-branch, file-level acceptance criteria. The plugin classifies the plan before nudging and silently stops on:
24
+ - **Umbrella plans.** Tracks multiple Linear issues (3+ distinct ticket IDs), has `## Chunks` / `## Milestones` / `## Workstreams` sections, or exceeds ~500 lines.
25
+ - **Measurement-gated plans.** An AC that requires a production window, post-deploy measurement, SLO check, or bake time. Phrases like `7-day`, `post-deploy`, `SLO`, `success rate reaches`, `bake time` anywhere in `## Acceptance criteria` trigger this.
26
+ - **Opt-out plans.** The plan contains a magic comment `<!-- autopilot: skip -->` anywhere in the file. Author-controlled override.
27
+
28
+ If you encounter one of these shapes, do NOT try to work against it directly. Write a proper unit plan for the next actionable chunk (single branch, tickable ACs) and proceed against that plan.
29
+
30
+ **Non-actionable acceptance criteria.** If an AC you planned cannot be completed in-session — blocked on an external event, requires prod measurement, belongs on a different branch — mark it:
31
+ - `- [~]` for in-progress / measurement-pending
32
+ - `- [-]` for blocked / conditional / deferred
33
+
34
+ Do NOT leave these as `- [ ]`. The plugin counts `- [ ]` as "not started, keep nudging"; `- [~]` and `- [-]` are ignored. Mis-marking wedges the loop.
35
+
36
+ The user wants autopilot to process: $ARGUMENTS
37
+
38
+ ## 0. Workflow-mechanics: decide before anything else
39
+
40
+ Before classifying the argument, apply the workflow-mechanics heuristic from `prime.md` § `# Workflow-mechanics decisions`. Autopilot is lights-out: the rule fires automatically and silently (single line of chat, no `question` tool). Never ask the user whether to open a fresh worktree, switch branches, or stack on current — the heuristic decides.
41
+
42
+ Abort paths (dirty tree on default branch; dirty tree on feature branch with unrelated work) mean STOP and report the one-sentence reason. The user resolves and re-runs.
43
+
44
+ If you auto-invoke `/fresh`, do NOT pass `--clean`. Cleanup stays user-triggered.
45
+
46
+ ## 1. Classify the argument
47
+
48
+ Pick ONE of these paths:
49
+
50
+ - **Issue-tracker reference** (single issue) — match any of:
51
+ - `<PROJECT>-<NUMBER>` where PROJECT is 2–10 uppercase letters (e.g. `ENG-1234`, `GEN-1114`) — Linear, Jira, YouTrack, Shortcut, etc.
52
+ - `#<NUMBER>` alone (e.g. `#1234`) — GitHub shorthand
53
+ - A URL to a recognized tracker (`github.com/.../issues/123`, `linear.app/.../issue/...`, `*.atlassian.net/browse/...`)
54
+ - **Free-form task description** — any natural-language request that isn't a recognized issue ref
55
+ - **Question** — starts with what/why/how/when/where/which/who, or ends with `?`
56
+
57
+ ## 2. Fetch issue content (only if step 1 returned an issue ref)
58
+
59
+ Probe in order, stop at the first that returns real content:
60
+
61
+ 1. **Linear MCP** — if configured and the arg matches `<PROJECT>-<NUMBER>` shape OR is a `linear.app` URL: `linear_get_issue`.
62
+ 2. **GitHub MCP** — if configured OR the arg is a `github.com/.../issues/...` URL OR is `#<NUMBER>` and `gh` CLI is available.
63
+ 3. **Jira / Atlassian MCP** — if configured and the arg matches `<PROJECT>-<NUMBER>` OR is an `*.atlassian.net` URL.
64
+
65
+ If no probe resolves, report once: *"I see a ref that looks like a ticket (`<arg>`), but no issue-tracker MCP is configured. Treating as free-form — paste the issue body if you want me to ground in it."* Then proceed as free-form.
66
+
67
+ Treat the fetched issue's title + description + acceptance criteria as the intent baseline. Map to the plan's `## Acceptance criteria` 1:1, in order. Do not invent entries.
68
+
69
+ ## 3. Run the PRIME arc
70
+
71
+ Run the normal five-phase workflow from `prime.md`. Key adaptations for autopilot mode:
72
+
73
+ - **Phase 1 (Intent).** Already classified; skip redundant classification.
74
+ - **Phase 1.5 (Frame).** Announce the frame as `→ Frame:` and proceed — do NOT use the `question` tool to confirm. The user is walked away.
75
+ - **Phase 2 (Plan).** Delegate to `@plan`. For ref-originated requests, cite the issue ID in the plan's `## Goal`. The plan's `## Acceptance criteria` maps 1:1 to the ticket's Changes / Definition of Done list.
76
+ - **Phase 3 (Execute).** Delegate to `@build`. `@build` executes file-by-file and returns a summary; PRIME relays progress. Acceptance boxes get checked during `@build`'s execution.
77
+ - **Phase 4 (Verify).** Full suite pass + `@qa-reviewer` → iterate to `[PASS]`. No sentinel tokens.
78
+ - **Phase 5 (Handoff).** Print "Done. Run `/ship <plan-path>` when ready." and stop.
79
+
80
+ ## 4. Guardrails
81
+
82
+ - **Never ask scoping questions.** The issue's acceptance list IS the authoritative scope. If you're tempted to ask whether to include X, the answer is: if the ticket didn't ask for it, don't include it. The `question` tool is forbidden in autopilot mode except for one narrow case: an architectural fork that blocks all progress AFTER codebase inspection, `@gap-analyzer` consultation, and precedent search (`git log`) have ALL failed to determine a default.
83
+ - **Precedent defaults.** For helper-file location, naming, logging verbosity, error-wrapper style: search `git log` for a recent similar PR and mirror its structure. Cite the precedent commit in `## Constraints`.
84
+ - **Plan-revision budget.** After `@plan-reviewer` returns `[REJECT]`: 1st REJECT → fix listed issues, resubmit. 2nd REJECT → narrow scope (move disputed items to `## Out of scope`). 3rd REJECT → escalate to `@architecture-advisor`.
85
+ - **Never commit, push, or open a PR.** That's the human gate via `/ship`.
86
+ - **Never invoke `/ship` yourself.** Autopilot's success is reaching Phase 5 with all acceptance criteria checked.
87
+ - **Circular failure.** If the same test fails after the same fix twice, delegate to `@architecture-advisor` before a third attempt.
88
+ - **STOP when stuck, don't churn.** If the plan is structurally wrong for this session (wrong branch, un-tickable AC, missing upstream work), emit a single line starting with `STOP:` followed by the specific reason. Do not re-attempt. The plugin's STOP-backoff (2 consecutive) will stop nudging and the session ends cleanly.
89
+
90
+ ## 5. Reporting
91
+
92
+ Your single handoff message should include:
93
+ - What was classified — the resolved tracker reference or free-form summary
94
+ - Plan path if created
95
+ - 1-2 sentence summary of changes
96
+ - Exact command to ship: `/ship <plan-path>` (the absolute path the plan agent returned)
@@ -0,0 +1,94 @@
1
+ ---
2
+ description: Show running LLM cost totals accrued by the cost-tracker plugin. Reads ~/.glorious/opencode/costs.json (or $GLORIOUS_COST_TRACKER_DIR/costs.json) and prints a human-readable breakdown by provider and model. Pass `--json` to dump the raw rollup; pass `--log` to tail the event log. No arguments shows the sorted pretty-print.
3
+ ---
4
+
5
+ User input: $ARGUMENTS
6
+
7
+ You are a read-only reporter for the cost-tracker plugin. Your job: run a short node one-liner to read the rollup file and print results. Do NOT guess, do NOT invent numbers, do NOT modify any files.
8
+
9
+ ## What to do
10
+
11
+ Parse the user's input for flags. Behavior:
12
+
13
+ - **No args** (default) → pretty-print the rollup.
14
+ - **`--json`** → dump the raw `costs.json` content verbatim.
15
+ - **`--log`** or **`--tail`** → show the last 20 lines of `costs.jsonl`.
16
+
17
+ ## Resolving the data directory
18
+
19
+ The rollup lives at `${GLORIOUS_COST_TRACKER_DIR:-~/.glorious/opencode}/costs.json` (tilde-expand `~` via `$HOME`). Check `$GLORIOUS_COST_TRACKER_DIR` first; fall back to `$HOME/.glorious/opencode`.
20
+
21
+ ## Pretty-print (default)
22
+
23
+ Run this node one-liner (node is always available under OpenCode/Claude Code). Use the `bash` tool:
24
+
25
+ ```bash
26
+ node -e '
27
+ const fs=require("fs"),path=require("path"),os=require("os");
28
+ const overrideDir=process.env.GLORIOUS_COST_TRACKER_DIR;
29
+ let dir;
30
+ if(overrideDir){dir=overrideDir.startsWith("~")?path.join(os.homedir(),overrideDir.slice(1)):overrideDir;}
31
+ else{dir=path.join(os.homedir(),".glorious","opencode");}
32
+ const p=path.join(dir,"costs.json");
33
+ let r;
34
+ try{r=JSON.parse(fs.readFileSync(p,"utf8"));}
35
+ catch(e){
36
+ if(e.code==="ENOENT"){console.log("No cost data yet at "+p+". Start a session with the cost-tracker plugin enabled and come back.");process.exit(0);}
37
+ console.error("Failed to read "+p+": "+e.message);process.exit(1);
38
+ }
39
+ const fmt=n=>(n==null?"0":Number(n).toFixed(n>=1?2:6));
40
+ const fmtTok=t=>{if(!t)return"0";const parts=[];if(t.input)parts.push("in "+t.input);if(t.output)parts.push("out "+t.output);if(t.reasoning)parts.push("reason "+t.reasoning);if(t.cache&&(t.cache.read||t.cache.write)){if(t.cache.read)parts.push("cache-r "+t.cache.read);if(t.cache.write)parts.push("cache-w "+t.cache.write);}return parts.join(", ")||"0";};
41
+ console.log("");
42
+ console.log(" Total: $"+fmt(r.grandTotal.cost)+" ("+(r.grandTotal.messages||0)+" messages, "+fmtTok(r.grandTotal.tokens)+")");
43
+ console.log(" Updated: "+r.updatedAt);
44
+ console.log("");
45
+ const provs=Object.entries(r.byProvider||{}).sort((a,b)=>(b[1].cost||0)-(a[1].cost||0));
46
+ for(const[provID,prov]of provs){
47
+ console.log(" "+provID+" $"+fmt(prov.cost)+" ("+(prov.messages||0)+" msgs)");
48
+ const models=Object.entries(prov.byModel||{}).sort((a,b)=>(b[1].cost||0)-(a[1].cost||0));
49
+ for(const[modID,mod]of models){
50
+ console.log(" "+modID+" $"+fmt(mod.cost)+" ("+(mod.messages||0)+" msgs, "+fmtTok(mod.tokens)+")");
51
+ }
52
+ }
53
+ console.log("");
54
+ console.log(" Source: "+p);
55
+ '
56
+ ```
57
+
58
+ ## `--json` branch
59
+
60
+ Just `cat` the rollup, or use a tiny node wrapper to handle the dir resolution:
61
+
62
+ ```bash
63
+ node -e '
64
+ const fs=require("fs"),path=require("path"),os=require("os");
65
+ const overrideDir=process.env.GLORIOUS_COST_TRACKER_DIR;
66
+ const dir=overrideDir?(overrideDir.startsWith("~")?path.join(os.homedir(),overrideDir.slice(1)):overrideDir):path.join(os.homedir(),".glorious","opencode");
67
+ const p=path.join(dir,"costs.json");
68
+ try{process.stdout.write(fs.readFileSync(p,"utf8"));}
69
+ catch(e){if(e.code==="ENOENT"){console.log("{}");process.exit(0);}console.error(e.message);process.exit(1);}
70
+ '
71
+ ```
72
+
73
+ ## `--log` / `--tail` branch
74
+
75
+ Show the last 20 lines of `costs.jsonl`:
76
+
77
+ ```bash
78
+ node -e '
79
+ const fs=require("fs"),path=require("path"),os=require("os");
80
+ const overrideDir=process.env.GLORIOUS_COST_TRACKER_DIR;
81
+ const dir=overrideDir?(overrideDir.startsWith("~")?path.join(os.homedir(),overrideDir.slice(1)):overrideDir):path.join(os.homedir(),".glorious","opencode");
82
+ const p=path.join(dir,"costs.jsonl");
83
+ try{const lines=fs.readFileSync(p,"utf8").split(/\n/).filter(Boolean);for(const l of lines.slice(-20))console.log(l);}
84
+ catch(e){if(e.code==="ENOENT"){console.log("No event log yet at "+p+".");process.exit(0);}console.error(e.message);process.exit(1);}
85
+ '
86
+ ```
87
+
88
+ ## Ad-hoc queries
89
+
90
+ The user may ask follow-up questions like "how much did I spend on Claude Opus yesterday?" or "total cost this week". For those, read `${dir}/costs.jsonl` directly with the Read tool (or cat it), parse the lines in memory, and answer from the data. Each jsonl line contains `ts` (ISO timestamp), `sessionID`, `messageID`, `providerID`, `modelID`, `costDelta`, `costTotal`, `finalized`. Only lines with `finalized: true` represent settled message costs — use `costTotal` on finalized lines to avoid double-counting deltas.
91
+
92
+ ## Output
93
+
94
+ Print the node output verbatim. Do NOT add commentary unless the user asked a specific question. Keep it tight.
@@ -0,0 +1,382 @@
1
+ ---
2
+ description: Re-key the current worktree to a new task. Runs the repo's .glorious/hooks/fresh-reset if present+executable; otherwise discards local changes, fetches latest origin, and creates a new branch from it. Then continues inline into the PRIME on the new task. Assumes long-running worktree model — one terminal tab, one persistent worktree, many tasks over its lifetime.
3
+ ---
4
+
5
+ User input: $ARGUMENTS
6
+
7
+ ## STOP — read this first, before anything else
8
+
9
+ **You do NOT ask the user to confirm discarding the working tree. Ever. Unless the user's input above literally contains the flag `--confirm`, you wipe silently.**
10
+
11
+ Running `/fresh` IS the intent to discard. The user typed `/fresh` because they want a clean workspace. A confirmation prompt at this stage is not safety — it is friction that defeats the entire point of the command. If you are about to invoke the `question` tool to ask any variant of "proceed with discarding changes?" — **STOP.** Re-read this paragraph. The answer is already "yes," because the user already said it by running `/fresh`.
12
+
13
+ The ONLY permissible uses of the `question` tool inside `/fresh`:
14
+
15
+ 1. The user's input contains the literal flag `--confirm` AND the working tree is dirty → ask the §3 discard confirmation.
16
+ 2. The user's input has no free-text ref AND does not contain `--yes` → ask "what's this tab re-keying to?"
17
+
18
+ Those are the only two cases. **Not** "but there's an untracked file," **not** "but the file isn't gitignored," **not** "but `.opencode/package-lock.json` looks important." The user knows what's in their worktree; they typed `/fresh` anyway. Recovery is already baked in — unpushed commits stay reachable via `git reflog` and the old branch ref.
19
+
20
+ Before every `question` tool invocation in this command, verify it matches case 1 or case 2 above. If it doesn't, do not call the tool. Just proceed.
21
+
22
+ ---
23
+
24
+ You are re-keying an existing, long-running git worktree to a new unit of work. The worktree itself is not created or destroyed — it's a persistent shell tab owned by the user. Your job is to parse the request, dispatch to the repo's reset strategy (either a committed hook or the built-in default), print a compact summary, and then continue inline into the PRIME on the new task — all **scoped to this worktree only**. Other worktrees and their running processes must be untouched.
25
+
26
+ ## Mental model (read this first)
27
+
28
+ The user keeps 7–10 terminal tabs open, each permanently cd'd into a separate git worktree (typically under `~/.glorious/worktrees/<repo>/<name>`). Tabs are long-lived — the same tab hosts many tasks over weeks. `/fresh` is how a tab transitions from one task to the next without closing the session, spawning a new worktree, or touching any other tab's state.
29
+
30
+ What `/fresh` does NOT do:
31
+
32
+ - It does NOT create a new worktree directory.
33
+ - It does NOT run `glrs wt new` or `git worktree add`.
34
+ - It does NOT ask the user to `cd` anywhere — they're already where they need to be.
35
+ - It does NOT touch any other worktree's files, processes, or containers.
36
+
37
+ What `/fresh` DOES do, in order:
38
+
39
+ 1. **Prereq checks** — verify cwd is inside a worktree (not the main checkout).
40
+ 2. **Parse the user's input** — extract flags and free text.
41
+ 3. **Derive the new branch name** — from Linear/GitHub reference or free-text slug, with collision retry.
42
+ 4. **Working-tree safety check** — wipe without prompting in the interactive default; opt into confirmation via `--confirm`; hard-stop in `--yes` mode if the tree has tracked or non-gitignored untracked changes.
43
+ 5. **Capture state** — `OLD_BRANCH`, unpushed commits.
44
+ 6. **Dispatch to the reset strategy** — hook present+executable → hook; otherwise (or `--skip-hook`) → built-in flow.
45
+ 7. **Print a compact summary** — **Do NOT tell the user to `cd` — they're already there.**
46
+ 8. **Start the PRIME on the new task immediately** — in the SAME turn, begin the PRIME arc (Phase 0 → Phase 1 → …) on the user's original request. Do NOT stop after the summary and wait for the user to type "work on it." `/fresh` is "re-key and go," not "re-key and wait."
47
+
48
+ ## Architectural principle: who owns what
49
+
50
+ - **`/fresh` owns the protocol:** argument parsing, safety gates (dirty-tree checks, `--yes` abort semantics, `--no-discard`), `OLD_BRANCH` capture, summary printing, PRIME kickoff. These are invariants that must be consistent across every repo that uses the harness.
51
+
52
+ - **The reset strategy owns the reset:** discarding working tree, switching branches, cleaning up repo-specific processes/containers, resetting env files. This is project-specific. The built-in flow is the default strategy (sensible for the long-running-worktree model); projects can ship their own at `.glorious/hooks/fresh-reset` if they want different semantics (e.g., "brand new worktree per task," "nuke containers only," "no-op on a bare repo").
53
+
54
+ **The two paths are mutually exclusive.** Either the hook runs, or the built-in flow runs. Never both. Hooks that want "the built-in thing plus some extras" must either (a) explicitly replicate the built-in logic inline (see §5a for the exact commands to copy), or (b) leave the hook absent and rely on the user running their extras manually after `/fresh`.
55
+
56
+ ## 0. Prereqs
57
+
58
+ - Run `git rev-parse --is-inside-work-tree` — must print `true`. Abort cleanly if not.
59
+ - Run `git rev-parse --show-toplevel` — capture this as `WORKTREE_DIR`.
60
+ - Run `git rev-parse --git-common-dir` and compare with `git rev-parse --git-dir`. If they match, this is the main checkout, NOT a worktree. Abort with: `/fresh is for long-running worktrees, not the main checkout. Create one first (e.g. `glrs wt new` or `git worktree add`), or cd into an existing worktree tab.`
61
+ - No external worktree tool is required by this command. (Worktree creation is someone else's job; we don't need it for re-keying.)
62
+
63
+ ## 1. Parse the user's input
64
+
65
+ Same parsing rules as a typical fresh-worktree command:
66
+
67
+ - **Core flags** (consumed here):
68
+ - `--from <branch>` — base branch override (default: repo's default branch, usually `main`)
69
+ - `--skip-hook` — force the built-in flow even when `.glorious/hooks/fresh-reset` is present+executable. Escape hatch for when you want to bypass the hook (e.g., debugging a broken hook). When no hook is present, this flag is a silent no-op.
70
+ - `--no-discard` — refuse to proceed if the working tree is dirty, instead of discarding. Aborts cleanly with the dirty list. Sanity safety for paranoid users who want a hard gate.
71
+ - `--confirm` — **interactive safety gate**. Before discarding a dirty tree, prompt via the `question` tool with the "what would be lost" list. Without this flag, the default interactive behavior is **wipe without asking** — `/fresh` is the user saying "I want a fresh workspace, don't slow me down with prompts." Use `--confirm` when you're not sure whether your working tree has anything salvageable.
72
+ - `--yes` — **non-interactive mode**. Assume yes on any confirmation that would normally use the `question` tool. Autopilot and PRIME pass this when invoking `/fresh` inside a loop. Crucially, `--yes` is STRICTER than interactive default: it aborts on tracked changes or non-gitignored untracked files to protect unattended loops from silent data loss. See § Non-interactive mode below.
73
+
74
+ **Design note on the dirty-tree default:** interactive `/fresh` trusts that the human running it has already decided they want the workspace wiped — that's the whole point of running `/fresh`. We do NOT prompt by default. `--confirm` opts into the safety prompt for paranoid runs. `--yes` (autopilot) is stricter because a loop can't recover from mistaken destruction the way a human at the terminal can.
75
+ - **Free text** — first contiguous non-flag substring, used to derive the branch name.
76
+ - **Pass-through args** — forwarded to the reset hook verbatim.
77
+
78
+ If the input is empty or has no free text:
79
+
80
+ - **Interactive mode (default)**: use the `question` tool — "What's this tab re-keying to? (free text, or an issue-tracker reference like `ENG-1234`)"
81
+ - **Non-interactive mode (`--yes`)**: abort immediately with `ERROR: /fresh --yes requires a branch name or issue ref as input.` — the caller (autopilot) must always supply one.
82
+
83
+ ## 1a. Non-interactive mode (`--yes`)
84
+
85
+ Under `--yes`, every `question`-tool use in this command is replaced by a deterministic rule. Importantly, `--yes` is **stricter** than the interactive default on dirty trees — it aborts on tracked changes rather than wiping them. The interactive human at a terminal has recourse (they can `cd` elsewhere, inspect the old branch, etc.); an autopilot loop does not, so the gate lives here.
86
+
87
+ | Decision | Interactive default (no flag) | `--confirm` | `--yes` behavior |
88
+ |---|---|---|---|
89
+ | Dirty tree, only untracked/gitignored debris | **Wipe silently** | Ask to discard | **Proceed** — `git clean -fdx` is safe for gitignored/untracked build artifacts |
90
+ | Dirty tree with TRACKED changes (modified/staged/deleted) | **Wipe silently** — human explicitly ran `/fresh` | Ask to discard | **Abort** with `ERROR: /fresh --yes refuses to discard tracked changes. Commit/stash and re-run, or run /fresh without --yes.` |
91
+ | Dirty tree with untracked NON-gitignored files | **Wipe silently** — human explicitly ran `/fresh` | Ask to discard | **Abort** with the file list. Non-gitignored untracked files are almost always intentional. |
92
+ | Unpushed commits on current branch | Proceed silently | Proceed silently | Proceed silently |
93
+ | Input empty | Ask for input | Ask for input | Abort |
94
+
95
+ The invariants:
96
+
97
+ - **Interactive default trusts the human.** The user typing `/fresh` has already decided they want a clean workspace. Prompting is friction, not safety — they can `git reflog` or `git checkout <old-branch>` if they realize they wiped something important, since unpushed commits stay reachable via the old branch ref.
98
+ - **`--yes` must never destroy work that a reasonable human would want to keep** when running unattended. Gitignored build artifacts are the only discard that's clearly safe without consent. Everything else halts the autopilot sequence so a human can inspect. The autopilot loop treats a `/fresh --yes` abort as a hard stop, not a "try next issue."
99
+ - **`--confirm` is the opt-in safety prompt** for humans who want the old ask-first behavior on a specific run.
100
+
101
+ To detect the tracked-vs-untracked split from `git status --porcelain`:
102
+ - Lines starting with ` M`, `M `, `MM`, `A `, `D `, ` D`, `R `, `C `, `U ` (or any non-`??` prefix) = tracked changes present
103
+ - Lines starting with `??` = untracked; run `git check-ignore --stdin` across them to split gitignored-debris from intentional-new-files
104
+
105
+ **Why safety gates are owned by `/fresh`, not the hook:** the `question` tool is available only to the PRIME agent; a bash hook cannot prompt. To keep `--yes` abort semantics deterministic (which autopilot relies on) and interactive-mode confirmations coherent, all dirty-tree gating runs in `/fresh` BEFORE dispatching to either path. The dispatch target (hook or built-in) always runs against a tree that either is clean, is only gitignored debris cleared for `git clean -fdx`, or has been confirmed-for-discard by the user.
106
+
107
+ ## 2. Derive the new branch name
108
+
109
+ **Issue-tracker reference path** — matches these shapes:
110
+
111
+ - `<PROJECT>-<NUMBER>` where PROJECT is 2–10 uppercase letters (e.g. `ENG-1234`, `GEN-1127`, `ICE-42`).
112
+ - `#<NUMBER>` alone (GitHub/GitLab shorthand).
113
+ - URL to a known tracker (`linear.app/.../issue/...`, `github.com/.../issues/N`, `<company>.atlassian.net/browse/...`).
114
+
115
+ For Linear-style `<PROJECT>-<NUMBER>`, if a Linear MCP is enabled, call `linear_get_issue(id)` and use `branchName` verbatim.
116
+
117
+ For GitHub `#<NUMBER>` or issue URL, if `gh` is available: `gh issue view <N> --json title --jq .title`, then slug like free text with prefix `issue-<N>-`.
118
+
119
+ If tracker lookup fails for any reason, fall through to the free-text path. Never abort for a lookup failure.
120
+
121
+ **Free-text path** — slug + verb-prefix inference:
122
+
123
+ 1. Lowercase; replace non-alphanumeric runs with `-`; collapse repeats; strip leading/trailing `-`.
124
+ 2. Verb prefix from the first whitespace-separated word:
125
+ - `fix|bug|hotfix|patch` → `fix/`, strip verb. (`fix auth bug` → `fix/auth-bug`)
126
+ - `add|feat|feature|implement|create` → `feat/`, strip verb.
127
+ - `refactor|cleanup|rename|reorganize` → `refactor/`, strip verb.
128
+ - `doc|docs|document` → `docs/`, strip verb.
129
+ - Otherwise → `chore/` (or the dominant prefix from recent local branches if cheaply discoverable via `git branch --sort=-committerdate | head -5`).
130
+ 3. Truncate to 50 chars total; on mid-word truncation, chop to last full word.
131
+
132
+ **Name collision check**: run `git rev-parse --verify <new-branch-name>` against both local and `refs/remotes/origin/<new-branch-name>`. On collision:
133
+
134
+ - Retry with `-$(date +%y%m%d)` suffix.
135
+ - If that also collides, append `-${EPOCHSECONDS}`. Never fails by now.
136
+
137
+ Capture old branch name via `git branch --show-current` BEFORE any state changes — it's part of the summary.
138
+
139
+ The derived name is the **suggested** `NEW_BRANCH` passed to the hook (if one runs). A hook is free to override it — `/fresh` reads `git branch --show-current` post-dispatch to determine the actual post-reset branch and uses that in the summary.
140
+
141
+ ## 3. Working-tree safety check (critical)
142
+
143
+ Run these and assemble a "what would be lost" picture:
144
+
145
+ ```bash
146
+ DIRTY_FILES=$(git status --porcelain)
147
+ UNPUSHED_COMMITS=$(git log "@{upstream}..HEAD" --oneline 2>/dev/null || git log HEAD --oneline | head -20)
148
+ STALE_STASHES=$(git stash list | head -5)
149
+ ```
150
+
151
+ **Decision matrix:**
152
+
153
+ | Condition | Interactive default | `--confirm` | `--yes` mode |
154
+ |---|---|---|---|
155
+ | Clean tree, tracked upstream | Proceed silently | Proceed silently | Proceed silently |
156
+ | Dirty tree: only gitignored/untracked debris | **Proceed silently** — wipe it | Confirm discard (see below) | **Proceed** — the dispatch target is expected to clean it, or the built-in will |
157
+ | Dirty tree: tracked changes (modified/staged/deleted) | **Proceed silently** — wipe it; show summary of what was discarded | Confirm discard (see below) | **Abort** with tracked-file list |
158
+ | Dirty tree: untracked non-gitignored files | **Proceed silently** — wipe it; show summary of what was discarded | Confirm discard (see below) | **Abort** with file list |
159
+ | Dirty tree and `--no-discard` passed (any mode) | Abort with the dirty list | Abort with the dirty list | Abort with the dirty list |
160
+ | Unpushed commits exist | **Proceed without asking** — old branch ref preserves them; summary mentions `Previous branch <old> kept N unpushed commits — recover with git checkout <old>` | Same | Same |
161
+
162
+ **Summary of what was discarded:** in the interactive default path (wipe without prompting), the final summary (§7) reports `Discarded: <N> files` with a short list (up to 10, truncated) so the user can see what went. This is the visible trace that replaces the pre-wipe prompt — you lose the prompt, you gain a visible post-hoc receipt.
163
+
164
+ **Destructive-discard confirmation — DO NOT USE unless the user's input contains the literal flag `--confirm`:**
165
+
166
+ > If you're reading this section without `--confirm` in the user's input, **skip it entirely**. You wipe silently. The prompt below is ONLY for the `--confirm` opt-in. An untracked file, a non-gitignored file, a file that "looks important" — none of those change this. `/fresh` without `--confirm` = wipe without asking.
167
+
168
+ Use the `question` tool with these exact contents (only reachable when `--confirm` was passed):
169
+
170
+ - Question: `Worktree is dirty. /fresh will hard-discard ALL uncommitted changes in this worktree. Proceed?`
171
+ - Header: `Discard uncommitted changes?`
172
+ - Options:
173
+ - `Yes, discard everything` — proceeds to step 4 (dispatch)
174
+ - `No, abort /fresh` — exits the command cleanly, zero changes made
175
+ - `Show what would be lost first` — print `git status --short` output plus `git diff --stat HEAD`, then re-ask (recursive, but OK — the question tool handles this)
176
+
177
+ ## 4. Dispatch: hook-present vs hook-absent
178
+
179
+ This is the branch point where the reset strategy is chosen. `/fresh` does NOT run any git state-changing commands itself in this section — it only decides which path runs.
180
+
181
+ **Hook discovery:**
182
+
183
+ ```bash
184
+ HOOK_PATH="$WORKTREE_DIR/.glorious/hooks/fresh-reset"
185
+ ```
186
+
187
+ Three discovery outcomes:
188
+
189
+ | Condition | Outcome |
190
+ |---|---|
191
+ | `-f "$HOOK_PATH"` false | **No hook.** Run the built-in flow (§5a). Silent — generic repos don't need a hook. |
192
+ | `-f "$HOOK_PATH"` true AND `-x "$HOOK_PATH"` false | **Hook disabled.** Emit a WARN in the summary (`hook (skipped — not executable, ran built-in instead — WARNING)`), then run the built-in flow. This preserves `chmod -x` as a deliberate kill-switch but makes the skip visible so users don't silently lose their hook. |
193
+ | `-f "$HOOK_PATH"` true AND `-x "$HOOK_PATH"` true | **Hook present and enabled.** If `--skip-hook` was passed: log `hook (skipped via --skip-hook)` and run the built-in flow (§5a). Otherwise: dispatch to the hook (§5b). |
194
+
195
+ ### 5a. Built-in reset (hook absent, non-executable, or --skip-hook)
196
+
197
+ The default reset strategy. This is the long-running-worktree flow: discard any remaining dirt (the § 3 confirmation has already authorized this in interactive mode), fetch the latest base branch, and check out a new branch from it.
198
+
199
+ ```bash
200
+ # Discard any confirmed-for-discard dirty state. In the clean-tree case these are no-ops.
201
+ git reset --hard HEAD
202
+ git clean -fdx
203
+ ```
204
+
205
+ Note the `-x` on `clean`: removes files matched by `.gitignore` too (`.env`, `dist/`, `node_modules/.cache/`, leftover build artifacts). This is deliberate for the long-running-worktree model — a fresh task should get a pristine working tree. Projects that need per-task `.env` regeneration or dep installation should ship a hook (§5b) that does both the reset and the post-reset setup.
206
+
207
+ ```bash
208
+ # Default branch name — from repo convention
209
+ DEFAULT_BRANCH=$(git symbolic-ref --short refs/remotes/origin/HEAD 2>/dev/null | sed 's|^origin/||')
210
+ DEFAULT_BRANCH="${DEFAULT_BRANCH:-main}"
211
+
212
+ # --from flag overrides
213
+ BASE_BRANCH="${FROM_FLAG:-$DEFAULT_BRANCH}"
214
+
215
+ # Fetch only the branch we need (fast, avoids pulling every remote ref)
216
+ git fetch origin "$BASE_BRANCH" --prune
217
+
218
+ # Create the new branch from the freshly-fetched remote tip
219
+ git checkout -b "$NEW_BRANCH_NAME" "origin/$BASE_BRANCH"
220
+ ```
221
+
222
+ On `git fetch` failure (network, auth, etc.): print the error, then **fall back to the local tip of `$BASE_BRANCH`** with a warning. Do NOT abort — network blips are common and the user may be offline.
223
+
224
+ On `git checkout -b` failure (collision after §2's retry logic failed): this shouldn't happen given the earlier safeguards. If it does: abort with the error. Working tree is already clean, so the user is in a recoverable state.
225
+
226
+ `RESET_STATUS` for the summary is one of: `built-in (clean)` if the pre-dispatch tree was clean, `built-in (discarded N files)` if dirt was cleared.
227
+
228
+ ### 5b. Hook reset (hook present + executable, no --skip-hook)
229
+
230
+ The project-specific reset strategy. The hook owns the entire reset: working-tree clean, branch switch, process/container cleanup, env regeneration, dep re-install — whatever the project needs.
231
+
232
+ **Environment variables passed in:**
233
+
234
+ - `WORKTREE_DIR` — absolute path of the current worktree (captured in §0)
235
+ - `WORKTREE_NAME` — basename of `WORKTREE_DIR` (useful for scoping things like `docker-compose -p <name>`)
236
+ - `OLD_BRANCH` — the branch name before /fresh ran (captured in §2)
237
+ - `NEW_BRANCH` — the **suggested** new branch name (derived in §2). The hook MAY override by checking out a different branch; `/fresh` reads `git branch --show-current` post-hook to discover the actual result.
238
+ - `BASE_BRANCH` — the base branch the new branch is intended to derive from (from §1 `--from` flag or repo default). Informational; hook may pick a different base.
239
+ - `FRESH_PASSTHROUGH_ARGS` — pass-through args joined with spaces (informational only, not parse-safe)
240
+
241
+ **Positional args:** the pass-through args from the command input, verbatim, so the hook can use `getopt` / `case` / etc.
242
+
243
+ **Invocation** — execute the hook directly so its shebang is respected (the hook author chose zsh, python, node, or anything else):
244
+
245
+ ```bash
246
+ "$HOOK_PATH" "${PASSTHROUGH_ARGS[@]}"
247
+ ```
248
+
249
+ (Do NOT force `bash "$HOOK_PATH"` — that breaks non-bash hooks.)
250
+
251
+ **Exit semantics:**
252
+
253
+ - Exit 0 → success, continue to §6. `RESET_STATUS` = `hook (exit 0)`.
254
+ - Exit non-zero → **warn, do not abort.** Still proceed to §6 so the summary prints with a prominent failure banner and `RESET_STATUS` = `hook (exit <code> — WARNING)`. Rationale: the hook may have done 80% of its work before failing; the summary makes the failure visible, and the human is the right gate for deciding whether to recover or abandon.
255
+
256
+ **Convention for hook output:**
257
+
258
+ Hooks MAY write a JSON summary to stdout's last line (e.g., `{"postgresPort": 5442, "projectName": "wt-abc123"}`). Parse if valid JSON and include in the final summary. This is **enrichment-only** — the JSON tail does NOT change `/fresh` control flow or override the post-hook `git branch --show-current` reading. There are no reserved keys.
259
+
260
+ **Post-hook state capture** — ALWAYS run after the hook exits, regardless of exit code:
261
+
262
+ ```bash
263
+ ACTUAL_BRANCH=$(git branch --show-current)
264
+ ```
265
+
266
+ `ACTUAL_BRANCH` is what goes into the summary's `New:` field. If `ACTUAL_BRANCH != NEW_BRANCH` (the hook overrode the suggestion), the summary surfaces both.
267
+
268
+ ## 6. Summary (print to stderr for the human)
269
+
270
+ Assemble a compact summary. This is what the human sees.
271
+
272
+ ```
273
+ ✓ Worktree re-keyed
274
+ Directory: <WORKTREE_DIR>
275
+ Previous: <OLD_BRANCH> → New: <ACTUAL_BRANCH>
276
+ Base: <BASE_BRANCH> (requested)
277
+ Discarded: <"N files" if the tree was dirty, else "(clean)">
278
+ Unpushed: <"N commits preserved on <OLD_BRANCH>" if applicable, else "(none)">
279
+ Reset: <RESET_STATUS string>
280
+
281
+ <if ACTUAL_BRANCH != NEW_BRANCH:>
282
+ Note: reset strategy switched to a different branch than requested (requested: <NEW_BRANCH>).
283
+
284
+ <if RESET_STATUS contains "WARNING":>
285
+ ⚠️ Reset did not complete cleanly — check `git status` before resuming.
286
+
287
+ <if hook emitted a JSON summary, print each key-value one per line>
288
+ <if there are unpushed commits on the old branch:>
289
+ Recover previous work: git checkout <OLD_BRANCH>
290
+ ```
291
+
292
+ **Do NOT print `cd <path>` or "start a new session" or any other "do this next" command.** The user is already in the tab where the work happens. The session continues in place — and immediately continues into §7 (PRIME kickoff) in the same turn.
293
+
294
+ ## 7. Kick off the PRIME on the new task (in the SAME turn)
295
+
296
+ This is the piece that makes `/fresh` feel like "re-key and go" instead of "re-key and wait." After printing the summary, DO NOT stop and wait for a follow-up message. Continue in the same turn:
297
+
298
+ 1. **Treat the user's original input (plus any tracker context you resolved in §2) as the new PRIME input** — same as if the user had just typed that request as a fresh prompt.
299
+ 2. **Enter the PRIME arc from the top** — Phase 0 bootstrap probe, then Phase 1 intent classification, then Phase 1.5 framing (substantial requests only), etc.
300
+ 3. **Do not re-prompt for confirmation of the task itself.** The user's request is already in hand. In `--confirm` mode you've already gated on discard; in default mode you haven't, but that's fine — the PRIME's own safety gates (e.g., the Phase 1.5 framing confirmation for low-confidence substantial requests) are the right place for task-level clarifiers, not a `/fresh` meta-prompt.
301
+
302
+ **Why in the same turn:** the user ran `/fresh <task>` expecting work to start, not a checkpoint. One command, one turn, one uninterrupted transition from old task to new.
303
+
304
+ **Interaction with `--yes` (autopilot sequence mode):** same behavior. `/fresh --yes <ref>` re-keys and continues inline into the PRIME arc on the new ref. `/autopilot`'s sequence loop drives the iteration — `/fresh` hands off to the PRIME in the same turn, the PRIME runs plan → build → verify → STOP, and the outer `/autopilot` loop pops the next ref.
305
+
306
+ **Exception — abort paths:** if `/fresh` aborts in §0 (not in a worktree), §1 (empty input), §3 (`--yes` + dirty tracked), or §3 (`--no-discard` + dirty), DO NOT enter §7. The whole point of an abort is that no work should start. Print the abort message and stop.
307
+
308
+ **Exception — reset-strategy failure with WARNING status:** if the reset hook exited non-zero, the summary prints the warning banner. Still enter §7, but make sure the user sees the banner before work begins — a WARNING status means the worktree state may be inconsistent with the requested task.
309
+
310
+ ## Failure-mode reference
311
+
312
+ | Step | Failure / condition | Interactive default | `--confirm` | `--yes` |
313
+ |---|---|---|---|---|
314
+ | 0 (env check) | Not inside a worktree | Abort with guidance to create one first | Same | Same |
315
+ | 0 (env check) | Inside main checkout, not a worktree | Abort — `/fresh` is for worktrees only | Same | Same |
316
+ | 1 (parsing) | Empty input | Ask via `question` tool | Ask via `question` tool | **Abort** with `ERROR: /fresh --yes requires a ref/description.` |
317
+ | 2 (tracker lookup) | MCP/gh unavailable, issue not found | Fall back to free-text slug | Same | Same |
318
+ | 2 (name collision) | New branch name conflicts | Retry with `-YYMMDD`, then `-$EPOCHSECONDS` | Same | Same |
319
+ | 3 (dirty tree with tracked changes) | Working tree has modified/staged/deleted files | **Wipe silently**, surface discarded-file summary in §6 | Ask to discard | **Abort** with file list |
320
+ | 3 (dirty tree with untracked non-gitignored files) | New files not in `.gitignore` | **Wipe silently**, surface discarded-file summary in §6 | Ask to discard | **Abort** with file list |
321
+ | 3 (dirty tree, only gitignored debris) | Safe to clean | **Wipe silently** | Ask to discard | **Proceed** silently |
322
+ | 4 (dispatch) | Hook file present but non-executable | WARN, fall back to built-in (§5a) | Same | Same |
323
+ | 4 (dispatch) | `--skip-hook` with hook present | Log, fall back to built-in (§5a) | Same | Same |
324
+ | 5a (built-in fetch) | Network/auth failure | Fall back to local tip of base, warn, continue | Same | Same |
325
+ | 5a (built-in checkout) | Name collision despite §2 safeguards | Abort — shouldn't reach here | Same | Same |
326
+ | 5b (hook) | Hook exits non-zero | WARN, continue to §6; summary shows failure banner | Same | Same |
327
+ | 5b (hook) | Hook emits malformed JSON tail | Silent — enrichment is best-effort | Same | Same |
328
+ | 5b (hook) | Hook doesn't change branch (pure-cleanup) | `ACTUAL_BRANCH == OLD_BRANCH`; summary reflects that | Same | Same |
329
+ | 5b (hook) | Hook overrides `NEW_BRANCH` | `ACTUAL_BRANCH` from `git branch --show-current` goes into summary | Same | Same |
330
+ | 7 (PRIME kickoff) | Reset produced a WARNING status | Continue to §7, but make sure the warning banner is visible to the user before work starts | Same | Same |
331
+ | 7 (PRIME kickoff) | `/fresh` aborted earlier (no worktree, empty input, --yes + dirty tracked, --no-discard + dirty) | Do NOT enter §7 — print abort message and stop | Same | Same |
332
+
333
+ ## Integration with `/autopilot` (sequence-of-issues mode)
334
+
335
+ When the user runs `/autopilot` with a project / milestone / queue reference, the autopilot command sequences through multiple issues and invokes `/fresh <ref> --yes` between each one. The contract across that boundary:
336
+
337
+ **From autopilot's side** (before calling `/fresh`):
338
+
339
+ - Autopilot pops the next ref from its queue.
340
+ - Autopilot pre-checks whether that ref already has an open or merged PR (via `gh pr list --search <ref>` or Linear MCP). If yes, skip silently, log, and pop the next ref. `/fresh` is not invoked for already-shipped work.
341
+ - Autopilot calls `/fresh <ref> --yes` only when the ref is genuinely open.
342
+
343
+ **From `/fresh`'s side** (this command):
344
+
345
+ - `--yes` suppresses every `question`-tool prompt. Autopilot cannot respond to them.
346
+ - If the working tree has tracked changes or untracked non-gitignored files, `/fresh --yes` aborts. Autopilot treats this as a **hard stop** for the sequence, not "try next issue" — dirty tracked work means something went wrong in the previous iteration that requires human attention. This safety gate is owned by `/fresh`, not the reset strategy, which is what makes `--yes` abort semantics deterministic across repos (a hook cannot override them).
347
+ - On success, `/fresh --yes` continues inline into the PRIME arc on the new ref (§7). The PRIME runs plan → build → verify → STOP. Control returns to `/autopilot`'s outer sequence loop, which pops the next ref and calls `/fresh --yes` again.
348
+
349
+ **Sequence-loop shape:**
350
+
351
+ ```
352
+ autopilot queue → autopilot pops ref → /fresh <ref> --yes → /fresh re-keys:
353
+ - discards tree (via hook or built-in)
354
+ - fetches base, checks out new branch
355
+ - prints summary
356
+ - CONTINUES INLINE into PRIME (§7):
357
+ runs Phase 0 → 1 → 1.5 → …
358
+ plan → build → verify → STOP
359
+ autopilot sees acceptance criteria all [x],
360
+ pops next ref, loops
361
+ ```
362
+
363
+ ## Hook contract, for repo authors
364
+
365
+ A repo opts into a custom `/fresh` reset strategy by committing an executable file at `.glorious/hooks/fresh-reset` (committed to the repo, so it's automatically present in every worktree). It receives:
366
+
367
+ - **Env:** `WORKTREE_DIR`, `WORKTREE_NAME`, `OLD_BRANCH`, `NEW_BRANCH` (suggested), `BASE_BRANCH` (requested), `FRESH_PASSTHROUGH_ARGS`
368
+ - **Positional args:** the pass-through args from the command input
369
+
370
+ It is responsible for: discarding the working tree appropriately (e.g., `git reset --hard HEAD && git clean -fdx`), switching to the new branch (e.g., `git fetch origin "$BASE_BRANCH" && git checkout -b "$NEW_BRANCH" "origin/$BASE_BRANCH"`), and any project-specific cleanup (stopping docker/compose projects scoped to this worktree, killing dev servers matched by `/proc/<pid>/cwd` or PID files, freeing port slots, regenerating `.env`, re-installing deps if lockfiles changed).
371
+
372
+ It MUST NOT: touch any other worktree's directory/processes/containers, modify global state, or prompt the user (the `question` tool is agent-only; hooks run non-interactively). Scope filtering by `WORKTREE_NAME` or `WORKTREE_DIR` is mandatory if the hook uses broad tooling like `docker ps` or `ps`.
373
+
374
+ It SHOULD: exit 0 on success; exit non-zero on failure. Non-zero is treated as a warning by `/fresh` (not fatal) — the summary still prints with a failure banner so the user can see it. A partially-failed hook leaves the worktree in an unknown state; the banner surfaces this visibly.
375
+
376
+ It MAY: emit a single-line JSON object on stdout's last line for summary enrichment (e.g., `{"postgresPort": 5442}`). This is enrichment-only; it does NOT alter `/fresh` control flow.
377
+
378
+ Projects that want the built-in long-running-worktree flow ARE the default; they don't need a hook. Projects that want a hook for cleanup only, with the built-in flow still running, should copy the built-in commands (§5a) into their hook and add the cleanup on top — the two paths are mutually exclusive, so "augment" is achieved by the hook duplicating the built-in steps inline.
379
+
380
+ ## One-sentence philosophy
381
+
382
+ `/fresh` is a re-key-and-go protocol with a pluggable reset strategy: it wipes the worktree without friction (the human running `/fresh` has already decided), fetches the fresh base, checks out a new branch, and continues inline into the PRIME on the new task — one command, one turn, one uninterrupted transition from old task to new. Repos can ship their own reset strategy at `.glorious/hooks/fresh-reset`; `/fresh` owns the invariants (safety gates, summary, PRIME kickoff) so those remain consistent across every repo that uses the harness.