@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.
- package/LICENSE +21 -0
- package/README.md +214 -0
- package/adapters/antigravity/adapter.js +196 -0
- package/adapters/antigravity/hooks.json +39 -0
- package/adapters/antigravity/instructions/AGENTS.md +638 -0
- package/adapters/antigravity/instructions/header.md +3 -0
- package/adapters/antigravity/instructions/surfaces.md +153 -0
- package/adapters/antigravity/instructions/vars.json +1 -0
- package/adapters/antigravity/scripts/antigravity-hook-adapter.sh +147 -0
- package/adapters/antigravity/skills/momentum-orient/SKILL.md +29 -0
- package/adapters/antigravity/skills/momentum-reviewer-architecture/SKILL.md +39 -0
- package/adapters/antigravity/skills/momentum-reviewer-qa/SKILL.md +38 -0
- package/adapters/antigravity/skills/momentum-reviewer-security/SKILL.md +42 -0
- package/adapters/antigravity/skills/swarm-supervisor/SKILL.md +75 -0
- package/adapters/antigravity/workflows/continue.md +39 -0
- package/adapters/antigravity/workflows/dispatch.md +49 -0
- package/adapters/antigravity/workflows/handoff.md +38 -0
- package/adapters/antigravity/workflows/review-code.md +84 -0
- package/adapters/antigravity/workflows/scout.md +42 -0
- package/adapters/antigravity/workflows/swarm.md +203 -0
- package/adapters/claude-code/adapter.js +148 -0
- package/adapters/claude-code/commands/continue.md +82 -0
- package/adapters/claude-code/commands/dispatch.md +154 -0
- package/adapters/claude-code/commands/handoff.md +85 -0
- package/adapters/claude-code/commands/review-code.md +194 -0
- package/adapters/claude-code/commands/scout.md +119 -0
- package/adapters/claude-code/commands/swarm.md +242 -0
- package/adapters/claude-code/instructions/header.md +3 -0
- package/adapters/claude-code/instructions/vars.json +1 -0
- package/adapters/claude-code/settings.json +36 -0
- package/adapters/codex/adapter.js +225 -0
- package/adapters/codex/agents/momentum-reviewer-architecture.toml +57 -0
- package/adapters/codex/agents/momentum-reviewer-qa.toml +52 -0
- package/adapters/codex/agents/momentum-reviewer-security.toml +57 -0
- package/adapters/codex/agents/swarm-supervisor.toml +76 -0
- package/adapters/codex/commands/continue.md +40 -0
- package/adapters/codex/commands/dispatch.md +111 -0
- package/adapters/codex/commands/handoff.md +57 -0
- package/adapters/codex/commands/scout.md +90 -0
- package/adapters/codex/commands/swarm.md +334 -0
- package/adapters/codex/hooks.json +36 -0
- package/adapters/codex/instructions/AGENTS.md +691 -0
- package/adapters/codex/instructions/header.md +3 -0
- package/adapters/codex/instructions/surfaces.md +206 -0
- package/adapters/codex/instructions/vars.json +1 -0
- package/adapters/codex/skills/momentum-orient/SKILL.md +29 -0
- package/adapters/opencode/adapter.js +224 -0
- package/adapters/opencode/agents/momentum-reviewer-architecture.md +54 -0
- package/adapters/opencode/agents/momentum-reviewer-qa.md +48 -0
- package/adapters/opencode/agents/momentum-reviewer-security.md +48 -0
- package/adapters/opencode/agents/swarm-supervisor.md +51 -0
- package/adapters/opencode/commands/continue.md +40 -0
- package/adapters/opencode/commands/dispatch.md +111 -0
- package/adapters/opencode/commands/handoff.md +57 -0
- package/adapters/opencode/commands/review-code.md +194 -0
- package/adapters/opencode/commands/scout.md +90 -0
- package/adapters/opencode/commands/swarm.md +334 -0
- package/adapters/opencode/instructions/AGENTS.md +604 -0
- package/adapters/opencode/instructions/header.md +3 -0
- package/adapters/opencode/instructions/surfaces.md +119 -0
- package/adapters/opencode/instructions/vars.json +1 -0
- package/adapters/opencode/plugins/momentum.js +219 -0
- package/adapters/opencode/skills/momentum-lanes/SKILL.md +30 -0
- package/adapters/opencode/skills/momentum-orient/SKILL.md +29 -0
- package/adapters/opencode/skills/momentum-track/SKILL.md +28 -0
- package/adapters/opencode/skills/momentum-validate/SKILL.md +31 -0
- package/bin/antigravity.js +112 -0
- package/bin/ecosystem.js +1302 -0
- package/bin/lanes.js +300 -0
- package/bin/momentum.js +1857 -0
- package/bin/okf.js +72 -0
- package/bin/orchestration-commands.js +305 -0
- package/bin/state-commands.js +218 -0
- package/bin/swarm.js +1104 -0
- package/bin/waves.js +147 -0
- package/core/adapter-capabilities.md +112 -0
- package/core/adapter-parity-matrix.md +170 -0
- package/core/commands/brainstorm-idea.md +98 -0
- package/core/commands/brainstorm-phase.md +129 -0
- package/core/commands/complete-phase.md +130 -0
- package/core/commands/ecosystem.md +161 -0
- package/core/commands/hotfix.md +64 -0
- package/core/commands/initiative.md +119 -0
- package/core/commands/lanes.md +94 -0
- package/core/commands/log.md +45 -0
- package/core/commands/migrate.md +70 -0
- package/core/commands/review.md +31 -0
- package/core/commands/session.md +79 -0
- package/core/commands/start-phase.md +161 -0
- package/core/commands/start-project.md +142 -0
- package/core/commands/sync-docs.md +81 -0
- package/core/commands/systematic-debug.md +46 -0
- package/core/commands/track.md +54 -0
- package/core/commands/validate.md +96 -0
- package/core/ecosystem/layout.md +128 -0
- package/core/ecosystem/lib/index.js +245 -0
- package/core/ecosystem/lib/initiative.js +258 -0
- package/core/ecosystem/lib/pointer.js +198 -0
- package/core/ecosystem/lib/state.js +295 -0
- package/core/ecosystem/schema/ecosystem.schema.json +85 -0
- package/core/ecosystem/schema/initiative.schema.json +61 -0
- package/core/ecosystem/scripts/session-append.sh +167 -0
- package/core/ecosystem/templates/ecosystem-agents.md +79 -0
- package/core/ecosystem/templates/ecosystem-claude.md +79 -0
- package/core/ecosystem/templates/ecosystem-settings-claude.json +14 -0
- package/core/ecosystem/templates/initiative-template.md +50 -0
- package/core/engines/subagent-dispatch.md +80 -0
- package/core/git-hooks/commit-msg +14 -0
- package/core/git-hooks/contract.js +176 -0
- package/core/git-hooks/pre-push +15 -0
- package/core/git-hooks/run-check.js +160 -0
- package/core/instructions/legacy-project-md-hashes.json +12 -0
- package/core/instructions/navigation.md +14 -0
- package/core/instructions/rules-body.md +454 -0
- package/core/lanes/lib/board.js +161 -0
- package/core/lanes/lib/land.js +301 -0
- package/core/lanes/lib/signals.js +207 -0
- package/core/lanes/lib/state.js +325 -0
- package/core/lib/frontmatter.js +163 -0
- package/core/lib/okf-migrate.js +374 -0
- package/core/lib/okf-types.js +61 -0
- package/core/lifecycle-contract.md +59 -0
- package/core/orchestration/capability-routing.js +120 -0
- package/core/orchestration/continue.js +102 -0
- package/core/orchestration/dispatch.js +366 -0
- package/core/orchestration/events.js +197 -0
- package/core/orchestration/handoff.js +317 -0
- package/core/orchestration/index.js +50 -0
- package/core/orchestration/run-artifact.js +93 -0
- package/core/orchestration/scout.js +327 -0
- package/core/orchestration/session-log.js +123 -0
- package/core/orchestration/tracking.js +180 -0
- package/core/orchestration/types.js +131 -0
- package/core/scripts/brainstorm-gate.sh +157 -0
- package/core/scripts/check-history-reminder.sh +110 -0
- package/core/scripts/sessionstart-handoff.sh +180 -0
- package/core/specs-templates/CLAUDE.md +484 -0
- package/core/specs-templates/README.md +32 -0
- package/core/specs-templates/specs/README.md +30 -0
- package/core/specs-templates/specs/adhoc/README.md +31 -0
- package/core/specs-templates/specs/adhoc/_TEMPLATE.md +29 -0
- package/core/specs-templates/specs/architecture/ecosystem.md +214 -0
- package/core/specs-templates/specs/backlog/backlog.md +46 -0
- package/core/specs-templates/specs/backlog/details/.gitkeep +0 -0
- package/core/specs-templates/specs/changelog/.gitkeep +0 -0
- package/core/specs-templates/specs/decisions/0000-template.md +33 -0
- package/core/specs-templates/specs/decisions/README.md +29 -0
- package/core/specs-templates/specs/decisions/impact-map.md +14 -0
- package/core/specs-templates/specs/decisions/index.md +4 -0
- package/core/specs-templates/specs/index.md +16 -0
- package/core/specs-templates/specs/phases/README.md +41 -0
- package/core/specs-templates/specs/phases/index.md +6 -0
- package/core/specs-templates/specs/planning/roadmap.md +23 -0
- package/core/specs-templates/specs/status.md +70 -0
- package/core/specs-templates/specs/vision/principles.md +16 -0
- package/core/specs-templates/specs/vision/project-charter.md +35 -0
- package/core/specs-templates/specs/vision/success-criteria.md +19 -0
- package/core/swarm/absorb.js +294 -0
- package/core/swarm/conductor.js +499 -0
- package/core/swarm/focus.js +151 -0
- package/core/swarm/inbox.js +222 -0
- package/core/swarm/join.js +138 -0
- package/core/swarm/lib/board.js +178 -0
- package/core/swarm/lib/brief.js +157 -0
- package/core/swarm/lib/git-sha-cache.js +71 -0
- package/core/swarm/lib/incremental-log.js +117 -0
- package/core/swarm/lib/manifest.js +578 -0
- package/core/swarm/lib/pre-merge.js +112 -0
- package/core/swarm/lib/saga.js +146 -0
- package/core/swarm/lib/sessions.js +83 -0
- package/core/swarm/lib/tokens.js +255 -0
- package/core/swarm/lib/wave-ordering.js +55 -0
- package/core/swarm/schema/board.schema.json +54 -0
- package/core/swarm/schema/contract.schema.json +56 -0
- package/core/swarm/schema/dispatch-run.schema.json +70 -0
- package/core/swarm/schema/manifest.schema.json +234 -0
- package/core/swarm/schema/signal.schema.json +61 -0
- package/core/swarm/signals.js +296 -0
- package/core/swarm/supervise.md +81 -0
- package/core/waves/lib/plan-graph.js +175 -0
- package/core/waves/lib/waves.js +83 -0
- 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
|
+
};
|