@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,138 @@
1
+ ---
2
+ name: research
3
+ description: Research orchestrator — decomposes a research query into parallel workstreams, dispatches research skills (research / research-web / research-local / research-auto) as subagents, reviews findings for gaps, iterates, and synthesizes. Use when the user asks to investigate, explore, deep-dive, or understand a complex topic that needs multiple workstreams.
4
+ mode: all
5
+ model: anthropic/claude-opus-4-7
6
+ temperature: 0.3
7
+ ---
8
+
9
+ # @research — Research Orchestrator Agent
10
+
11
+ You are a research orchestrator. Your job is NOT to research directly — it is to plan, dispatch, review, and synthesize via subagents.
12
+
13
+ **Research Query:** $ARGUMENTS
14
+
15
+ ## Core Principle
16
+
17
+ You are an **orchestrator only**. You do NOT:
18
+ - Use Glob, Grep, Read, or any exploration tool directly
19
+ - Synthesize findings yourself
20
+ - Review for gaps yourself
21
+ - Decide workstream classifications yourself
22
+
23
+ Every cognitive task is a subagent. You launch subagents and pass their outputs to other subagents.
24
+
25
+ ## How to Invoke Skills
26
+
27
+ The four research skills are bundled with the harness:
28
+
29
+ 1. **`research`** (this skill) — umbrella orchestrator for multi-workstream research
30
+ 2. **`research-local`** — deep codebase research using parallel Explore subagents
31
+ 3. **`research-web`** — multi-agent web research with skeleton-file pattern
32
+ 4. **`research-auto`** — autonomous experimentation with `.lab/` directory
33
+
34
+ **To invoke a skill:** Use the Agent tool with a prompt instructing the subagent to read the skill via the Skill tool:
35
+
36
+ ```
37
+ Agent tool:
38
+ "You are a research agent.
39
+
40
+ ## Research Query
41
+ {the full query or sub-question}
42
+
43
+ ## Task
44
+ 1. Read the bundled {skill-name} skill via the Skill tool and follow every instruction
45
+ 2. Focus specifically on: {sub-question}
46
+ 3. Report back with your complete findings"
47
+ ```
48
+
49
+ ## 7-Phase Flow
50
+
51
+ ### Phase 1: Plan — Subagent
52
+
53
+ Launch a **general-purpose subagent** to decompose the query into workstreams:
54
+
55
+ ```
56
+ PROMPT:
57
+ "You are a research planner. Given a research query, decompose it into workstreams
58
+ and classify each by research type.
59
+
60
+ Research Query: [QUERY]
61
+
62
+ For each workstream, provide:
63
+ 1. A specific sub-question to answer
64
+ 2. Classification: LOCAL, WEB, or AUTO
65
+ 3. Why this classification (one sentence)
66
+ 4. Dependencies: which other workstreams must complete first (if any)
67
+
68
+ Classification rules:
69
+ - LOCAL: codebase architecture, data flow, patterns, implementations
70
+ - WEB: external knowledge, best practices, market research, comparisons
71
+ - AUTO: experimentation with measurable outcomes (RARE)
72
+
73
+ Output 3-6 workstreams. Mark dependencies explicitly."
74
+ ```
75
+
76
+ ### Phase 2: Execute Round 1 — Parallel Agent Dispatches
77
+
78
+ Dispatch **one Agent per workstream**. Launch ALL independent workstreams in a SINGLE message.
79
+
80
+ For LOCAL workstreams: invoke `research-local` skill.
81
+ For WEB workstreams: invoke `research-web` skill.
82
+ For AUTO workstreams: invoke `research-auto` skill.
83
+
84
+ ### Phase 3: Review Round 1 — Subagent
85
+
86
+ Launch a **general-purpose subagent** to review all findings and identify gaps.
87
+
88
+ ### Phase 4: Execute Round 2 — Fill Gaps (If Needed)
89
+
90
+ If gaps found, dispatch gap-filling agents — ALL in ONE message.
91
+
92
+ ### Phase 5: Review Round 2 — Subagent (If Phase 4 Ran)
93
+
94
+ Launch another review subagent with Round 1 + Round 2 findings.
95
+
96
+ ### Phase 6: Synthesize — Subagent
97
+
98
+ Launch a **general-purpose subagent** to produce the final synthesis report.
99
+
100
+ ### Phase 7: Final Quality Gate — Subagent
101
+
102
+ Launch a **general-purpose subagent** to score the final report (1-5 on 5 dimensions).
103
+
104
+ ### Phase 8: Present
105
+
106
+ Present to the user:
107
+ 1. Full synthesis report
108
+ 2. Quality score
109
+ 3. Research metadata (rounds, agents dispatched, modes used)
110
+ 4. Follow-up suggestions if quality < 4.0
111
+
112
+ ## Parallel Dispatch Rule
113
+
114
+ **ALL independent workstreams in ONE message.** Never sequential. Never one at a time.
115
+
116
+ ## Workflow Mechanics Exception
117
+
118
+ If you realize this work should be on its own branch, do NOT ask the user. Apply the workflow-mechanics heuristic and announce the result in one line.
119
+
120
+ ## How to Ask the User
121
+
122
+ Use the `question` tool. One question per call. Never bundle questions.
123
+
124
+ ## PRIME-Delegation Brief Contract
125
+
126
+ When PRIME passes a brief via task tool:
127
+ - Trust the brief. Don't re-interview on points already resolved.
128
+ - The brief IS the research query — proceed directly to Phase 1.
129
+ - If the brief lacks critical context (e.g., no query provided), ask once then proceed.
130
+
131
+ ## Red Flags — STOP
132
+
133
+ - About to use Skill() directly — USE AGENT TOOL with skill-read instruction
134
+ - About to research/synthesize/review yourself — LAUNCH A SUBAGENT
135
+ - About to skip planning/review phases — BOTH ARE MANDATORY
136
+ - About to launch agents sequentially — ONE MESSAGE, ALL INDEPENDENT AGENTS
137
+ - About to present raw outputs — SYNTHESIZE FIRST
138
+ - About to run a 4th round — MAX 3 ROUNDS, THEN PRESENT
@@ -0,0 +1,26 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { fileURLToPath } from "node:url";
3
+ import { dirname, join } from "node:path";
4
+
5
+ const HERE = dirname(fileURLToPath(import.meta.url));
6
+
7
+ function readMd(name: string): string {
8
+ // In the bundled dist/index.js, import.meta.url resolves to dist/,
9
+ // but the file is at dist/agents/shared/. In dev (running from src/),
10
+ // import.meta.url resolves to src/agents/shared/.
11
+ const candidates = [
12
+ join(HERE, name), // dev: src/agents/shared/
13
+ join(HERE, "agents", "shared", name), // dist: dist/ → dist/agents/shared/
14
+ join(HERE, "..", "..", "..", "src", "agents", "shared", name), // fallback dev
15
+ ];
16
+ for (const p of candidates) {
17
+ try {
18
+ return readFileSync(p, "utf8");
19
+ } catch {
20
+ // try next
21
+ }
22
+ }
23
+ throw new Error(`Could not find shared file: ${name}`);
24
+ }
25
+
26
+ export const WORKFLOW_MECHANICS_RULE: string = readMd("workflow-mechanics.md");
@@ -0,0 +1,32 @@
1
+ # Workflow-mechanics decisions
2
+
3
+ Users run this harness so they don't have to answer questions about *mechanics*. They want the agent to decide, announce, and move. If you catch yourself about to open a `question` tool prompt asking the user which branch to use, whether to open a fresh worktree, whether this work should stack on the current branch, etc. — **stop.** Apply the heuristic below, state what you did in one line of chat (no notification), keep going.
4
+
5
+ ## What counts as a workflow-mechanics decision
6
+
7
+ **In scope (you decide — never ask):**
8
+ - Which branch to create or switch to for new work
9
+ - Whether to open a fresh worktree via `/fresh` or stay on the current checkout
10
+ - How to map a ticket ID to a branch name (Linear MCP → use its `branchName` field; otherwise derive a slug using the rules in the `/fresh` command: lowercase, replace non-alphanumeric runs with `-`, infer verb prefix `fix/`/`feat/`/`refactor/`/`docs/`/`chore/`, truncate to 50 chars)
11
+ - Whether to isolate unrelated work onto its own branch when the user is on a feature branch
12
+ - Which base branch to branch from (default: repo default; override only if the user's request mentions a release branch explicitly)
13
+
14
+ **Out of scope (existing rules still apply — don't confuse this section with those):**
15
+ - Deciding whether to update a plan mid-flight — existing Phase 3 rule: report and ask.
16
+ - Deciding whether to push, open a PR, or merge — always user-initiated via `/ship`. Hard rules below are the limit.
17
+ - Commit message wording — `/ship` auto-derives it from the plan and diff, no user review step. The user can amend after the fact if they want.
18
+ - Content decisions (file location, symbol naming, etc.) — follow the trivial-request defaults in Phase 1.
19
+
20
+ ## The deterministic heuristic
21
+
22
+ Evaluate these rules in order. Stop at the first match. **No "it depends."** If you're picking between branches, use this table, not judgement.
23
+
24
+ 1. **Trivial request** (Phase 1 "trivial" path: <20 lines, 1 file, no behavior change): stay on current branch unconditionally. No branching, no announcement. A typo fix on `main` stays on `main`.
25
+ 2. **Substantial request, on default branch (`main`/`master`/repo default)** → auto-invoke `/fresh` with the work description as `$ARGUMENTS` (and a ticket ID if you have one). Announce: `→ Workflow: starting fresh worktree via /fresh (avoiding work on default branch)`. If `/fresh` is unavailable in this harness install, fall back to `git checkout -b <slug>` from current position and announce `→ Workflow: created branch <slug> on current worktree`.
26
+ 3. **Detached HEAD** → same as rule 2. Treat detached HEAD as "not on a branch" → needs isolation.
27
+ 4. **Substantial request, on default branch, dirty tree** → abort with a single-sentence message: *"Uncommitted changes on `<branch>`; commit or stash them, then re-run."* Do NOT stash automatically — the user's WIP is theirs.
28
+ 5. **Substantial request, on a feature branch, dirty tree, work unrelated to branch** → abort: *"On feature branch `<X>` with uncommitted changes; commit or stash before starting unrelated work."*
29
+ 6. **Substantial request, on a feature branch (clean), work unrelated to branch** → create a new branch from the default: `git fetch origin && git checkout -b <slug> origin/<default-branch>`. Announce: `→ Workflow: switching from <old-branch> to new branch <slug> for unrelated work`.
30
+ 7. **Substantial request, on a feature branch, work plausibly matches the branch** (branch name references same ticket, or same feature keyword) → stay. No announcement (status quo is the expected default).
31
+
32
+ Announcement format: plain chat, prefixed `→ Workflow:`. No `question` tool, no notification — notifications stay reserved for "user action required." Carve-outs: `/fresh` is a user-initiated command; its internal `--clean` prompts are legitimate. `/ship` executes end-to-end without per-step prompts once invoked (see ship.md Stop conditions for the only exceptions). This rule governs *agent-initiated* decisions only.
@@ -0,0 +1,145 @@
1
+ #!/usr/bin/env bash
2
+ # memory-mcp-launcher.sh — resolve per-repo MEMORY_FILE_PATH and exec the memory MCP server.
3
+ #
4
+ # Fixes glorious-opencode issue #24: the stock @modelcontextprotocol/server-memory
5
+ # invocation via `npx -y ... ` with a RELATIVE MEMORY_FILE_PATH resolves inside the
6
+ # npx cache directory (because OpenCode does not set cwd for MCP launches), so every
7
+ # project silently shares one volatile file buried in ~/.npm/_npx/<hash>/.
8
+ #
9
+ # This launcher resolves the project root via git (worktree-aware, submodule-aware,
10
+ # bare-repo-aware), sets an ABSOLUTE MEMORY_FILE_PATH, ensures the target directory
11
+ # exists, adds a narrow entry to <repo>/.agent/.gitignore so memory.json is not
12
+ # accidentally committed, then execs the real memory server.
13
+ #
14
+ # CONSTRAINTS (do not break these):
15
+ # - Must be bash 3.2 compatible (macOS default /bin/bash).
16
+ # - MUST NOT write anything to stdout before the final `exec npx`. MCP uses stdio
17
+ # JSON-RPC; any stdout noise corrupts the handshake. All diagnostics go to stderr.
18
+ # - Called via `bash "$HOME/.config/opencode/bin/memory-mcp-launcher.sh"` from the
19
+ # opencode.json `command` array. The executable bit is nice-to-have (stored as
20
+ # 100755 in git via `git update-index --chmod=+x`) but not required.
21
+ #
22
+ # ENV CONTRACT:
23
+ # - MEMORY_MCP_LAUNCHER_DEBUG=1
24
+ # After resolving MEMORY_FILE_PATH, log it to stderr as
25
+ # `[memory-mcp-launcher] MEMORY_FILE_PATH=<path>` and still exec npx. Useful
26
+ # when a user asks "where is my memory going?".
27
+ # - MEMORY_MCP_LAUNCHER_PRINT_AND_EXIT=1
28
+ # Test-only. After resolving MEMORY_FILE_PATH, print it to stderr and exit 0
29
+ # (skipping the npx exec). Enables launcher behavior tests without needing
30
+ # an actual MCP handshake. Intentionally undocumented to end users.
31
+
32
+ set -Eeuo pipefail
33
+
34
+ # Init under -u so we can do `[[ -n "$target_path" ]]` later without risk.
35
+ target_path=""
36
+ fallback_path="${HOME}/.config/opencode/memory/fallback.json"
37
+
38
+ # -------- resolve target --------
39
+ # Only attempt git-based resolution if git is on PATH. If anything goes wrong in
40
+ # this block, we drop through to the fallback path — never hard-fail on a git
41
+ # edge case (bare repo, damaged .git, submodule, worktree with missing main, etc).
42
+ if command -v git >/dev/null 2>&1; then
43
+
44
+ # Bare-repo check FIRST, before any path resolution. A bare repo has no
45
+ # working tree so per-repo memory has no sensible location — fall back.
46
+ _is_bare="$(git rev-parse --is-bare-repository 2>/dev/null || printf "")"
47
+ if [[ "$_is_bare" != "true" ]]; then
48
+
49
+ # Get the current repo's working-tree root. Always returns an absolute path.
50
+ # Returns empty (stderr suppressed) when:
51
+ # - not in a git repo
52
+ # - CWD inside the .git directory itself
53
+ # - git is too old / broken
54
+ _toplevel="$(git rev-parse --show-toplevel 2>/dev/null || printf "")"
55
+
56
+ if [[ -n "$_toplevel" ]]; then
57
+ target_path="$_toplevel"
58
+
59
+ # Worktree-share rewrite. For a `git worktree`, the per-worktree toplevel
60
+ # differs from the MAIN worktree — but we want all worktrees of the same
61
+ # repo to share one memory.json. `--git-common-dir` points at the shared
62
+ # .git dir. Its parent is the main working tree.
63
+ #
64
+ # Resolution is CWD-sensitive (common-dir may be relative), so canonicalize
65
+ # inside a subshell via `cd -P && pwd -P`. Failures fall back to _toplevel.
66
+ _common_dir_raw="$(git rev-parse --git-common-dir 2>/dev/null || printf "")"
67
+ if [[ -n "$_common_dir_raw" ]]; then
68
+ _common_abs="$(cd -P "$_common_dir_raw" 2>/dev/null && pwd -P || printf "")"
69
+ if [[ -n "$_common_abs" ]]; then
70
+ _main_candidate="$(dirname "$_common_abs")"
71
+ # Only rewrite if:
72
+ # (a) candidate differs from current toplevel (i.e., we're in a worktree)
73
+ # (b) candidate has a .git entry (real working tree — gitfile OR dir)
74
+ # Submodules: their common-dir is <super>/.git/modules/<name>, parent is
75
+ # .git/modules which has no .git entry, so (b) rejects and we keep the
76
+ # submodule's own toplevel. Bare repos were already skipped above.
77
+ if [[ "$_main_candidate" != "$_toplevel" ]] \
78
+ && [[ -e "$_main_candidate/.git" ]]; then
79
+ target_path="$_main_candidate"
80
+ fi
81
+ fi
82
+ fi
83
+ fi
84
+ fi
85
+ unset _is_bare _toplevel _common_dir_raw _common_abs _main_candidate
86
+ fi
87
+
88
+ # -------- validate target, create dir + narrow gitignore --------
89
+ MEMORY_FILE_PATH=""
90
+ if [[ -n "$target_path" ]]; then
91
+ if mkdir -p "${target_path}/.agent" 2>/dev/null; then
92
+ MEMORY_FILE_PATH="${target_path}/.agent/memory.json"
93
+
94
+ # Narrow gitignore: only ignore `memory.json`. Do NOT touch the file if it
95
+ # already exists — the user (or an earlier run) may have set their own rules
96
+ # and we refuse to clobber sibling tracked content like `.agent/plans/`.
97
+ _gi="${target_path}/.agent/.gitignore"
98
+ if [[ ! -e "$_gi" ]]; then
99
+ _tmp_gi="$(mktemp "${target_path}/.agent/.gitignore.XXXXXX" 2>/dev/null || printf "")"
100
+ if [[ -n "$_tmp_gi" ]]; then
101
+ if printf "memory.json\n" > "$_tmp_gi" 2>/dev/null; then
102
+ mv "$_tmp_gi" "$_gi" 2>/dev/null || rm -f "$_tmp_gi" 2>/dev/null || true
103
+ else
104
+ rm -f "$_tmp_gi" 2>/dev/null || true
105
+ fi
106
+ fi
107
+ unset _tmp_gi
108
+ fi
109
+ unset _gi
110
+ else
111
+ # mkdir failed (read-only mount, perms). Fall through to fallback.
112
+ target_path=""
113
+ fi
114
+ fi
115
+
116
+ # -------- fallback path --------
117
+ if [[ -z "$MEMORY_FILE_PATH" ]]; then
118
+ # Use bash parameter expansion instead of `dirname` so the launcher works on
119
+ # restricted PATHs (e.g., when the environment is so bare that coreutils isn't
120
+ # on PATH, such as a session started with env -i + a minimal PATH).
121
+ _fb_dir="${fallback_path%/*}"
122
+ if ! mkdir -p "$_fb_dir" 2>/dev/null; then
123
+ printf "[memory-mcp-launcher] ERROR: cannot create %s — memory server cannot run\n" "$_fb_dir" >&2
124
+ exit 1
125
+ fi
126
+ MEMORY_FILE_PATH="$fallback_path"
127
+ unset _fb_dir
128
+ fi
129
+
130
+ # -------- debug/test hooks --------
131
+ if [[ "${MEMORY_MCP_LAUNCHER_DEBUG:-0}" == "1" ]]; then
132
+ printf "[memory-mcp-launcher] MEMORY_FILE_PATH=%s\n" "$MEMORY_FILE_PATH" >&2
133
+ fi
134
+
135
+ if [[ "${MEMORY_MCP_LAUNCHER_PRINT_AND_EXIT:-0}" == "1" ]]; then
136
+ printf "%s\n" "$MEMORY_FILE_PATH" >&2
137
+ exit 0
138
+ fi
139
+
140
+ # Intentionally override any pre-existing MEMORY_FILE_PATH in the env. The whole
141
+ # purpose of this launcher is to set the correct path — if a user wants a
142
+ # project-local override, they should set it in their project's opencode.json.
143
+ export MEMORY_FILE_PATH
144
+
145
+ exec npx -y @modelcontextprotocol/server-memory "$@"
@@ -0,0 +1,255 @@
1
+ #!/usr/bin/env bash
2
+ # plan-check.sh — parse a plan file's plan-state fence and report on it.
3
+ #
4
+ # Modes:
5
+ # plan-check.sh <path> Prints a summary line then one line per item:
6
+ # `total=N done=M pending=K invalid=I`
7
+ # `STATUS ID VERIFY` (one per item)
8
+ #
9
+ # plan-check.sh --run <path> Prints the verify command of each PENDING
10
+ # item on stdout, one per line, raw. The
11
+ # caller is responsible for executing them.
12
+ # This script NEVER executes verify commands
13
+ # itself — that would bypass the caller's
14
+ # bash-permission scope.
15
+ #
16
+ # plan-check.sh --check <path>
17
+ # Structural validation only. Exits 1 if any
18
+ # fence item is missing a required field.
19
+ #
20
+ # Fence format, inside `## Acceptance criteria`:
21
+ #
22
+ # ```plan-state
23
+ # - [ ] id: a1
24
+ # intent: Prose description of business intent (one line).
25
+ # tests:
26
+ # - path/to/test.sh::"some test name"
27
+ # - path/to/other.ts::"another test"
28
+ # verify: bash path/to/test.sh
29
+ #
30
+ # - [x] id: a2
31
+ # ...
32
+ # ```
33
+ #
34
+ # Backward compat: a plan without a ```plan-state fence emits the line
35
+ # `legacy` and exits 0 — callers treat it as "old format, fall back".
36
+ #
37
+ # Portability: POSIX bash + awk + grep only. No sed -i.
38
+
39
+ set -eu
40
+
41
+ MODE=""
42
+ PLAN_PATH=""
43
+
44
+ case "${1:-}" in
45
+ --run) MODE=run; PLAN_PATH="${2:-}" ;;
46
+ --check) MODE=check; PLAN_PATH="${2:-}" ;;
47
+ -h|--help|"")
48
+ sed -n '2,34p' "$0"
49
+ exit 0
50
+ ;;
51
+ *) MODE=summary; PLAN_PATH="${1:-}" ;;
52
+ esac
53
+
54
+ if [[ -z "${PLAN_PATH:-}" ]]; then
55
+ echo "plan-check.sh: missing plan path" >&2
56
+ exit 2
57
+ fi
58
+
59
+ if [[ ! -f "$PLAN_PATH" ]]; then
60
+ echo "plan-check.sh: file not found: $PLAN_PATH" >&2
61
+ exit 2
62
+ fi
63
+
64
+ # Extract the plan-state fence body into a temp file. awk state machine:
65
+ # enter `## Acceptance criteria`, enter ``` plan-state, exit on next ```.
66
+ FENCE_BODY="$(awk '
67
+ /^## Acceptance criteria/ { in_ac = 1; next }
68
+ /^## / && in_ac && !in_fence { in_ac = 0 }
69
+ in_ac && /^```plan-state[[:space:]]*$/ { in_fence = 1; next }
70
+ in_fence && /^```[[:space:]]*$/ { in_fence = 0; next }
71
+ in_fence { print }
72
+ ' "$PLAN_PATH")"
73
+
74
+ if [[ -z "$FENCE_BODY" ]]; then
75
+ # No fence found — legacy plan. Report and exit cleanly.
76
+ if [[ "$MODE" == "summary" ]]; then
77
+ echo "legacy (no plan-state fence)"
78
+ fi
79
+ # --run on a legacy plan emits nothing (no commands to run).
80
+ # --check on a legacy plan succeeds (we're accepting legacy plans).
81
+ exit 0
82
+ fi
83
+
84
+ # Parse items. awk state machine:
85
+ # - A line `- [ ] id: ID` or `- [x] id: ID` starts a new item.
86
+ # - While inside an item, indented keys `intent:`, `tests:`, `verify:` set
87
+ # fields. Under `tests:`, subsequent ` - ...` lines extend the list
88
+ # until the next key or the next item.
89
+ # - Items are separated by one or more blank lines OR by the next `- [`.
90
+ #
91
+ # We emit a tab-delimited record per item:
92
+ # STATUS<TAB>ID<TAB>INTENT<TAB>TESTS<TAB>VERIFY
93
+ # TESTS is a `|`-delimited list. Missing fields are the empty string.
94
+ PARSED="$(echo "$FENCE_BODY" | awk '
95
+ function flush() {
96
+ if (cur_id != "") {
97
+ # Trim trailing/leading whitespace on each field
98
+ gsub(/^[[:space:]]+|[[:space:]]+$/, "", cur_intent)
99
+ gsub(/^[[:space:]]+|[[:space:]]+$/, "", cur_verify)
100
+ gsub(/^\||\|$/, "", cur_tests)
101
+ printf "%s\t%s\t%s\t%s\t%s\n", cur_status, cur_id, cur_intent, cur_tests, cur_verify
102
+ }
103
+ cur_status = ""; cur_id = ""; cur_intent = ""; cur_tests = ""; cur_verify = ""
104
+ in_tests = 0
105
+ }
106
+
107
+ /^-[[:space:]]+\[[[:space:]xX[:space:]]\][[:space:]]+id:/ {
108
+ flush()
109
+ status = $0
110
+ sub(/^-[[:space:]]+\[[[:space:]]*/, "", status)
111
+ sub(/\].*$/, "", status)
112
+ # status is either empty/space (" ") -> pending, or "x"/"X" -> done
113
+ if (status ~ /[xX]/) cur_status = "done"; else cur_status = "pending"
114
+ # Capture id
115
+ id_part = $0
116
+ sub(/^.*id:[[:space:]]*/, "", id_part)
117
+ cur_id = id_part
118
+ next
119
+ }
120
+
121
+ /^[[:space:]]*intent:/ {
122
+ field = $0
123
+ sub(/^[[:space:]]*intent:[[:space:]]*/, "", field)
124
+ cur_intent = field
125
+ in_tests = 0
126
+ next
127
+ }
128
+
129
+ /^[[:space:]]*intent\b/ {
130
+ # already handled
131
+ next
132
+ }
133
+
134
+ /^[[:space:]]*tests:/ {
135
+ in_tests = 1
136
+ next
137
+ }
138
+
139
+ /^[[:space:]]*verify:/ {
140
+ field = $0
141
+ sub(/^[[:space:]]*verify:[[:space:]]*/, "", field)
142
+ cur_verify = field
143
+ in_tests = 0
144
+ next
145
+ }
146
+
147
+ # Continuation lines inside tests: list
148
+ in_tests && /^[[:space:]]+-[[:space:]]/ {
149
+ line = $0
150
+ sub(/^[[:space:]]+-[[:space:]]+/, "", line)
151
+ if (cur_tests == "") cur_tests = line
152
+ else cur_tests = cur_tests "|" line
153
+ next
154
+ }
155
+
156
+ # Continuation line for intent (indented without `-`, after intent is set
157
+ # and before another key). Append with a space separator.
158
+ !in_tests && /^[[:space:]]{4,}[^-[:space:]]/ && cur_id != "" && cur_intent != "" && cur_verify == "" {
159
+ line = $0
160
+ sub(/^[[:space:]]+/, "", line)
161
+ cur_intent = cur_intent " " line
162
+ next
163
+ }
164
+
165
+ END { flush() }
166
+ ' 2>&1)"
167
+
168
+ # If PARSED contains awk errors, surface them as invalid.
169
+ if echo "$PARSED" | grep -q '^awk:'; then
170
+ echo "plan-check.sh: parser error" >&2
171
+ echo "$PARSED" >&2
172
+ exit 3
173
+ fi
174
+
175
+ # Count totals.
176
+ total=0
177
+ done_count=0
178
+ pending_count=0
179
+ invalid_count=0
180
+ invalid_reasons=()
181
+
182
+ while IFS=$'\t' read -r status id intent tests verify; do
183
+ [[ -z "$status" ]] && continue
184
+ total=$((total + 1))
185
+ if [[ -z "$id" ]]; then
186
+ invalid_count=$((invalid_count + 1))
187
+ invalid_reasons+=("missing id")
188
+ continue
189
+ fi
190
+ if [[ -z "$intent" ]]; then
191
+ invalid_count=$((invalid_count + 1))
192
+ invalid_reasons+=("$id: missing intent")
193
+ continue
194
+ fi
195
+ if [[ -z "$tests" ]]; then
196
+ invalid_count=$((invalid_count + 1))
197
+ invalid_reasons+=("$id: missing tests")
198
+ continue
199
+ fi
200
+ if [[ -z "$verify" ]]; then
201
+ invalid_count=$((invalid_count + 1))
202
+ invalid_reasons+=("$id: missing verify")
203
+ continue
204
+ fi
205
+ if [[ "$status" == "done" ]]; then
206
+ done_count=$((done_count + 1))
207
+ else
208
+ pending_count=$((pending_count + 1))
209
+ fi
210
+ done <<< "$PARSED"
211
+
212
+ case "$MODE" in
213
+ summary)
214
+ printf 'total=%d done=%d pending=%d invalid=%d\n' \
215
+ "$total" "$done_count" "$pending_count" "$invalid_count"
216
+ while IFS=$'\t' read -r status id intent tests verify; do
217
+ [[ -z "$status" ]] && continue
218
+ # For the summary-per-item line, prefer displaying the verify
219
+ # command (truncated) so the reader sees what gates each item.
220
+ v="${verify:0:60}"
221
+ if [[ -n "$verify" && ${#verify} -gt 60 ]]; then v="${v}…"; fi
222
+ printf '%s %s %s\n' "$status" "$id" "$v"
223
+ done <<< "$PARSED"
224
+ if [[ "$invalid_count" -gt 0 ]]; then
225
+ echo "invalid:"
226
+ for r in "${invalid_reasons[@]}"; do
227
+ echo " $r"
228
+ done
229
+ fi
230
+ ;;
231
+
232
+ run)
233
+ # Emit verify command per PENDING item, one per line. Skip done items,
234
+ # skip invalid items. Caller executes via their own bash permission.
235
+ while IFS=$'\t' read -r status id intent tests verify; do
236
+ [[ -z "$status" ]] && continue
237
+ [[ "$status" == "done" ]] && continue
238
+ [[ -z "$verify" ]] && continue
239
+ [[ -z "$intent" || -z "$tests" ]] && continue
240
+ echo "$verify"
241
+ done <<< "$PARSED"
242
+ ;;
243
+
244
+ check)
245
+ # Structural validation. Exit 1 if anything invalid.
246
+ if [[ "$invalid_count" -gt 0 ]]; then
247
+ echo "plan-check: $invalid_count invalid item(s):" >&2
248
+ for r in "${invalid_reasons[@]}"; do
249
+ echo " $r" >&2
250
+ done
251
+ exit 1
252
+ fi
253
+ printf 'ok: %d item(s) pass structural validation\n' "$total"
254
+ ;;
255
+ esac