compounding-loop 0.0.0-stage → 0.2.0
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 +123 -3
- package/bin/loop.js +2 -0
- package/dist/cli/checkLanes.js +60 -0
- package/dist/cli/checkLanes.js.map +1 -0
- package/dist/cli/dashboard.js +52 -0
- package/dist/cli/dashboard.js.map +1 -0
- package/dist/cli/doctor.js +54 -0
- package/dist/cli/doctor.js.map +1 -0
- package/dist/cli/gh.js +29 -0
- package/dist/cli/gh.js.map +1 -0
- package/dist/cli/index.js +228 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/init.js +73 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/laneStatus.js +52 -0
- package/dist/cli/laneStatus.js.map +1 -0
- package/dist/cli/lanesInit.js +56 -0
- package/dist/cli/lanesInit.js.map +1 -0
- package/dist/cli/lock.js +42 -0
- package/dist/cli/lock.js.map +1 -0
- package/dist/cli/loops.js +92 -0
- package/dist/cli/loops.js.map +1 -0
- package/dist/cli/new.js +54 -0
- package/dist/cli/new.js.map +1 -0
- package/dist/cli/run.js +169 -0
- package/dist/cli/run.js.map +1 -0
- package/dist/core/blocked.js +42 -0
- package/dist/core/blocked.js.map +1 -0
- package/dist/core/brief.js +91 -0
- package/dist/core/brief.js.map +1 -0
- package/dist/core/doctor.js +49 -0
- package/dist/core/doctor.js.map +1 -0
- package/dist/core/gh.js +2 -0
- package/dist/core/gh.js.map +1 -0
- package/dist/core/init.js +59 -0
- package/dist/core/init.js.map +1 -0
- package/dist/core/laneStatus.js +82 -0
- package/dist/core/laneStatus.js.map +1 -0
- package/dist/core/lanes.js +139 -0
- package/dist/core/lanes.js.map +1 -0
- package/dist/core/lanesInit.js +143 -0
- package/dist/core/lanesInit.js.map +1 -0
- package/dist/core/repo.js +81 -0
- package/dist/core/repo.js.map +1 -0
- package/dist/core/rounds.js +50 -0
- package/dist/core/rounds.js.map +1 -0
- package/dist/core/runPrompt.js +31 -0
- package/dist/core/runPrompt.js.map +1 -0
- package/dist/core/status.js +21 -0
- package/dist/core/status.js.map +1 -0
- package/dist/core/table.js +43 -0
- package/dist/core/table.js.map +1 -0
- package/dist/core/template.js +29 -0
- package/dist/core/template.js.map +1 -0
- package/dist/core/types.js +3 -0
- package/dist/core/types.js.map +1 -0
- package/dist/server/data.js +50 -0
- package/dist/server/data.js.map +1 -0
- package/dist/server/events.js +106 -0
- package/dist/server/events.js.map +1 -0
- package/dist/server/five-sites.json +3071 -0
- package/dist/server/health.js +193 -0
- package/dist/server/health.js.map +1 -0
- package/dist/server/index.js +134 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/loops.js +145 -0
- package/dist/server/loops.js.map +1 -0
- package/dist/server/settings.js +25 -0
- package/dist/server/settings.js.map +1 -0
- package/dist/server/static-export.js +28 -0
- package/dist/server/static-export.js.map +1 -0
- package/dist/server/static.js +80 -0
- package/dist/server/static.js.map +1 -0
- package/dist/server/this-repo.json +371 -0
- package/dist/web/assets/index-B16QCSnY.css +2 -0
- package/dist/web/assets/index-CS82DKbF.js +49 -0
- package/dist/web/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2 +0 -0
- package/dist/web/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2 +0 -0
- package/dist/web/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2 +0 -0
- package/dist/web/assets/inter-greek-wght-normal-CkhJZR-_.woff2 +0 -0
- package/dist/web/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
- package/dist/web/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
- package/dist/web/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2 +0 -0
- package/dist/web/assets/jetbrains-mono-cyrillic-wght-normal-D73BlboJ.woff2 +0 -0
- package/dist/web/assets/jetbrains-mono-greek-wght-normal-Bw9x6K1M.woff2 +0 -0
- package/dist/web/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
- package/dist/web/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
- package/dist/web/assets/jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq.woff2 +0 -0
- package/dist/web/favicon.svg +1 -0
- package/dist/web/index.html +14 -0
- package/dist/web/logo.svg +1 -0
- package/method/COMPOUNDING_LOOP.md +603 -0
- package/method/example/K-0001.md +16 -0
- package/method/example/K-0002.md +16 -0
- package/method/example/K-0003.md +16 -0
- package/method/knowledge-index.md +5 -0
- package/method/operating-card.md +40 -0
- package/method/retro.md +10 -0
- package/method/reviewer-prompt.md +13 -0
- package/method/stuck-protocol.md +12 -0
- package/method/task-template.md +41 -0
- package/package.json +76 -4
- package/plugin/.claude-plugin/plugin.json +7 -0
- package/plugin/commands/handoff.md +10 -0
- package/plugin/commands/loop-init.md +13 -0
- package/plugin/commands/retro.md +11 -0
- package/plugin/commands/stuck.md +10 -0
- package/runners/github-actions/lanes.yml +103 -0
- package/runners/github-actions/loop.yml +51 -0
- package/runners/local/README.md +9 -0
- package/runners/local/crontab.txt +6 -0
- package/runners/local/launchd.plist +36 -0
- package/runners/local/task-scheduler.xml +32 -0
- package/runners/routine/README.md +56 -0
- package/runners/routine/control-room-prompt.md +16 -0
- package/runners/routine/lane-prompt.md +12 -0
- package/runners/routine/prompt.md +13 -0
- package/templates/chrome-extension/CLAUDE.md +18 -0
- package/templates/chrome-extension/IDEA.md +22 -0
- package/templates/chrome-extension/extension/background.js +5 -0
- package/templates/chrome-extension/extension/icons/icon128.png +0 -0
- package/templates/chrome-extension/extension/icons/icon16.png +0 -0
- package/templates/chrome-extension/extension/icons/icon48.png +0 -0
- package/templates/chrome-extension/extension/manifest.json +25 -0
- package/templates/chrome-extension/extension/popup.css +3 -0
- package/templates/chrome-extension/extension/popup.html +15 -0
- package/templates/chrome-extension/extension/popup.js +16 -0
- package/templates/chrome-extension/gitignore +6 -0
- package/templates/chrome-extension/package.json +12 -0
- package/templates/chrome-extension/playwright.config.js +22 -0
- package/templates/chrome-extension/scripts/check.mjs +51 -0
- package/templates/chrome-extension/scripts/test.mjs +59 -0
- package/templates/chrome-extension/tests/popup.spec.js +37 -0
- package/templates/lanes/README.md +23 -0
- package/templates/lanes/ci-check-lanes.yml +38 -0
- package/templates/lanes/claude-section.md +17 -0
- package/templates/lanes/control-room.md +3 -0
- package/templates/lanes/outbox.md +5 -0
- package/templates/lanes/task.md +36 -0
- package/templates/static-site/.ai/index.md +5 -0
- package/templates/static-site/.ai/log.md +3 -0
- package/templates/static-site/.ai/loop-prompt.md +10 -0
- package/templates/static-site/.ai/task.md +27 -0
- package/templates/static-site/.gitattributes +1 -0
- package/templates/static-site/CLAUDE.md +113 -0
- package/templates/static-site/IDEA.md +36 -0
- package/templates/static-site/gitignore +6 -0
- package/templates/static-site/netlify.toml +14 -0
- package/templates/static-site/package.json +14 -0
- package/templates/static-site/playwright.config.js +27 -0
- package/templates/static-site/scripts/check.mjs +188 -0
- package/templates/static-site/scripts/serve.mjs +44 -0
- package/templates/static-site/scripts/test.mjs +59 -0
- package/templates/static-site/site/index.html +23 -0
- package/templates/static-site/site/robots.txt +4 -0
- package/templates/static-site/site/sitemap.xml +4 -0
- package/templates/static-site/tests/pages.spec.js +21 -0
- package/templates/static-site/vercel.json +19 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/cli/run.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
function sectionText(text, label) {
|
|
2
|
+
const lines = text.split(/\r?\n/);
|
|
3
|
+
const start = lines.findIndex((l) => label.test(l.replace(/^#+\s*|\*\*/g, '').trim()));
|
|
4
|
+
if (start === -1)
|
|
5
|
+
return '';
|
|
6
|
+
const first = (lines[start] ?? '').replace(/^#+\s*/, '').replace(/\*\*/g, '');
|
|
7
|
+
const inline = first.replace(/^[^:]*:/, '').trim();
|
|
8
|
+
const body = inline && first.includes(':') ? [inline] : [];
|
|
9
|
+
for (const line of lines.slice(start + 1)) {
|
|
10
|
+
if (/^#+\s/.test(line) || /^\s*\*\*[^*]+\*\*:?/.test(line))
|
|
11
|
+
break;
|
|
12
|
+
body.push(line);
|
|
13
|
+
}
|
|
14
|
+
return body.join('\n').trim();
|
|
15
|
+
}
|
|
16
|
+
/** Pulls the question and best guess out of a BLOCKED.md, tolerating headings or bold labels. */
|
|
17
|
+
export function parseBlocked(text) {
|
|
18
|
+
const question = sectionText(text, /^(the )?(specific )?question/i);
|
|
19
|
+
const bestGuess = sectionText(text, /^(my |the )?best guess/i);
|
|
20
|
+
return { question: question || text.trim(), bestGuess, raw: text };
|
|
21
|
+
}
|
|
22
|
+
/** The block appended to task.md so the next run sees the owner's answer as a decision. */
|
|
23
|
+
export function formatAnswer(note, answer, date) {
|
|
24
|
+
const question = note.question.split(/\r?\n/)[0] ?? '';
|
|
25
|
+
return `### Owner answer, ${date}\nQuestion: ${question}\nAnswer: ${answer.trim()}\n`;
|
|
26
|
+
}
|
|
27
|
+
/** Inserts an answer block under "## Decisions" (or at the end when the file has none). */
|
|
28
|
+
export function addAnswerToTask(taskText, block) {
|
|
29
|
+
const match = /^## Decisions[^\n]*\n/m.exec(taskText);
|
|
30
|
+
if (!match)
|
|
31
|
+
return `${taskText.replace(/\s*$/, '')}\n\n## Decisions\n${block}`;
|
|
32
|
+
const at = match.index + match[0].length;
|
|
33
|
+
return `${taskText.slice(0, at)}${block}\n${taskText.slice(at)}`;
|
|
34
|
+
}
|
|
35
|
+
export const BUDGET_EXTENSION = 30;
|
|
36
|
+
/** True when BLOCKED.md was written because the run budget ran out (it has no real question). */
|
|
37
|
+
export const isBudgetBlock = (text) => /run budget/i.test(text);
|
|
38
|
+
/** Raises the limit of `Run: N / LIMIT` to N + BUDGET_EXTENSION; leaves other text alone. */
|
|
39
|
+
export function extendRunBudget(taskText, extra = BUDGET_EXTENSION) {
|
|
40
|
+
return taskText.replace(/^Run:\s*(\d+)\s*\/\s*\d+/m, (_whole, run) => `Run: ${run} / ${Number(run) + extra}`);
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=blocked.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blocked.js","sourceRoot":"","sources":["../../src/core/blocked.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// Brief linter. Pure and free of Node imports: the web wizard runs the same code in the browser.
|
|
2
|
+
export const MIN_BRIEF_SCORE = 60;
|
|
3
|
+
const VAGUE_WORDS = /\b(good|nice|great|modern|fast|clean|user-friendly|intuitive|robust|scalable|beautiful)\b/i;
|
|
4
|
+
const MIN_WORDS = 120;
|
|
5
|
+
/** Bold labels (`**Goal:** text`) count as the deepest heading level. */
|
|
6
|
+
const LABEL_LEVEL = 7;
|
|
7
|
+
function splitSections(text) {
|
|
8
|
+
const flat = [];
|
|
9
|
+
for (const line of text.split(/\r?\n/)) {
|
|
10
|
+
const heading = /^(#{1,6})\s+(.*?)\s*#*\s*$/.exec(line);
|
|
11
|
+
const label = /^\s*\*\*(.+?)\*\*:?\s*(.*)$/.exec(line) ?? /^\s*\*\*(.+?):\*\*\s*(.*)$/.exec(line);
|
|
12
|
+
if (heading)
|
|
13
|
+
flat.push({ heading: heading[2] ?? '', level: (heading[1] ?? '#').length, own: '' });
|
|
14
|
+
else if (label && !/^\s*[-*+]\s/.test(line))
|
|
15
|
+
flat.push({ heading: (label[1] ?? '').replace(/:$/, ''), level: LABEL_LEVEL, own: `${label[2] ?? ''}\n` });
|
|
16
|
+
else {
|
|
17
|
+
const last = flat[flat.length - 1];
|
|
18
|
+
if (last)
|
|
19
|
+
last.own += `${line}\n`;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return flat.map((section, i) => {
|
|
23
|
+
let body = section.own;
|
|
24
|
+
for (const later of flat.slice(i + 1)) {
|
|
25
|
+
if (later.level <= section.level)
|
|
26
|
+
break;
|
|
27
|
+
body += later.own;
|
|
28
|
+
}
|
|
29
|
+
return { heading: section.heading, body };
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
const findSection = (sections, pattern) => sections.find((s) => pattern.test(s.heading));
|
|
33
|
+
/** Bullet and numbered-list items of a section body, without their markers. */
|
|
34
|
+
export function listItems(body) {
|
|
35
|
+
return body
|
|
36
|
+
.split(/\r?\n/)
|
|
37
|
+
.map((line) => /^\s*(?:[-*+]|\d+[.)])\s+(?:\[[ xX]\]\s+)?(.+)$/.exec(line)?.[1]?.trim())
|
|
38
|
+
.filter((item) => Boolean(item));
|
|
39
|
+
}
|
|
40
|
+
/** A must-have is vague when it is very short, or leans on a fuzzy word with no number, path or command to check. */
|
|
41
|
+
export function isVagueItem(item) {
|
|
42
|
+
const hasEvidence = /`[^`]+`|\d/.test(item);
|
|
43
|
+
if (item.split(/\s+/).length < 4 && !hasEvidence)
|
|
44
|
+
return true;
|
|
45
|
+
return VAGUE_WORDS.test(item) && !hasEvidence;
|
|
46
|
+
}
|
|
47
|
+
/** Scores a brief (the project's IDEA.md) and names what is missing. */
|
|
48
|
+
export function lintBrief(text) {
|
|
49
|
+
const sections = splitSections(text);
|
|
50
|
+
const gaps = [];
|
|
51
|
+
const miss = (gap) => gaps.push(gap);
|
|
52
|
+
const oneLine = findSection(sections, /^\W*(one[- ]line|summary|overview|goal|what (this|it) is|pitch)\b/i);
|
|
53
|
+
if (!oneLine || oneLine.body.trim().length < 20) {
|
|
54
|
+
miss({ id: 'one-line', cost: 15, message: 'No one-line description of what you are building.' });
|
|
55
|
+
}
|
|
56
|
+
const audience = findSection(sections, /^\W*(who\b|audience|users?\b|customers?\b|target)/i);
|
|
57
|
+
if (!audience || audience.body.trim().length < 20) {
|
|
58
|
+
miss({ id: 'audience', cost: 15, message: 'No audience: say who this is for.' });
|
|
59
|
+
}
|
|
60
|
+
const mustHeading = findSection(sections, /^\W*(must[- ]?haves?|requirements?|features?|deliverables?|scope\b)/i);
|
|
61
|
+
const items = mustHeading ? listItems(mustHeading.body) : [];
|
|
62
|
+
if (items.length < 3) {
|
|
63
|
+
miss({ id: 'must-haves', cost: 20, message: 'Fewer than three must-haves listed as bullets.' });
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
const vague = items.filter(isVagueItem);
|
|
67
|
+
if (vague.length > items.length / 2) {
|
|
68
|
+
miss({
|
|
69
|
+
id: 'vague-must-haves',
|
|
70
|
+
cost: 10,
|
|
71
|
+
message: `Vague must-haves (${vague.length} of ${items.length}): add numbers, paths or commands that can be checked.`,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
const doneWhen = findSection(sections, /^\W*(done[- ]when|definition of done|acceptance|success criteria)/i);
|
|
76
|
+
const checkable = doneWhen ? /`[^`]+`|\b(npm|pnpm|yarn|pytest|make|cargo)\b|\btests?\s+(pass|green)/i.test(doneWhen.body) : false;
|
|
77
|
+
if (!checkable) {
|
|
78
|
+
miss({ id: 'done-when', cost: 25, message: 'No checkable done-when: list commands or tests that must pass.' });
|
|
79
|
+
}
|
|
80
|
+
const outOfScope = findSection(sections, /^\W*(out of scope|not in scope|non-goals?|not included|won'?t)/i);
|
|
81
|
+
if (!outOfScope || outOfScope.body.trim().length < 10) {
|
|
82
|
+
miss({ id: 'out-of-scope', cost: 15, message: 'No out-of-scope section: say what the loop must not build.' });
|
|
83
|
+
}
|
|
84
|
+
if (text.split(/\s+/).filter(Boolean).length < MIN_WORDS) {
|
|
85
|
+
miss({ id: 'length', cost: 10, message: `Under ${MIN_WORDS} words: too thin for an unattended build.` });
|
|
86
|
+
}
|
|
87
|
+
const score = Math.max(0, 100 - gaps.reduce((sum, gap) => sum + gap.cost, 0));
|
|
88
|
+
return { score, gaps };
|
|
89
|
+
}
|
|
90
|
+
export const briefPasses = (lint) => lint.score >= MIN_BRIEF_SCORE;
|
|
91
|
+
//# sourceMappingURL=brief.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brief.js","sourceRoot":"","sources":["../../src/core/brief.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// Pure part of `loop doctor`: turn probe results into checks with a fix for each failure.
|
|
2
|
+
export const MIN_NODE_MAJOR = 20;
|
|
3
|
+
export function parseNodeMajor(version) {
|
|
4
|
+
const major = Number(/^v?(\d+)/.exec(version.trim())?.[1]);
|
|
5
|
+
return Number.isFinite(major) ? major : 0;
|
|
6
|
+
}
|
|
7
|
+
const firstLine = (text) => text.trim().split(/\r?\n/)[0] ?? '';
|
|
8
|
+
export function evaluateDoctor(input) {
|
|
9
|
+
const nodeOk = parseNodeMajor(input.nodeVersion) >= MIN_NODE_MAJOR;
|
|
10
|
+
return [
|
|
11
|
+
{
|
|
12
|
+
id: 'node', label: `Node.js ${MIN_NODE_MAJOR} or newer`, required: true, ok: nodeOk, detail: input.nodeVersion,
|
|
13
|
+
fix: nodeOk ? '' : `Install Node.js ${MIN_NODE_MAJOR}+ from https://nodejs.org (or use nvm/fnm), then open a new terminal.`,
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
id: 'git', label: 'git', required: true, ok: input.git.ok, detail: input.git.ok ? firstLine(input.git.output) : 'not found',
|
|
17
|
+
fix: input.git.ok ? '' : 'Install git from https://git-scm.com/downloads and make sure `git --version` works.',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
id: 'claude', label: 'Claude Code (claude)', required: true, ok: input.claude.ok, detail: input.claude.ok ? firstLine(input.claude.output) : firstLine(input.claude.output) || 'not found',
|
|
21
|
+
fix: input.claude.ok ? '' : input.claude.output.includes('.cmd') ? input.claude.output : 'Install Claude Code (https://docs.claude.com/en/docs/claude-code), then run `claude` once to sign in.',
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
id: 'gh', label: 'GitHub CLI (gh), needed by `loop new` and for pushing', required: false, ok: input.gh.ok, detail: input.gh.ok ? firstLine(input.gh.output) : 'not found',
|
|
25
|
+
fix: input.gh.ok ? '' : 'Install gh from https://cli.github.com. Without it, use `loop new --dry-run` and create the repo yourself.',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
id: 'gh-auth', label: 'gh is signed in', required: false, ok: input.ghAuth.ok, detail: input.ghAuth.ok ? 'signed in' : input.gh.ok ? 'not signed in' : 'skipped (gh missing)',
|
|
29
|
+
fix: input.ghAuth.ok || !input.gh.ok ? '' : 'Run `gh auth login` and choose GitHub.com.',
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
id: 'chromium', label: 'Playwright Chromium, needed by generated sites\' browser tests', required: false, ok: input.chromium !== undefined, detail: input.chromium ?? 'not found',
|
|
33
|
+
fix: input.chromium !== undefined ? '' : 'Run `npx playwright install chromium` (add `npx playwright install-deps chromium` on Linux if Chrome fails to start).',
|
|
34
|
+
},
|
|
35
|
+
];
|
|
36
|
+
}
|
|
37
|
+
export function doctorPassed(checks) {
|
|
38
|
+
return checks.every((c) => c.ok || !c.required);
|
|
39
|
+
}
|
|
40
|
+
export function formatDoctor(checks) {
|
|
41
|
+
const lines = checks.map((c) => {
|
|
42
|
+
const mark = c.ok ? 'ok ' : c.required ? 'MISSING' : 'missing';
|
|
43
|
+
return `${mark} ${c.label}: ${c.detail}${c.fix ? `\n fix: ${c.fix}` : ''}`;
|
|
44
|
+
});
|
|
45
|
+
const bad = checks.filter((c) => !c.ok && c.required).length;
|
|
46
|
+
lines.push('', bad > 0 ? `${bad} required tool(s) missing. Fix them and run \`loop doctor\` again.` : 'Everything required is installed.');
|
|
47
|
+
return lines.join('\n');
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=doctor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/core/doctor.ts"],"names":[],"mappings":"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"}
|
package/dist/core/gh.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gh.js","sourceRoot":"","sources":["../../src/core/gh.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// Planning for `loop init`: decides what to write, without touching the disk.
|
|
2
|
+
import { briefPasses, lintBrief } from './brief.js';
|
|
3
|
+
export const CARD_START = '<!-- compounding-loop:start -->';
|
|
4
|
+
export const CARD_END = '<!-- compounding-loop:end -->';
|
|
5
|
+
const AGENTS_POINTER = '# AGENTS.md\n\nThis repository follows the rules in [CLAUDE.md](CLAUDE.md). Read it first; it applies to any coding agent.\n';
|
|
6
|
+
/** Wraps the card in markers and merges it into an existing CLAUDE.md. Re-running is a no-op. */
|
|
7
|
+
export function mergeCard(existing, card) {
|
|
8
|
+
const block = `${CARD_START}\n${card.trim()}\n${CARD_END}\n`;
|
|
9
|
+
if (existing === undefined || existing.trim() === '')
|
|
10
|
+
return block;
|
|
11
|
+
const start = existing.indexOf(CARD_START);
|
|
12
|
+
const end = existing.indexOf(CARD_END);
|
|
13
|
+
if ((start === -1) !== (end === -1) || (start !== -1 && end < start)) {
|
|
14
|
+
throw new Error(`CLAUDE.md has a broken ${CARD_START} / ${CARD_END} pair: fix or remove the markers, then re-run.`);
|
|
15
|
+
}
|
|
16
|
+
if (start !== -1 && end > start) {
|
|
17
|
+
return existing.slice(0, start) + block + existing.slice(end + CARD_END.length).replace(/^\r?\n/, '');
|
|
18
|
+
}
|
|
19
|
+
return `${existing.replace(/\s*$/, '')}\n\n${block}`;
|
|
20
|
+
}
|
|
21
|
+
/** Returns why a brief blocks `init`, or undefined when it is good enough. */
|
|
22
|
+
export function briefBlocker(brief) {
|
|
23
|
+
if (brief === undefined)
|
|
24
|
+
return 'IDEA.md is missing: write the brief first (or pass --force).';
|
|
25
|
+
const lint = lintBrief(brief);
|
|
26
|
+
if (briefPasses(lint))
|
|
27
|
+
return undefined;
|
|
28
|
+
const gaps = lint.gaps.map((gap) => ` - ${gap.message}`).join('\n');
|
|
29
|
+
return `IDEA.md scores ${lint.score}/100 (needs 60):\n${gaps}`;
|
|
30
|
+
}
|
|
31
|
+
export function planInit({ kit, card, existing, force }) {
|
|
32
|
+
const actions = [];
|
|
33
|
+
for (const file of kit) {
|
|
34
|
+
const current = existing.get(file.dest);
|
|
35
|
+
if (current === undefined)
|
|
36
|
+
actions.push({ dest: file.dest, kind: 'create', content: file.content });
|
|
37
|
+
else if (current === file.content)
|
|
38
|
+
actions.push({ dest: file.dest, kind: 'skip', reason: 'already up to date' });
|
|
39
|
+
else if (force && !file.keep)
|
|
40
|
+
actions.push({ dest: file.dest, kind: 'overwrite', content: file.content });
|
|
41
|
+
else
|
|
42
|
+
actions.push({ dest: file.dest, kind: 'skip', reason: file.keep ? 'loop state, never overwritten' : 'exists (use --force to overwrite)' });
|
|
43
|
+
}
|
|
44
|
+
if (card !== undefined) {
|
|
45
|
+
const current = existing.get('CLAUDE.md');
|
|
46
|
+
const merged = mergeCard(current, card);
|
|
47
|
+
if (merged === current)
|
|
48
|
+
actions.push({ dest: 'CLAUDE.md', kind: 'skip', reason: 'Operating Card already installed' });
|
|
49
|
+
else
|
|
50
|
+
actions.push({ dest: 'CLAUDE.md', kind: current === undefined ? 'create' : 'update', content: merged });
|
|
51
|
+
}
|
|
52
|
+
const agents = existing.get('AGENTS.md');
|
|
53
|
+
if (agents === undefined)
|
|
54
|
+
actions.push({ dest: 'AGENTS.md', kind: 'create', content: AGENTS_POINTER });
|
|
55
|
+
else
|
|
56
|
+
actions.push({ dest: 'AGENTS.md', kind: 'skip', reason: 'exists' });
|
|
57
|
+
return actions;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/core/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// Pure derivation of one lane's state from the files and commits around it.
|
|
2
|
+
import { LOCK_MINUTES } from './status.js';
|
|
3
|
+
/** A lane with neither a commit nor a lock for this long is stalled (same rule as the dashboard's health check). */
|
|
4
|
+
export const STALL_MINUTES = 120;
|
|
5
|
+
/** Rough minutes between runs of a 5-field cron expression; undefined when it cannot be read. */
|
|
6
|
+
export function cronPeriodMinutes(cron) {
|
|
7
|
+
const fields = cron.trim().split(/\s+/);
|
|
8
|
+
if (fields.length !== 5)
|
|
9
|
+
return undefined;
|
|
10
|
+
const [minute, hour, , , weekday] = fields;
|
|
11
|
+
const step = (field) => /^\*\/(\d+)$/.exec(field)?.[1];
|
|
12
|
+
const count = (field) => field.split(',').length;
|
|
13
|
+
const minuteStep = step(minute);
|
|
14
|
+
if (minuteStep)
|
|
15
|
+
return Number(minuteStep) || undefined;
|
|
16
|
+
if (minute === '*')
|
|
17
|
+
return 1;
|
|
18
|
+
const hourStep = step(hour);
|
|
19
|
+
if (hourStep)
|
|
20
|
+
return Number(hourStep) * 60 || undefined;
|
|
21
|
+
if (hour === '*')
|
|
22
|
+
return 60;
|
|
23
|
+
const perDay = 1440 / count(hour);
|
|
24
|
+
return weekday === '*' ? perDay : 10_080 / count(weekday) / count(hour);
|
|
25
|
+
}
|
|
26
|
+
/** A lane is stalled after missing two scheduled runs; `STALL_MINUTES` when it has no readable cron. */
|
|
27
|
+
export function stallMinutesFor(cron) {
|
|
28
|
+
const period = cron === undefined ? undefined : cronPeriodMinutes(cron);
|
|
29
|
+
return period === undefined ? STALL_MINUTES : period * 2;
|
|
30
|
+
}
|
|
31
|
+
const minutesSince = (now, then) => (now.getTime() - then.getTime()) / 60_000;
|
|
32
|
+
export function deriveLaneState(facts, now = new Date()) {
|
|
33
|
+
if (facts.hasBlocked)
|
|
34
|
+
return 'blocked';
|
|
35
|
+
if (facts.hasDone)
|
|
36
|
+
return 'done';
|
|
37
|
+
if (facts.lockAt && minutesSince(now, facts.lockAt) < LOCK_MINUTES)
|
|
38
|
+
return 'building';
|
|
39
|
+
const latest = [facts.lockAt, facts.lastCommitAt].filter((d) => d !== undefined).map((d) => d.getTime());
|
|
40
|
+
if (latest.length > 0 && minutesSince(now, new Date(Math.max(...latest))) > (facts.stallMinutes ?? STALL_MINUTES))
|
|
41
|
+
return 'stalled';
|
|
42
|
+
return 'waiting';
|
|
43
|
+
}
|
|
44
|
+
const OUTBOX_LINE = /^(\d{4}-\d\d-\d\d) (\d\d:\d\d) UTC · to ([^·]+?) · (.+)$/;
|
|
45
|
+
/** Parses `YYYY-MM-DD HH:MM UTC · to <lane|a, b|all> · message` lines; other lines are ignored. */
|
|
46
|
+
export function parseOutbox(from, text) {
|
|
47
|
+
const messages = [];
|
|
48
|
+
for (const line of text.split(/\r?\n/)) {
|
|
49
|
+
const m = OUTBOX_LINE.exec(line.trim());
|
|
50
|
+
if (!m)
|
|
51
|
+
continue;
|
|
52
|
+
const [, date, time, to, body] = m;
|
|
53
|
+
messages.push({ from, to: to.split(/\s*,\s*|\s+and\s+/).map((t) => t.trim().toLowerCase()).filter(Boolean), at: `${date}T${time}:00.000Z`, text: body.trim() });
|
|
54
|
+
}
|
|
55
|
+
return messages;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* A message to a named lane counts as unanswered until that lane writes any later outbox entry.
|
|
59
|
+
* A later commit by that lane (`lastCommitAt`, ISO) also counts as a reply, since a lane often answers by shipping.
|
|
60
|
+
* This is a heuristic, so it only ever informs; it never fails anything.
|
|
61
|
+
*/
|
|
62
|
+
export function summarizeOutboxes(outboxes, lastCommitAt = new Map()) {
|
|
63
|
+
const lastWrite = new Map();
|
|
64
|
+
for (const [lane, messages] of outboxes)
|
|
65
|
+
lastWrite.set(lane, [...messages.map((m) => m.at), lastCommitAt.get(lane) ?? ''].sort().at(-1) ?? '');
|
|
66
|
+
const unanswered = new Map();
|
|
67
|
+
const waitingOn = new Map();
|
|
68
|
+
for (const [from, messages] of outboxes) {
|
|
69
|
+
for (const message of messages) {
|
|
70
|
+
for (const to of new Set(message.to)) {
|
|
71
|
+
if (to === 'all' || to === from || !outboxes.has(to))
|
|
72
|
+
continue;
|
|
73
|
+
if ((lastWrite.get(to) ?? '') >= message.at)
|
|
74
|
+
continue;
|
|
75
|
+
unanswered.set(to, [...(unanswered.get(to) ?? []), { from, to, at: message.at, text: message.text }]);
|
|
76
|
+
waitingOn.set(from, [...new Set([...(waitingOn.get(from) ?? []), to])]);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return { unanswered, waitingOn };
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=laneStatus.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"laneStatus.js","sourceRoot":"","sources":["../../src/core/laneStatus.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
// Lane config: who owns which paths. Pure (no Node imports) so the dashboard can reuse it.
|
|
2
|
+
/** The supervising routine's commit trailer; it may touch anything. */
|
|
3
|
+
export const CONTROL_LANE = 'control';
|
|
4
|
+
const LANE_NAME = /^[a-z][a-z0-9-]{0,30}$/;
|
|
5
|
+
export function isValidLaneName(name) {
|
|
6
|
+
return LANE_NAME.test(name) && name !== CONTROL_LANE;
|
|
7
|
+
}
|
|
8
|
+
/** Backslashes to slashes, no leading `./` or `/`, so Windows-style paths match POSIX globs. */
|
|
9
|
+
export function normalizePath(file) {
|
|
10
|
+
return file.replace(/\\/g, '/').replace(/^(?:\.?\/)+/, '');
|
|
11
|
+
}
|
|
12
|
+
const REGEX_SPECIAL = /[.+^${}()|[\]\\]/g;
|
|
13
|
+
/** Compiles `**` (any depth), `*` (one segment), `?` (one character) and literals to an anchored regex. */
|
|
14
|
+
function globToRegExp(glob) {
|
|
15
|
+
const g = normalizePath(glob);
|
|
16
|
+
let out = '';
|
|
17
|
+
for (let i = 0; i < g.length; i++) {
|
|
18
|
+
const c = g[i];
|
|
19
|
+
if (c === '*' && g[i + 1] === '*') {
|
|
20
|
+
const slashAfter = g[i + 2] === '/';
|
|
21
|
+
out += slashAfter ? '(?:.*/)?' : '.*';
|
|
22
|
+
i += slashAfter ? 2 : 1;
|
|
23
|
+
}
|
|
24
|
+
else if (c === '*')
|
|
25
|
+
out += '[^/]*';
|
|
26
|
+
else if (c === '?')
|
|
27
|
+
out += '[^/]';
|
|
28
|
+
else
|
|
29
|
+
out += c.replace(REGEX_SPECIAL, '\\$&');
|
|
30
|
+
}
|
|
31
|
+
return new RegExp(`^${out}$`);
|
|
32
|
+
}
|
|
33
|
+
export function matchGlob(glob, file) {
|
|
34
|
+
return globToRegExp(glob).test(normalizePath(file));
|
|
35
|
+
}
|
|
36
|
+
function matchesAny(globs, file) {
|
|
37
|
+
return globs.some((glob) => matchGlob(glob, file));
|
|
38
|
+
}
|
|
39
|
+
/** A concrete path the glob matches, used to detect two globs claiming the same files. */
|
|
40
|
+
function sampleFor(glob) {
|
|
41
|
+
return normalizePath(glob).replace(/\*\*\/?/g, 'x/').replace(/\/$/, '').replace(/[*?]/g, 'x');
|
|
42
|
+
}
|
|
43
|
+
function globsOverlap(a, b) {
|
|
44
|
+
return matchGlob(a, sampleFor(b)) || matchGlob(b, sampleFor(a));
|
|
45
|
+
}
|
|
46
|
+
function stringArray(value) {
|
|
47
|
+
return Array.isArray(value) && value.every((v) => typeof v === 'string' && v.trim() !== '') ? value : undefined;
|
|
48
|
+
}
|
|
49
|
+
/** Validates an already-parsed JSON value. Returns every problem found, not just the first. */
|
|
50
|
+
export function validateLanesConfig(raw) {
|
|
51
|
+
const errors = [];
|
|
52
|
+
if (typeof raw !== 'object' || raw === null || Array.isArray(raw))
|
|
53
|
+
return { errors: ['.ai/lanes.json must be an object with "lanes" and "shared".'] };
|
|
54
|
+
const obj = raw;
|
|
55
|
+
if (!Array.isArray(obj.lanes) || obj.lanes.length === 0)
|
|
56
|
+
return { errors: ['.ai/lanes.json needs at least one lane in "lanes".'] };
|
|
57
|
+
const lanes = [];
|
|
58
|
+
obj.lanes.forEach((item, index) => {
|
|
59
|
+
const at = `lanes[${index}]`;
|
|
60
|
+
if (typeof item !== 'object' || item === null)
|
|
61
|
+
return void errors.push(`${at} must be an object.`);
|
|
62
|
+
const entry = item;
|
|
63
|
+
const name = typeof entry.name === 'string' ? entry.name : '';
|
|
64
|
+
if (!isValidLaneName(name))
|
|
65
|
+
errors.push(`${at}: name "${name}" is invalid. Use lowercase letters, digits and dashes, starting with a letter ("${CONTROL_LANE}" is reserved).`);
|
|
66
|
+
else if (lanes.some((l) => l.name === name))
|
|
67
|
+
errors.push(`${at}: lane "${name}" is listed twice.`);
|
|
68
|
+
const owns = stringArray(entry.owns);
|
|
69
|
+
if (!owns || owns.length === 0)
|
|
70
|
+
errors.push(`${at} (${name || '?'}): "owns" must be a non-empty list of globs.`);
|
|
71
|
+
if (entry.cron !== undefined && typeof entry.cron !== 'string')
|
|
72
|
+
errors.push(`${at} (${name || '?'}): "cron" must be a string.`);
|
|
73
|
+
if (name && owns)
|
|
74
|
+
lanes.push({ name, owns, ...(typeof entry.cron === 'string' ? { cron: entry.cron } : {}) });
|
|
75
|
+
});
|
|
76
|
+
const shared = obj.shared === undefined ? [] : stringArray(obj.shared);
|
|
77
|
+
if (!shared)
|
|
78
|
+
errors.push('"shared" must be a list of globs.');
|
|
79
|
+
for (let i = 0; i < lanes.length; i++) {
|
|
80
|
+
for (let j = i + 1; j < lanes.length; j++) {
|
|
81
|
+
for (const a of lanes[i].owns) {
|
|
82
|
+
for (const b of lanes[j].owns) {
|
|
83
|
+
if (globsOverlap(a, b))
|
|
84
|
+
errors.push(`Lanes "${lanes[i].name}" and "${lanes[j].name}" both own files matching "${a}" / "${b}". Make the globs disjoint or move the path to "shared".`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return errors.length > 0 || !shared ? { errors } : { config: { lanes, shared }, errors };
|
|
90
|
+
}
|
|
91
|
+
export function parseLanesConfig(text) {
|
|
92
|
+
try {
|
|
93
|
+
return validateLanesConfig(JSON.parse(text));
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
return { errors: ['.ai/lanes.json is not valid JSON.'] };
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/** The lane that owns the file, "shared" for a shared path, or undefined when nobody does. */
|
|
100
|
+
export function laneForPath(config, file) {
|
|
101
|
+
const lane = config.lanes.find((l) => matchesAny(l.owns, file) || matchGlob(`.ai/lanes/${l.name}/**`, file));
|
|
102
|
+
if (lane)
|
|
103
|
+
return lane.name;
|
|
104
|
+
return matchesAny(config.shared, file) ? 'shared' : undefined;
|
|
105
|
+
}
|
|
106
|
+
/** Reads the last `Lane: <name>` line of a commit message (it may be followed by other trailers); undefined when there is none. */
|
|
107
|
+
export function parseLaneTrailer(message) {
|
|
108
|
+
const lines = message.trimEnd().split(/\r?\n/);
|
|
109
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
110
|
+
const line = lines[i].trim();
|
|
111
|
+
const match = /^lane:\s*(\S+)$/i.exec(line);
|
|
112
|
+
if (match)
|
|
113
|
+
return match[1].toLowerCase();
|
|
114
|
+
}
|
|
115
|
+
return undefined;
|
|
116
|
+
}
|
|
117
|
+
/** Files a commit with the given `Lane:` trailer may not touch, each with a fix-it message. */
|
|
118
|
+
export function checkCommitFiles(config, lane, files) {
|
|
119
|
+
if (lane === CONTROL_LANE)
|
|
120
|
+
return [];
|
|
121
|
+
const self = config.lanes.find((l) => l.name === lane);
|
|
122
|
+
if (!self) {
|
|
123
|
+
const known = config.lanes.map((l) => l.name).join(', ');
|
|
124
|
+
return [{ file: '(trailer)', message: `unknown lane "${lane}". Use one of: ${known}, or fix the trailer.` }];
|
|
125
|
+
}
|
|
126
|
+
const violations = [];
|
|
127
|
+
for (const file of files) {
|
|
128
|
+
const owner = laneForPath(config, file);
|
|
129
|
+
// A path listed in "shared" is open to every lane even when an "owns" glob also covers it (e.g. src/core/types.ts).
|
|
130
|
+
if (owner === self.name || owner === 'shared' || matchesAny(config.shared, file))
|
|
131
|
+
continue;
|
|
132
|
+
const fix = owner
|
|
133
|
+
? `it belongs to lane "${owner}". Ask that lane through your outbox (.ai/lanes/${self.name}/outbox.md) instead of editing it.`
|
|
134
|
+
: `no lane owns it. Add it to a lane's "owns" or to "shared" in .ai/lanes.json.`;
|
|
135
|
+
violations.push({ file: normalizePath(file), message: `lane "${self.name}" touched ${normalizePath(file)}, but ${fix}` });
|
|
136
|
+
}
|
|
137
|
+
return violations;
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=lanes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lanes.js","sourceRoot":"","sources":["../../src/core/lanes.ts"],"names":[],"mappings":"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"}
|