@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,71 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Git HEAD SHA invalidation — Strategy B from the indexing design.
5
+ *
6
+ * The conductor stores per-repo `last_seen_sha` in the manifest. Each
7
+ * conductor turn:
8
+ *
9
+ * 1. `git rev-parse HEAD` per active-wave repo (no token cost)
10
+ * 2. If unchanged → that repo's cached supervisor state is fresh
11
+ * 3. If changed → re-read details + history tail for that repo only
12
+ *
13
+ * This file isolates the spawnSync call so the rest of the swarm code
14
+ * stays pure (and the spawn is easily stubbed in tests).
15
+ */
16
+
17
+ const { spawnSync } = require('child_process');
18
+ const fs = require('fs');
19
+ const path = require('path');
20
+
21
+ /**
22
+ * @param {string} repoPath absolute path to a repo's working tree
23
+ * @returns {string|null} 7+-char hex SHA, or null if not a git repo
24
+ * or HEAD is unborn
25
+ */
26
+ function readHeadSha(repoPath) {
27
+ if (typeof repoPath !== 'string' || repoPath.length === 0) return null;
28
+ if (!fs.existsSync(path.join(repoPath, '.git'))) return null;
29
+ const r = spawnSync('git', ['rev-parse', 'HEAD'], {
30
+ cwd: repoPath,
31
+ encoding: 'utf8',
32
+ timeout: 3000,
33
+ });
34
+ if (r.status !== 0) return null;
35
+ const out = (r.stdout || '').trim();
36
+ return /^[0-9a-f]{7,40}$/.test(out) ? out : null;
37
+ }
38
+
39
+ /**
40
+ * Given a snapshot of (repoId → lastSeenSha) and a way to find each
41
+ * repo's working tree, return:
42
+ * { changed: [repoId,…], unchanged: [repoId,…], shas: {repoId: sha} }
43
+ *
44
+ * `resolveRepoPath(repoId)` returns the absolute path. Lets the caller
45
+ * thread ecosystem-root → member.path lookup without coupling this
46
+ * module to ecosystem internals.
47
+ */
48
+ function diffSinceLastSeen(lastSeen, resolveRepoPath) {
49
+ const changed = [];
50
+ const unchanged = [];
51
+ const shas = {};
52
+ for (const repoId of Object.keys(lastSeen)) {
53
+ const repoPath = resolveRepoPath(repoId);
54
+ const sha = repoPath ? readHeadSha(repoPath) : null;
55
+ shas[repoId] = sha;
56
+ if (sha == null) {
57
+ // Treat unreadable repos as changed so the caller refreshes.
58
+ changed.push(repoId);
59
+ } else if (sha !== lastSeen[repoId]) {
60
+ changed.push(repoId);
61
+ } else {
62
+ unchanged.push(repoId);
63
+ }
64
+ }
65
+ return { changed, unchanged, shas };
66
+ }
67
+
68
+ module.exports = {
69
+ readHeadSha,
70
+ diffSinceLastSeen,
71
+ };
@@ -0,0 +1,117 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Incremental log reader — Strategy C from the indexing design.
5
+ *
6
+ * Two distinct shapes here:
7
+ *
8
+ * 1. Session log incremental read: track `last_read_offset` per
9
+ * session per file; on each conductor turn read only NEW bytes.
10
+ * Typical delta: <500 bytes.
11
+ *
12
+ * 2. History.md tail read: never read the full file. Return the
13
+ * newest N entries (entries are separated by `\n---\n`).
14
+ *
15
+ * Offsets persist at <eco>/swarms/<id>/.offsets.json. Keyed by absolute
16
+ * file path → byte offset.
17
+ */
18
+
19
+ const fs = require('fs');
20
+ const path = require('path');
21
+
22
+ const manifestLib = require('./manifest');
23
+
24
+ const OFFSETS_FILENAME = '.offsets.json';
25
+ const ENTRY_DELIMITER = '\n---\n';
26
+
27
+ function offsetsPath(ecosystemRoot, swarmId) {
28
+ return path.join(manifestLib.swarmDir(ecosystemRoot, swarmId), OFFSETS_FILENAME);
29
+ }
30
+
31
+ function loadOffsets(ecosystemRoot, swarmId) {
32
+ const file = offsetsPath(ecosystemRoot, swarmId);
33
+ if (!fs.existsSync(file)) return {};
34
+ try {
35
+ return JSON.parse(fs.readFileSync(file, 'utf8'));
36
+ } catch (_e) {
37
+ return {};
38
+ }
39
+ }
40
+
41
+ function saveOffsets(ecosystemRoot, swarmId, offsets) {
42
+ manifestLib.ensureSwarmLayout(ecosystemRoot, swarmId);
43
+ const file = offsetsPath(ecosystemRoot, swarmId);
44
+ return manifestLib.withLock(file, () => {
45
+ fs.writeFileSync(file, JSON.stringify(offsets, null, 2) + '\n', 'utf8');
46
+ return file;
47
+ });
48
+ }
49
+
50
+ /**
51
+ * Read NEW bytes appended to `filePath` since the last call. Returns
52
+ * { delta: string, newOffset: number }. If `filePath` doesn't exist
53
+ * yet, returns { delta: '', newOffset: 0 }.
54
+ *
55
+ * If the file shrunk (e.g. truncated/rotated) we reset to 0 and read
56
+ * from the start.
57
+ */
58
+ function readDelta(filePath, lastOffset) {
59
+ if (!fs.existsSync(filePath)) return { delta: '', newOffset: 0 };
60
+ const size = fs.statSync(filePath).size;
61
+ if (lastOffset == null || lastOffset > size) {
62
+ const all = fs.readFileSync(filePath, 'utf8');
63
+ return { delta: all, newOffset: size };
64
+ }
65
+ if (lastOffset === size) {
66
+ return { delta: '', newOffset: size };
67
+ }
68
+ const fd = fs.openSync(filePath, 'r');
69
+ try {
70
+ const length = size - lastOffset;
71
+ const buf = Buffer.alloc(length);
72
+ fs.readSync(fd, buf, 0, length, lastOffset);
73
+ return { delta: buf.toString('utf8'), newOffset: size };
74
+ } finally {
75
+ fs.closeSync(fd);
76
+ }
77
+ }
78
+
79
+ /**
80
+ * Persistent variant: reads delta + updates the swarm's offsets file.
81
+ */
82
+ function readDeltaPersistent(ecosystemRoot, swarmId, filePath) {
83
+ const offsets = loadOffsets(ecosystemRoot, swarmId);
84
+ const last = offsets[filePath] || 0;
85
+ const { delta, newOffset } = readDelta(filePath, last);
86
+ if (newOffset !== last) {
87
+ offsets[filePath] = newOffset;
88
+ saveOffsets(ecosystemRoot, swarmId, offsets);
89
+ }
90
+ return { delta, newOffset, previousOffset: last };
91
+ }
92
+
93
+ /**
94
+ * Read the last `n` entries from a history.md-style append-only file.
95
+ * Entries are separated by `\n---\n`. Returns an array of entry strings
96
+ * (newest last). When the file is empty, returns []. When fewer than
97
+ * `n` entries exist, returns all available.
98
+ */
99
+ function tailHistory(filePath, n) {
100
+ if (!fs.existsSync(filePath)) return [];
101
+ const raw = fs.readFileSync(filePath, 'utf8');
102
+ if (raw.length === 0) return [];
103
+ const parts = raw.split(ENTRY_DELIMITER).map((s) => s.trim()).filter((s) => s.length > 0);
104
+ if (parts.length <= n) return parts;
105
+ return parts.slice(parts.length - n);
106
+ }
107
+
108
+ module.exports = {
109
+ OFFSETS_FILENAME,
110
+ ENTRY_DELIMITER,
111
+ offsetsPath,
112
+ loadOffsets,
113
+ saveOffsets,
114
+ readDelta,
115
+ readDeltaPersistent,
116
+ tailHistory,
117
+ };