@limina-labs/momentum 0.30.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (182) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +214 -0
  3. package/adapters/antigravity/adapter.js +196 -0
  4. package/adapters/antigravity/hooks.json +39 -0
  5. package/adapters/antigravity/instructions/AGENTS.md +638 -0
  6. package/adapters/antigravity/instructions/header.md +3 -0
  7. package/adapters/antigravity/instructions/surfaces.md +153 -0
  8. package/adapters/antigravity/instructions/vars.json +1 -0
  9. package/adapters/antigravity/scripts/antigravity-hook-adapter.sh +147 -0
  10. package/adapters/antigravity/skills/momentum-orient/SKILL.md +29 -0
  11. package/adapters/antigravity/skills/momentum-reviewer-architecture/SKILL.md +39 -0
  12. package/adapters/antigravity/skills/momentum-reviewer-qa/SKILL.md +38 -0
  13. package/adapters/antigravity/skills/momentum-reviewer-security/SKILL.md +42 -0
  14. package/adapters/antigravity/skills/swarm-supervisor/SKILL.md +75 -0
  15. package/adapters/antigravity/workflows/continue.md +39 -0
  16. package/adapters/antigravity/workflows/dispatch.md +49 -0
  17. package/adapters/antigravity/workflows/handoff.md +38 -0
  18. package/adapters/antigravity/workflows/review-code.md +84 -0
  19. package/adapters/antigravity/workflows/scout.md +42 -0
  20. package/adapters/antigravity/workflows/swarm.md +203 -0
  21. package/adapters/claude-code/adapter.js +148 -0
  22. package/adapters/claude-code/commands/continue.md +82 -0
  23. package/adapters/claude-code/commands/dispatch.md +154 -0
  24. package/adapters/claude-code/commands/handoff.md +85 -0
  25. package/adapters/claude-code/commands/review-code.md +194 -0
  26. package/adapters/claude-code/commands/scout.md +119 -0
  27. package/adapters/claude-code/commands/swarm.md +242 -0
  28. package/adapters/claude-code/instructions/header.md +3 -0
  29. package/adapters/claude-code/instructions/vars.json +1 -0
  30. package/adapters/claude-code/settings.json +36 -0
  31. package/adapters/codex/adapter.js +225 -0
  32. package/adapters/codex/agents/momentum-reviewer-architecture.toml +57 -0
  33. package/adapters/codex/agents/momentum-reviewer-qa.toml +52 -0
  34. package/adapters/codex/agents/momentum-reviewer-security.toml +57 -0
  35. package/adapters/codex/agents/swarm-supervisor.toml +76 -0
  36. package/adapters/codex/commands/continue.md +40 -0
  37. package/adapters/codex/commands/dispatch.md +111 -0
  38. package/adapters/codex/commands/handoff.md +57 -0
  39. package/adapters/codex/commands/scout.md +90 -0
  40. package/adapters/codex/commands/swarm.md +334 -0
  41. package/adapters/codex/hooks.json +36 -0
  42. package/adapters/codex/instructions/AGENTS.md +691 -0
  43. package/adapters/codex/instructions/header.md +3 -0
  44. package/adapters/codex/instructions/surfaces.md +206 -0
  45. package/adapters/codex/instructions/vars.json +1 -0
  46. package/adapters/codex/skills/momentum-orient/SKILL.md +29 -0
  47. package/adapters/opencode/adapter.js +224 -0
  48. package/adapters/opencode/agents/momentum-reviewer-architecture.md +54 -0
  49. package/adapters/opencode/agents/momentum-reviewer-qa.md +48 -0
  50. package/adapters/opencode/agents/momentum-reviewer-security.md +48 -0
  51. package/adapters/opencode/agents/swarm-supervisor.md +51 -0
  52. package/adapters/opencode/commands/continue.md +40 -0
  53. package/adapters/opencode/commands/dispatch.md +111 -0
  54. package/adapters/opencode/commands/handoff.md +57 -0
  55. package/adapters/opencode/commands/review-code.md +194 -0
  56. package/adapters/opencode/commands/scout.md +90 -0
  57. package/adapters/opencode/commands/swarm.md +334 -0
  58. package/adapters/opencode/instructions/AGENTS.md +604 -0
  59. package/adapters/opencode/instructions/header.md +3 -0
  60. package/adapters/opencode/instructions/surfaces.md +119 -0
  61. package/adapters/opencode/instructions/vars.json +1 -0
  62. package/adapters/opencode/plugins/momentum.js +219 -0
  63. package/adapters/opencode/skills/momentum-lanes/SKILL.md +30 -0
  64. package/adapters/opencode/skills/momentum-orient/SKILL.md +29 -0
  65. package/adapters/opencode/skills/momentum-track/SKILL.md +28 -0
  66. package/adapters/opencode/skills/momentum-validate/SKILL.md +31 -0
  67. package/bin/antigravity.js +112 -0
  68. package/bin/ecosystem.js +1302 -0
  69. package/bin/lanes.js +300 -0
  70. package/bin/momentum.js +1857 -0
  71. package/bin/okf.js +72 -0
  72. package/bin/orchestration-commands.js +305 -0
  73. package/bin/state-commands.js +218 -0
  74. package/bin/swarm.js +1104 -0
  75. package/bin/waves.js +147 -0
  76. package/core/adapter-capabilities.md +112 -0
  77. package/core/adapter-parity-matrix.md +170 -0
  78. package/core/commands/brainstorm-idea.md +98 -0
  79. package/core/commands/brainstorm-phase.md +129 -0
  80. package/core/commands/complete-phase.md +130 -0
  81. package/core/commands/ecosystem.md +161 -0
  82. package/core/commands/hotfix.md +64 -0
  83. package/core/commands/initiative.md +119 -0
  84. package/core/commands/lanes.md +94 -0
  85. package/core/commands/log.md +45 -0
  86. package/core/commands/migrate.md +70 -0
  87. package/core/commands/review.md +31 -0
  88. package/core/commands/session.md +79 -0
  89. package/core/commands/start-phase.md +161 -0
  90. package/core/commands/start-project.md +142 -0
  91. package/core/commands/sync-docs.md +81 -0
  92. package/core/commands/systematic-debug.md +46 -0
  93. package/core/commands/track.md +54 -0
  94. package/core/commands/validate.md +96 -0
  95. package/core/ecosystem/layout.md +128 -0
  96. package/core/ecosystem/lib/index.js +245 -0
  97. package/core/ecosystem/lib/initiative.js +258 -0
  98. package/core/ecosystem/lib/pointer.js +198 -0
  99. package/core/ecosystem/lib/state.js +295 -0
  100. package/core/ecosystem/schema/ecosystem.schema.json +85 -0
  101. package/core/ecosystem/schema/initiative.schema.json +61 -0
  102. package/core/ecosystem/scripts/session-append.sh +167 -0
  103. package/core/ecosystem/templates/ecosystem-agents.md +79 -0
  104. package/core/ecosystem/templates/ecosystem-claude.md +79 -0
  105. package/core/ecosystem/templates/ecosystem-settings-claude.json +14 -0
  106. package/core/ecosystem/templates/initiative-template.md +50 -0
  107. package/core/engines/subagent-dispatch.md +80 -0
  108. package/core/git-hooks/commit-msg +14 -0
  109. package/core/git-hooks/contract.js +176 -0
  110. package/core/git-hooks/pre-push +15 -0
  111. package/core/git-hooks/run-check.js +160 -0
  112. package/core/instructions/legacy-project-md-hashes.json +12 -0
  113. package/core/instructions/navigation.md +14 -0
  114. package/core/instructions/rules-body.md +454 -0
  115. package/core/lanes/lib/board.js +161 -0
  116. package/core/lanes/lib/land.js +301 -0
  117. package/core/lanes/lib/signals.js +207 -0
  118. package/core/lanes/lib/state.js +325 -0
  119. package/core/lib/frontmatter.js +163 -0
  120. package/core/lib/okf-migrate.js +374 -0
  121. package/core/lib/okf-types.js +61 -0
  122. package/core/lifecycle-contract.md +59 -0
  123. package/core/orchestration/capability-routing.js +120 -0
  124. package/core/orchestration/continue.js +102 -0
  125. package/core/orchestration/dispatch.js +366 -0
  126. package/core/orchestration/events.js +197 -0
  127. package/core/orchestration/handoff.js +317 -0
  128. package/core/orchestration/index.js +50 -0
  129. package/core/orchestration/run-artifact.js +93 -0
  130. package/core/orchestration/scout.js +327 -0
  131. package/core/orchestration/session-log.js +123 -0
  132. package/core/orchestration/tracking.js +180 -0
  133. package/core/orchestration/types.js +131 -0
  134. package/core/scripts/brainstorm-gate.sh +157 -0
  135. package/core/scripts/check-history-reminder.sh +110 -0
  136. package/core/scripts/sessionstart-handoff.sh +180 -0
  137. package/core/specs-templates/CLAUDE.md +484 -0
  138. package/core/specs-templates/README.md +32 -0
  139. package/core/specs-templates/specs/README.md +30 -0
  140. package/core/specs-templates/specs/adhoc/README.md +31 -0
  141. package/core/specs-templates/specs/adhoc/_TEMPLATE.md +29 -0
  142. package/core/specs-templates/specs/architecture/ecosystem.md +214 -0
  143. package/core/specs-templates/specs/backlog/backlog.md +46 -0
  144. package/core/specs-templates/specs/backlog/details/.gitkeep +0 -0
  145. package/core/specs-templates/specs/changelog/.gitkeep +0 -0
  146. package/core/specs-templates/specs/decisions/0000-template.md +33 -0
  147. package/core/specs-templates/specs/decisions/README.md +29 -0
  148. package/core/specs-templates/specs/decisions/impact-map.md +14 -0
  149. package/core/specs-templates/specs/decisions/index.md +4 -0
  150. package/core/specs-templates/specs/index.md +16 -0
  151. package/core/specs-templates/specs/phases/README.md +41 -0
  152. package/core/specs-templates/specs/phases/index.md +6 -0
  153. package/core/specs-templates/specs/planning/roadmap.md +23 -0
  154. package/core/specs-templates/specs/status.md +70 -0
  155. package/core/specs-templates/specs/vision/principles.md +16 -0
  156. package/core/specs-templates/specs/vision/project-charter.md +35 -0
  157. package/core/specs-templates/specs/vision/success-criteria.md +19 -0
  158. package/core/swarm/absorb.js +294 -0
  159. package/core/swarm/conductor.js +499 -0
  160. package/core/swarm/focus.js +151 -0
  161. package/core/swarm/inbox.js +222 -0
  162. package/core/swarm/join.js +138 -0
  163. package/core/swarm/lib/board.js +178 -0
  164. package/core/swarm/lib/brief.js +157 -0
  165. package/core/swarm/lib/git-sha-cache.js +71 -0
  166. package/core/swarm/lib/incremental-log.js +117 -0
  167. package/core/swarm/lib/manifest.js +578 -0
  168. package/core/swarm/lib/pre-merge.js +112 -0
  169. package/core/swarm/lib/saga.js +146 -0
  170. package/core/swarm/lib/sessions.js +83 -0
  171. package/core/swarm/lib/tokens.js +255 -0
  172. package/core/swarm/lib/wave-ordering.js +55 -0
  173. package/core/swarm/schema/board.schema.json +54 -0
  174. package/core/swarm/schema/contract.schema.json +56 -0
  175. package/core/swarm/schema/dispatch-run.schema.json +70 -0
  176. package/core/swarm/schema/manifest.schema.json +234 -0
  177. package/core/swarm/schema/signal.schema.json +61 -0
  178. package/core/swarm/signals.js +296 -0
  179. package/core/swarm/supervise.md +81 -0
  180. package/core/waves/lib/plan-graph.js +175 -0
  181. package/core/waves/lib/waves.js +83 -0
  182. package/package.json +46 -0
@@ -0,0 +1,119 @@
1
+ ## Momentum Recipes — opencode Commands
2
+
3
+ Every momentum recipe ships as a native opencode command at
4
+ `.opencode/commands/<name>.md` ([opencode commands
5
+ docs](https://opencode.ai/docs/commands/)). opencode auto-discovers them
6
+ at startup — type `/` in the TUI and the full recipe set appears; e.g.
7
+ `/brainstorm-phase` runs the phase-planning recipe. Arguments flow via
8
+ `$ARGUMENTS` (e.g. `/track BUG some description`).
9
+
10
+ The shipped recipe set (one command per recipe):
11
+
12
+ | Recipe | What it does |
13
+ |---|---|
14
+ | brainstorm-idea | Explore an idea before scaffolding anything |
15
+ | brainstorm-phase | Plan the next implementation phase (gate-protected) |
16
+ | start-project | Scaffold a new spec-driven project |
17
+ | start-phase | Begin a planned phase (autonomous execution contract) |
18
+ | complete-phase | Verify, retro, release a finished phase |
19
+ | sync-docs | Propagate history entries to other spec docs |
20
+ | track | Track a backlog item (bug / feature / tech debt / enhancement) |
21
+ | review | Review and groom the backlog between phases |
22
+ | log | Append a manual narrative entry to the history of the phase bound to your branch (fallback: status.md) |
23
+ | hotfix | Ship a bounded ad-hoc change (quick-task / spike) without a phase |
24
+ | lanes | Work with lanes — concurrent workstreams in one repo (Rule 15) |
25
+ | migrate | Onboard an existing project into momentum |
26
+ | validate | Check spec structure health |
27
+ | ecosystem | Cross-repo ecosystem coordination |
28
+ | initiative | Manage cross-repo initiatives |
29
+ | session | Append a manual narrative entry to today's ecosystem session log |
30
+ | systematic-debug | Systematically isolate, reproduce, and resolve task execution failures |
31
+ | scout | Read-only context fetch from one ecosystem member repo |
32
+ | dispatch | Parallel multi-repo fan-out + synthesis |
33
+ | handoff | Cross-session control transfer with structured context block |
34
+ | continue | Pick up a pending handoff in this repo |
35
+ | review-code | Multi-perspective code review (uses momentum-reviewer-* subagents) |
36
+ | swarm | Sustained parallel multi-project feature delivery (uses the swarm-supervisor agent) |
37
+
38
+ The recipes are platform-independent — they describe what to do, not how
39
+ opencode specifically should do it. When a recipe mentions "use the Task
40
+ tool" (Claude Code terminology), use opencode's task tool: invoke the
41
+ relevant subagent (`@momentum-reviewer-qa` mention or automatic task
42
+ dispatch).
43
+
44
+ ## Momentum Skills
45
+
46
+ Momentum also ships skills at `.opencode/skills/<name>/SKILL.md`
47
+ ([opencode skills docs](https://opencode.ai/docs/skills/)). opencode
48
+ discovers them natively and exposes them through the `skill` tool — the
49
+ agent loads a skill on demand when its description matches the work.
50
+ Skills complement commands: commands are user-invoked (`/name`), skills
51
+ are agent-invoked (momentum-orient runs Rule 1 orientation without you
52
+ asking).
53
+
54
+ Add project-specific skills under `.opencode/skills/<name>/SKILL.md`
55
+ with `name` + `description` frontmatter (name must match
56
+ `^[a-z0-9]+(-[a-z0-9]+)*$`).
57
+
58
+ ## Momentum Plugin — enforcement hooks
59
+
60
+ Momentum's enforcement layer ships as one plugin at
61
+ `.opencode/plugins/momentum.js` ([opencode plugins
62
+ docs](https://opencode.ai/docs/plugins/)), auto-loaded at startup:
63
+
64
+ | Hook | Purpose |
65
+ |---|---|
66
+ | `tool.execute.before` | Brainstorm gate — blocks write-class tools targeting `specs/**` while `.momentum/brainstorm-active` exists (throws to block, mirroring the Claude Code PreToolUse gate). |
67
+ | `tool.execute.after` | History reminder — prompts for a `history.md` append when meaningful edits land during phase work (Rule 8); bash tool calls additionally delegate to the installed scripts/check-history-reminder.sh, which also feeds the ecosystem session log (ENH-058). |
68
+ | `event (session.created)` | Handoff banner — surfaces pending `.momentum/inbox/` handoffs at session start. **Run-mode caveat**: this handler is registered only in TUI/serve sessions. In `opencode run` (headless/non-interactive) the handler is skipped — its mere presence hangs `opencode run` on 1.17.x (upstream candidate, noted in ENH-058). Session banners are meaningless in headless mode anyway. |
69
+
70
+ The plugin is self-contained (no npm dependencies) and reads the same
71
+ `.momentum/` sentinels as the other adapters' hook scripts — the
72
+ enforcement semantics are identical across platforms.
73
+
74
+ ## Momentum Subagents
75
+
76
+ Momentum ships four agents at `.opencode/agents/` ([opencode agents
77
+ docs](https://opencode.ai/docs/agents/)):
78
+
79
+ - `momentum-reviewer-security.md` — OWASP/STRIDE-focused
80
+ - `momentum-reviewer-qa.md` — test coverage + edge cases + regression risk
81
+ - `momentum-reviewer-architecture.md` — rule compliance + pattern consistency
82
+ - `swarm-supervisor.md` — per-repo supervisor spawned by `/swarm start`
83
+
84
+ The three reviewers declare `mode: subagent` with `permission: edit: deny`
85
+ — they cannot modify the codebase. The `review-code` recipe dispatches
86
+ all three in one turn so opencode can fan them out via the task tool.
87
+ The swarm supervisor is not read-only — supervisors write code, that's
88
+ the job.
89
+
90
+ To add a project-specific reviewer, drop another `<name>.md` into
91
+ `.opencode/agents/` with `description` + `mode: subagent` frontmatter.
92
+
93
+ ## Swarm — Lookup Pattern
94
+
95
+ Momentum's swarm primitive ships on opencode. The swarm recipe lives at
96
+ `.opencode/commands/swarm.md` (`/swarm <sub>`); the CLI floor is
97
+ `momentum swarm <sub> [args]` — both produce the same on-disk artifacts.
98
+
99
+ **Supervisor spawn**: the conductor dispatches spawns through
100
+ `adapters/opencode/adapter.js::spawn(directive)`, which shells
101
+
102
+ ```bash
103
+ opencode run --dir <repoPath> --agent swarm-supervisor "<boot directive>"
104
+ ```
105
+
106
+ `--dir` pins each supervisor's working directory to its repo — no MCP
107
+ cwd shim needed (unlike Codex). If `opencode` isn't on PATH,
108
+ `momentum swarm start --spawn` degrades to dry-run and prints the spawn
109
+ directives for manual launch.
110
+
111
+ ## Instruction precedence note
112
+
113
+ opencode reads `AGENTS.md` (this file) as its primary project
114
+ instruction, with `CLAUDE.md` as a compatibility fallback — when both
115
+ exist (e.g. a project installed for multiple agents), `AGENTS.md` wins
116
+ and nothing is read twice. opencode also discovers Claude-compatible
117
+ skill paths (`.claude/skills/`, `.agents/skills/`); momentum's opencode
118
+ surfaces live under `.opencode/` so multi-adapter installs stay
119
+ side-by-side without collisions.
@@ -0,0 +1 @@
1
+ { "TASK_TOOL": "the built-in **task** tool (subagent fan-out)", "TASK_TOOL_NAME": "The task tool" }
@@ -0,0 +1,219 @@
1
+ // momentum enforcement plugin for opencode.
2
+ //
3
+ // Installed by momentum init/upgrade --agent opencode into
4
+ // .opencode/plugins/momentum.js — auto-loaded by opencode at startup.
5
+ //
6
+ // One plugin, three hooks — the opencode-native equivalent of the shell
7
+ // hooks the other adapters wire (core/scripts/brainstorm-gate.sh,
8
+ // check-history-reminder.sh, sessionstart-handoff.sh). Reads the same
9
+ // .momentum/ sentinels, so enforcement semantics are identical across
10
+ // platforms:
11
+ //
12
+ // tool.execute.before — brainstorm gate: while .momentum/brainstorm-active
13
+ // exists, write-class tools targeting specs/** throw
14
+ // (throwing blocks the tool call).
15
+ // tool.execute.after — history reminder: meaningful edits during phase
16
+ // work prompt for a history.md append (Rule 8);
17
+ // bash tool calls additionally delegate to the
18
+ // installed scripts/check-history-reminder.sh,
19
+ // which also feeds the ecosystem session log
20
+ // (commit / pr events — ENH-058).
21
+ // event (session.created) — session banners: delegates to the installed
22
+ // scripts/sessionstart-handoff.sh (ecosystem
23
+ // context + handoff inbox, same output as every
24
+ // other adapter); pure-JS handoff fallback when
25
+ // the script is absent. TUI/serve sessions only;
26
+ // see the run-mode note below.
27
+ //
28
+ // Node builtins only, no npm dependencies. The ecosystem behaviors reuse the
29
+ // SAME installed shell scripts the other adapters wire (scripts/ self-guard
30
+ // and no-op outside ecosystems), so semantics stay identical across
31
+ // platforms. Fail-open by design: any unexpected error in reminder/banner
32
+ // paths is swallowed; only the gate throws, and only on a confirmed
33
+ // specs/-write during an active brainstorm.
34
+
35
+ import fs from "node:fs"
36
+ import path from "node:path"
37
+ import { spawnSync } from "node:child_process"
38
+
39
+ const WRITE_TOOLS = new Set(["write", "edit", "patch"])
40
+ const REMINDER_THROTTLE_MS = 30 * 60 * 1000 // one nudge per 30 min
41
+ const SCRIPT_TIMEOUT_MS = 3000
42
+
43
+ // Run an installed momentum hook script (scripts/<name>) with the canonical
44
+ // JSON hook payload on stdin. Returns trimmed combined output, or null when
45
+ // the script is missing/failed — callers treat null as "nothing to show".
46
+ function runInstalledScript(root, name, payload) {
47
+ try {
48
+ const script = path.join(root, "scripts", name)
49
+ if (!fs.existsSync(script)) return null
50
+ const r = spawnSync("bash", [script], {
51
+ cwd: root,
52
+ input: payload ? JSON.stringify(payload) : "",
53
+ encoding: "utf8",
54
+ timeout: SCRIPT_TIMEOUT_MS,
55
+ env: { ...process.env, MOMENTUM_PROJECT_DIR: root },
56
+ })
57
+ if (r.error) return null
58
+ const out = `${r.stdout || ""}${r.stderr || ""}`.trim()
59
+ return out.length ? out : ""
60
+ } catch {
61
+ return null
62
+ }
63
+ }
64
+
65
+ function extractTargetPath(tool, args) {
66
+ if (!args || typeof args !== "object") return null
67
+ if (typeof args.filePath === "string") return args.filePath
68
+ if (typeof args.path === "string") return args.path
69
+ if (tool === "bash" && typeof args.command === "string") {
70
+ // Mirror brainstorm-gate.sh's shell heuristic: first specs/ path in the
71
+ // command (catches `> specs/...`, `sed -i ... specs/...`, `tee specs/...`).
72
+ const m = args.command.match(/specs\/[^\s"'\\]+/)
73
+ return m ? m[0] : null
74
+ }
75
+ return null
76
+ }
77
+
78
+ function isUnderSpecs(root, targetPath) {
79
+ const abs = path.isAbsolute(targetPath) ? targetPath : path.join(root, targetPath)
80
+ const rel = path.relative(path.join(root, "specs"), abs)
81
+ return rel === "" || (!rel.startsWith("..") && !path.isAbsolute(rel))
82
+ }
83
+
84
+ export const MomentumPlugin = async ({ directory, worktree }) => {
85
+ const root = worktree || directory || process.cwd()
86
+ const momentumDir = path.join(root, ".momentum")
87
+
88
+ // tool.execute.after does NOT carry tool args (confirmed live, Phase 22 G5)
89
+ // — only the before hook sees them. Correlate by callID so the reminder
90
+ // knows which path a completed write touched. Bounded: entries are removed
91
+ // at after-time; the cap guards sessions whose after hooks never fire.
92
+ const pendingWrites = new Map()
93
+ const pendingBash = new Map()
94
+ const PENDING_CAP = 512
95
+
96
+ const remember = (map, key, value) => {
97
+ if (map.size >= PENDING_CAP) map.delete(map.keys().next().value)
98
+ map.set(key, value)
99
+ }
100
+
101
+ return {
102
+ "tool.execute.before": async (input, output) => {
103
+ const tool = (input && input.tool) || ""
104
+ if (!WRITE_TOOLS.has(tool) && tool !== "bash") return
105
+ const target = extractTargetPath(tool, output && output.args)
106
+ if (target && WRITE_TOOLS.has(tool) && input && input.callID) {
107
+ remember(pendingWrites, input.callID, target)
108
+ }
109
+ if (tool === "bash" && input && input.callID) {
110
+ const command = output && output.args && output.args.command
111
+ if (typeof command === "string") remember(pendingBash, input.callID, command)
112
+ }
113
+ if (!fs.existsSync(path.join(momentumDir, "brainstorm-active"))) return
114
+ if (!target) return // fail-open when no path is extractable
115
+ if (isUnderSpecs(root, target)) {
116
+ throw new Error(
117
+ [
118
+ "[brainstorm-gate] Blocked: cannot write to specs/ during active brainstorm.",
119
+ `[brainstorm-gate] Path: ${target}`,
120
+ "[brainstorm-gate] The conversation IS the draft. Get explicit user approval, then:",
121
+ "[brainstorm-gate] rm .momentum/brainstorm-active",
122
+ "[brainstorm-gate] and retry the write.",
123
+ ].join("\n"),
124
+ )
125
+ }
126
+ },
127
+
128
+ "tool.execute.after": async (input, output) => {
129
+ try {
130
+ const tool = (input && input.tool) || ""
131
+ // Bash completions delegate to the installed reminder script, which
132
+ // also appends commit/pr events to the ecosystem session log
133
+ // (ENH-058). The script self-guards: instant no-op outside
134
+ // ecosystems and for non-matching commands.
135
+ if (tool === "bash") {
136
+ let command = input && input.callID ? pendingBash.get(input.callID) : undefined
137
+ if (input && input.callID) pendingBash.delete(input.callID)
138
+ if (!command && output && output.args) command = output.args.command
139
+ if (typeof command !== "string" || !command) return
140
+ const out = runInstalledScript(root, "check-history-reminder.sh", {
141
+ tool_name: "Bash",
142
+ tool_input: { command },
143
+ })
144
+ if (out) console.log(out)
145
+ return
146
+ }
147
+ if (!WRITE_TOOLS.has(tool)) return
148
+ // Args live only in the before hook — recover the path via callID
149
+ // (fallback to output.args for synthetic/direct invocations).
150
+ let target = input && input.callID ? pendingWrites.get(input.callID) : undefined
151
+ if (input && input.callID) pendingWrites.delete(input.callID)
152
+ if (!target) target = extractTargetPath(tool, output && output.args)
153
+ if (!target) return
154
+ // Edits to the spec layer ARE the tracking — only code/doc edits
155
+ // outside specs/ and .momentum/ warrant a history nudge.
156
+ if (isUnderSpecs(root, target)) return
157
+ const rel = path.relative(root, path.isAbsolute(target) ? target : path.join(root, target))
158
+ if (rel.startsWith(".momentum")) return
159
+
160
+ const stampFile = path.join(momentumDir, "history-reminder-stamp")
161
+ const now = Date.now()
162
+ try {
163
+ const last = fs.statSync(stampFile).mtimeMs
164
+ if (now - last < REMINDER_THROTTLE_MS) return
165
+ } catch {
166
+ /* no stamp yet — proceed */
167
+ }
168
+ fs.mkdirSync(momentumDir, { recursive: true })
169
+ fs.writeFileSync(stampFile, String(now))
170
+ console.log(
171
+ "[momentum] Meaningful edit landed — if this completes a decision, discovery, or " +
172
+ "scope change, append a history entry to your phase's history.md (Rule 8). " +
173
+ "Resolve your phase from the current branch (Rule 15).",
174
+ )
175
+ } catch {
176
+ /* reminder is best-effort; never disturb the session */
177
+ }
178
+ },
179
+
180
+ // Handoff banner. Session events reach plugins ONLY via the generic
181
+ // `event` bus in opencode 1.17.x — a named "session.created" hook key
182
+ // never fires (live-verified, Phase 22 follow-up). The event handler is
183
+ // registered conditionally: its mere presence HANGS `opencode run`
184
+ // non-interactive mode (reproduced on 1.17.13), and a session-start
185
+ // banner is meaningless there anyway — so run-mode skips it.
186
+ ...(process.argv.includes("run")
187
+ ? {}
188
+ : {
189
+ event: async ({ event }) => {
190
+ try {
191
+ if (!event || event.type !== "session.created") return
192
+ // Preferred path (ENH-058): the installed script prints BOTH
193
+ // banners — ecosystem context (parent-walk + sibling-scan) and
194
+ // the handoff inbox — with the same output every other adapter
195
+ // shows. Non-TTY stdin keeps it prompt-free.
196
+ const banners = runInstalledScript(root, "sessionstart-handoff.sh", null)
197
+ if (banners !== null) {
198
+ if (banners) console.log(banners)
199
+ return
200
+ }
201
+ // Fallback (script not installed): pure-JS handoff banner.
202
+ const inboxDir = path.join(momentumDir, "inbox")
203
+ if (!fs.existsSync(inboxDir)) return
204
+ const pending = fs
205
+ .readdirSync(inboxDir)
206
+ .filter((f) => /^handoff-\d+\.md$/.test(f))
207
+ .sort()
208
+ if (pending.length === 0) return
209
+ console.log(
210
+ `[momentum] ${pending.length} pending handoff(s) in .momentum/inbox/: ` +
211
+ `${pending.join(", ")} — run /continue (or \`momentum continue\`) to pick up.`,
212
+ )
213
+ } catch {
214
+ /* banner is best-effort; never disturb the session */
215
+ }
216
+ },
217
+ }),
218
+ }
219
+ }
@@ -0,0 +1,30 @@
1
+ ---
2
+ name: momentum-lanes
3
+ description: Work with concurrent workstreams (Rule 15). Activates when the session involves multiple active branches, cross-lane coordination, or when starting work that should not live on the current branch.
4
+ ---
5
+
6
+ # momentum-lanes
7
+
8
+ Use this skill when you detect concurrent workstreams or need to coordinate
9
+ across branches. Key behaviors:
10
+
11
+ 1. **Lane binding**: your phase is the phase bound to your branch
12
+ (`phase-N-shortname`). `specs/status.md` is the cross-lane overview.
13
+ 2. **Lane-scoped tracking**: write ONLY your own phase's artifacts
14
+ (`tasks.md`, `history.md`, `evidence/`). Shared files (`status.md`,
15
+ `backlog.md`, `changelog/`) are append / own-row-touch only.
16
+ 3. **Landing order**: one lane at a time, suite green on updated `main`
17
+ between landings, remaining lanes rebase.
18
+
19
+ When the user starts a second workstream or asks about what's in flight,
20
+ read the lane board before proceeding.
21
+
22
+ ## When NOT to apply
23
+
24
+ - Single-lane, single-branch sessions with no cross-lane coordination
25
+
26
+ ## References
27
+
28
+ - Rule 15 in `AGENTS.md` — concurrent workstreams
29
+ - `/lanes` command — board, queue, signal, land
30
+ - `specs/status.md` — cross-lane overview
@@ -0,0 +1,29 @@
1
+ ---
2
+ name: momentum-orient
3
+ description: Read specs/status.md before starting any work in a momentum-managed project. Activates at the start of every new task to ensure the agent has current phase context. Codifies Rule 1 (Orient First).
4
+ ---
5
+
6
+ # momentum-orient
7
+
8
+ When this skill activates (at session start or when the user asks you to
9
+ work on something new), read these files in order before any other action:
10
+
11
+ 1. `specs/status.md` — current phase, blockers, P0 items, next actions
12
+ 2. `specs/backlog/backlog.md` — P0/P1 items that may block the current task
13
+ 3. `specs/phases/<active-phase>/tasks.md` — what's done / in flight / blocked
14
+ 4. `AGENTS.md` — project rules and constraints (the complete rulebook)
15
+
16
+ Then proceed with the user's request, framing any output in terms of:
17
+ - which phase is active
18
+ - whether the requested work belongs in the active phase or is a side track
19
+ - any existing tasks or history entries that already cover the request
20
+
21
+ This skill is shipped by the momentum toolkit. It codifies Rule 1 (Orient
22
+ First) from the project rules. See `AGENTS.md` for the full set of rules.
23
+
24
+ ## When NOT to apply this skill
25
+
26
+ - If the user's message is purely conversational ("what is X?") and doesn't
27
+ require touching the codebase, you don't need to orient.
28
+ - If you've already oriented this session and nothing on disk has changed
29
+ since, don't re-orient.
@@ -0,0 +1,28 @@
1
+ ---
2
+ name: momentum-track
3
+ description: Record a new backlog item (bug, feature, tech debt, or enhancement) when you discover work that needs tracking. Activates when the session identifies unplanned work that should be tracked in the backlog.
4
+ ---
5
+
6
+ # momentum-track
7
+
8
+ When you discover something that should be tracked during a session
9
+ (a bug, a missing feature, tech debt, an enhancement), automatically:
10
+
11
+ 1. Read `specs/backlog/backlog.md` to find the next available ID
12
+ 2. Determine item type and prefix: `BUG-`, `FEAT-`, `TD-`, or `ENH-`
13
+ 3. Add a row to the appropriate table with priority (infer from urgency), status `open`, and target phase or `unscheduled`
14
+ 4. Mention the new item to the user: "I found [issue] and added it as [ID] to backlog"
15
+
16
+ This skill codifies Rule 3 (Auto-Track Discoveries) from the project rules.
17
+
18
+ ## When NOT to apply
19
+
20
+ - If the user explicitly asks you not to track something
21
+ - If the issue is already tracked (check the backlog first)
22
+ - For purely conversational exploration where no work item is identified
23
+
24
+ ## References
25
+
26
+ - `/track` command for manual tracking
27
+ - `specs/backlog/backlog.md` — the backlog file
28
+ - Rule 3 in `AGENTS.md` — auto-track discoveries
@@ -0,0 +1,31 @@
1
+ ---
2
+ name: momentum-validate
3
+ description: Check spec structure health of the momentum project. Activates when the user runs `/validate`, asks for a health check, or when spec changes need verification before phase completion.
4
+ ---
5
+
6
+ # momentum-validate
7
+
8
+ When spec health validation is needed:
9
+
10
+ 1. Read `specs/status.md` — verify required fields are present
11
+ 2. Read `specs/backlog/backlog.md` — verify all 4 section tables
12
+ 3. For each phase directory under `specs/phases/`: verify all required files
13
+ and frontmatter
14
+ 4. Check `.momentum/installed.json` — verify schema and agent entries
15
+ 5. Verify `AGENTS.md` or `CLAUDE.md` primary instruction file has the
16
+ `## Project Extensions` marker
17
+ 6. Report all failures found
18
+
19
+ This skill supports the `/validate` command for deep spec structure checks.
20
+ Use it proactively before `/complete-phase` to catch structural issues early.
21
+
22
+ ## When NOT to apply
23
+
24
+ - During active implementation work (validation should not interrupt flow)
25
+ - When the user explicitly asks for no validation
26
+
27
+ ## References
28
+
29
+ - `/validate` command — run health checks
30
+ - `specs/status.md` — project status
31
+ - Rule 9 in `AGENTS.md` — doc sync protocol
@@ -0,0 +1,112 @@
1
+ 'use strict';
2
+
3
+ // momentum antigravity <subcommand> — Antigravity-specific utilities.
4
+ //
5
+ // Phase 22b G3 (ADR-0006). The only subcommand today is `plugin-pack`:
6
+ // assembles momentum's skills into a native Antigravity PLUGIN bundle
7
+ // (`plugins/<name>/plugin.json` + `skills/`, per the vendor plugin layout —
8
+ // fact-sheet §6). Two targets:
9
+ //
10
+ // momentum antigravity plugin-pack → <cwd>/.agents/plugins/momentum/
11
+ // momentum antigravity plugin-pack --global → ~/.gemini/config/plugins/momentum/
12
+ //
13
+ // The --global form is the explicit OPT-IN way to get momentum's skills in
14
+ // every Antigravity workspace on this machine (global discovery root,
15
+ // priority below workspace files — a project-level install always wins).
16
+ // Hooks are deliberately NOT packed: plugin hooks run with CWD = the
17
+ // plugin's own directory, so momentum's project-relative hook commands only
18
+ // make sense installed per-project by `momentum init/upgrade`.
19
+ //
20
+ // momentum never installs or provisions the `agy` binary itself — see the
21
+ // VAL-002 adjudication (specs/adhoc/feat-VAL-002-antigravity-compatibility/).
22
+
23
+ const fs = require('fs');
24
+ const path = require('path');
25
+ const os = require('os');
26
+
27
+ const PLUGIN_NAME = 'momentum';
28
+
29
+ function copyDirRecursive(src, dest, dryRun, log) {
30
+ const entries = fs.readdirSync(src, { withFileTypes: true });
31
+ for (const entry of entries) {
32
+ const s = path.join(src, entry.name);
33
+ const d = path.join(dest, entry.name);
34
+ if (entry.isDirectory()) {
35
+ if (!dryRun) fs.mkdirSync(d, { recursive: true });
36
+ copyDirRecursive(s, d, dryRun, log);
37
+ } else {
38
+ if (!dryRun) {
39
+ fs.mkdirSync(path.dirname(d), { recursive: true });
40
+ fs.copyFileSync(s, d);
41
+ }
42
+ log.push(d);
43
+ }
44
+ }
45
+ }
46
+
47
+ function cmdPluginPack(args) {
48
+ const global = args.includes('--global');
49
+ const dryRun = args.includes('--dry-run');
50
+ const positional = args.filter((a) => !a.startsWith('--'));
51
+
52
+ const skillsSrc = path.join(__dirname, '..', 'adapters', 'antigravity', 'skills');
53
+ if (!fs.existsSync(skillsSrc)) {
54
+ throw new Error(`antigravity skills source not found at ${skillsSrc}`);
55
+ }
56
+
57
+ const home = process.env.MOMENTUM_HOME_OVERRIDE || os.homedir();
58
+ const base = global
59
+ ? path.join(home, '.gemini', 'config', 'plugins', PLUGIN_NAME)
60
+ : path.join(path.resolve(positional[0] || process.cwd()), '.agents', 'plugins', PLUGIN_NAME);
61
+
62
+ console.log(`→ Packing momentum as an Antigravity plugin${dryRun ? ' (dry-run)' : ''}...`);
63
+ console.log(` target: ${base}`);
64
+
65
+ const written = [];
66
+ const manifestPath = path.join(base, 'plugin.json');
67
+ if (!dryRun) {
68
+ fs.mkdirSync(base, { recursive: true });
69
+ fs.writeFileSync(manifestPath, JSON.stringify({ name: PLUGIN_NAME }, null, 2) + '\n');
70
+ }
71
+ written.push(manifestPath);
72
+ copyDirRecursive(skillsSrc, path.join(base, 'skills'), dryRun, written);
73
+
74
+ for (const f of written) {
75
+ console.log(` ${dryRun ? '✋ would write' : '+ wrote'}: ${path.relative(path.dirname(base), f)}`);
76
+ }
77
+ console.log('');
78
+ console.log(` ✓ plugin ${dryRun ? 'planned' : 'packed'} (${written.length} files).`);
79
+ console.log(` Validate: agy plugin validate "${base}"`);
80
+ if (global) {
81
+ console.log(' Global plugins apply to every Antigravity workspace on this machine;');
82
+ console.log(' a per-project momentum install always takes priority.');
83
+ }
84
+ return base;
85
+ }
86
+
87
+ function usage() {
88
+ console.log('Usage: momentum antigravity <subcommand>');
89
+ console.log('');
90
+ console.log('Subcommands:');
91
+ console.log(' plugin-pack [target] [--global] [--dry-run]');
92
+ console.log(' Assemble momentum skills as a native Antigravity plugin at');
93
+ console.log(' <target>/.agents/plugins/momentum/ (or the global discovery');
94
+ console.log(' root ~/.gemini/config/plugins/momentum/ with --global).');
95
+ }
96
+
97
+ function runAntigravity(args) {
98
+ const sub = args[0];
99
+ if (!sub || sub === 'help' || sub === '--help') {
100
+ usage();
101
+ return;
102
+ }
103
+ if (sub === 'plugin-pack') {
104
+ cmdPluginPack(args.slice(1));
105
+ return;
106
+ }
107
+ console.error(`Unknown antigravity subcommand: ${sub}`);
108
+ usage();
109
+ process.exit(1);
110
+ }
111
+
112
+ module.exports = { runAntigravity, cmdPluginPack };