@protoboxai/codeloop 0.3.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 +589 -0
- package/dist/commands/adopt.d.ts +2 -0
- package/dist/commands/adopt.js +26 -0
- package/dist/commands/adopt.js.map +1 -0
- package/dist/commands/brief.d.ts +2 -0
- package/dist/commands/brief.js +22 -0
- package/dist/commands/brief.js.map +1 -0
- package/dist/commands/card.d.ts +6 -0
- package/dist/commands/card.js +159 -0
- package/dist/commands/card.js.map +1 -0
- package/dist/commands/check.d.ts +4 -0
- package/dist/commands/check.js +76 -0
- package/dist/commands/check.js.map +1 -0
- package/dist/commands/cloud.d.ts +8 -0
- package/dist/commands/cloud.js +123 -0
- package/dist/commands/cloud.js.map +1 -0
- package/dist/commands/guard.d.ts +2 -0
- package/dist/commands/guard.js +26 -0
- package/dist/commands/guard.js.map +1 -0
- package/dist/commands/import.d.ts +2 -0
- package/dist/commands/import.js +24 -0
- package/dist/commands/import.js.map +1 -0
- package/dist/commands/inbox.d.ts +2 -0
- package/dist/commands/inbox.js +48 -0
- package/dist/commands/inbox.js.map +1 -0
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.js +142 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/install.d.ts +2 -0
- package/dist/commands/install.js +125 -0
- package/dist/commands/install.js.map +1 -0
- package/dist/commands/lane.d.ts +2 -0
- package/dist/commands/lane.js +100 -0
- package/dist/commands/lane.js.map +1 -0
- package/dist/commands/list.d.ts +2 -0
- package/dist/commands/list.js +35 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/login.d.ts +2 -0
- package/dist/commands/login.js +77 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/mock.d.ts +3 -0
- package/dist/commands/mock.js +22 -0
- package/dist/commands/mock.js.map +1 -0
- package/dist/commands/pack.d.ts +2 -0
- package/dist/commands/pack.js +19 -0
- package/dist/commands/pack.js.map +1 -0
- package/dist/commands/publish.d.ts +2 -0
- package/dist/commands/publish.js +125 -0
- package/dist/commands/publish.js.map +1 -0
- package/dist/commands/remove.d.ts +2 -0
- package/dist/commands/remove.js +31 -0
- package/dist/commands/remove.js.map +1 -0
- package/dist/commands/render.d.ts +5 -0
- package/dist/commands/render.js +47 -0
- package/dist/commands/render.js.map +1 -0
- package/dist/commands/run.d.ts +2 -0
- package/dist/commands/run.js +45 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/commands/scan.d.ts +2 -0
- package/dist/commands/scan.js +26 -0
- package/dist/commands/scan.js.map +1 -0
- package/dist/commands/schedule.d.ts +2 -0
- package/dist/commands/schedule.js +51 -0
- package/dist/commands/schedule.js.map +1 -0
- package/dist/commands/search.d.ts +2 -0
- package/dist/commands/search.js +85 -0
- package/dist/commands/search.js.map +1 -0
- package/dist/commands/serve.d.ts +7 -0
- package/dist/commands/serve.js +126 -0
- package/dist/commands/serve.js.map +1 -0
- package/dist/commands/spec.d.ts +3 -0
- package/dist/commands/spec.js +64 -0
- package/dist/commands/spec.js.map +1 -0
- package/dist/commands/status.d.ts +3 -0
- package/dist/commands/status.js +251 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/update.d.ts +2 -0
- package/dist/commands/update.js +83 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/verify.d.ts +3 -0
- package/dist/commands/verify.js +75 -0
- package/dist/commands/verify.js.map +1 -0
- package/dist/commands/watch.d.ts +6 -0
- package/dist/commands/watch.js +111 -0
- package/dist/commands/watch.js.map +1 -0
- package/dist/commands/wiki.d.ts +3 -0
- package/dist/commands/wiki.js +85 -0
- package/dist/commands/wiki.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +86 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/agent.d.ts +27 -0
- package/dist/lib/agent.js +178 -0
- package/dist/lib/agent.js.map +1 -0
- package/dist/lib/board.d.ts +38 -0
- package/dist/lib/board.js +86 -0
- package/dist/lib/board.js.map +1 -0
- package/dist/lib/cards.d.ts +82 -0
- package/dist/lib/cards.js +107 -0
- package/dist/lib/cards.js.map +1 -0
- package/dist/lib/clock.d.ts +5 -0
- package/dist/lib/clock.js +14 -0
- package/dist/lib/clock.js.map +1 -0
- package/dist/lib/cloud.d.ts +122 -0
- package/dist/lib/cloud.js +580 -0
- package/dist/lib/cloud.js.map +1 -0
- package/dist/lib/competitors.d.ts +28 -0
- package/dist/lib/competitors.js +90 -0
- package/dist/lib/competitors.js.map +1 -0
- package/dist/lib/config.d.ts +7 -0
- package/dist/lib/config.js +25 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/cron.d.ts +5 -0
- package/dist/lib/cron.js +82 -0
- package/dist/lib/cron.js.map +1 -0
- package/dist/lib/detect.d.ts +13 -0
- package/dist/lib/detect.js +60 -0
- package/dist/lib/detect.js.map +1 -0
- package/dist/lib/engine.d.ts +88 -0
- package/dist/lib/engine.js +435 -0
- package/dist/lib/engine.js.map +1 -0
- package/dist/lib/flow.d.ts +44 -0
- package/dist/lib/flow.js +121 -0
- package/dist/lib/flow.js.map +1 -0
- package/dist/lib/glob.d.ts +2 -0
- package/dist/lib/glob.js +10 -0
- package/dist/lib/glob.js.map +1 -0
- package/dist/lib/import.d.ts +13 -0
- package/dist/lib/import.js +127 -0
- package/dist/lib/import.js.map +1 -0
- package/dist/lib/inbox.d.ts +42 -0
- package/dist/lib/inbox.js +65 -0
- package/dist/lib/inbox.js.map +1 -0
- package/dist/lib/lane.d.ts +71 -0
- package/dist/lib/lane.js +105 -0
- package/dist/lib/lane.js.map +1 -0
- package/dist/lib/lock.d.ts +6 -0
- package/dist/lib/lock.js +64 -0
- package/dist/lib/lock.js.map +1 -0
- package/dist/lib/mcp.d.ts +2 -0
- package/dist/lib/mcp.js +57 -0
- package/dist/lib/mcp.js.map +1 -0
- package/dist/lib/mock.d.ts +17 -0
- package/dist/lib/mock.js +137 -0
- package/dist/lib/mock.js.map +1 -0
- package/dist/lib/pack.d.ts +24 -0
- package/dist/lib/pack.js +77 -0
- package/dist/lib/pack.js.map +1 -0
- package/dist/lib/proposals.d.ts +48 -0
- package/dist/lib/proposals.js +240 -0
- package/dist/lib/proposals.js.map +1 -0
- package/dist/lib/render.d.ts +7 -0
- package/dist/lib/render.js +84 -0
- package/dist/lib/render.js.map +1 -0
- package/dist/lib/research.d.ts +8 -0
- package/dist/lib/research.js +39 -0
- package/dist/lib/research.js.map +1 -0
- package/dist/lib/run.d.ts +38 -0
- package/dist/lib/run.js +215 -0
- package/dist/lib/run.js.map +1 -0
- package/dist/lib/scaffold.d.ts +16 -0
- package/dist/lib/scaffold.js +175 -0
- package/dist/lib/scaffold.js.map +1 -0
- package/dist/lib/scan.d.ts +22 -0
- package/dist/lib/scan.js +85 -0
- package/dist/lib/scan.js.map +1 -0
- package/dist/lib/schedule.d.ts +20 -0
- package/dist/lib/schedule.js +66 -0
- package/dist/lib/schedule.js.map +1 -0
- package/dist/lib/server.d.ts +68 -0
- package/dist/lib/server.js +235 -0
- package/dist/lib/server.js.map +1 -0
- package/dist/lib/shell.d.ts +1 -0
- package/dist/lib/shell.js +25 -0
- package/dist/lib/shell.js.map +1 -0
- package/dist/lib/skills.d.ts +20 -0
- package/dist/lib/skills.js +92 -0
- package/dist/lib/skills.js.map +1 -0
- package/dist/lib/spec.d.ts +24 -0
- package/dist/lib/spec.js +102 -0
- package/dist/lib/spec.js.map +1 -0
- package/dist/lib/stats.d.ts +13 -0
- package/dist/lib/stats.js +43 -0
- package/dist/lib/stats.js.map +1 -0
- package/dist/lib/verify.d.ts +25 -0
- package/dist/lib/verify.js +135 -0
- package/dist/lib/verify.js.map +1 -0
- package/dist/lib/version.d.ts +10 -0
- package/dist/lib/version.js +27 -0
- package/dist/lib/version.js.map +1 -0
- package/dist/lib/wiki.d.ts +51 -0
- package/dist/lib/wiki.js +164 -0
- package/dist/lib/wiki.js.map +1 -0
- package/dist/registry/index.d.ts +7 -0
- package/dist/registry/index.js +8 -0
- package/dist/registry/index.js.map +1 -0
- package/dist/registry/installer.d.ts +30 -0
- package/dist/registry/installer.js +133 -0
- package/dist/registry/installer.js.map +1 -0
- package/dist/registry/local-index.d.ts +32 -0
- package/dist/registry/local-index.js +58 -0
- package/dist/registry/local-index.js.map +1 -0
- package/dist/registry/lockfile.d.ts +40 -0
- package/dist/registry/lockfile.js +85 -0
- package/dist/registry/lockfile.js.map +1 -0
- package/dist/registry/security.d.ts +25 -0
- package/dist/registry/security.js +100 -0
- package/dist/registry/security.js.map +1 -0
- package/dist/registry/skill-schema.d.ts +30 -0
- package/dist/registry/skill-schema.js +95 -0
- package/dist/registry/skill-schema.js.map +1 -0
- package/dist/ui/404.html +1 -0
- package/dist/ui/_next/static/6wzGE5sCtbYkSyhMWxL32/_buildManifest.js +1 -0
- package/dist/ui/_next/static/6wzGE5sCtbYkSyhMWxL32/_ssgManifest.js +1 -0
- package/dist/ui/_next/static/chunks/255-54d3085ce94738a4.js +1 -0
- package/dist/ui/_next/static/chunks/423-bb541b7ae2733575.js +1 -0
- package/dist/ui/_next/static/chunks/4bd1b696-c023c6e3521b1417.js +1 -0
- package/dist/ui/_next/static/chunks/app/_not-found/page-d6bc774f7acb716e.js +1 -0
- package/dist/ui/_next/static/chunks/app/layout-e5fc8e78e1c8da95.js +1 -0
- package/dist/ui/_next/static/chunks/app/page-0c34b6e119cef236.js +1 -0
- package/dist/ui/_next/static/chunks/framework-de98b93a850cfc71.js +1 -0
- package/dist/ui/_next/static/chunks/main-49fd204fc9037ea3.js +1 -0
- package/dist/ui/_next/static/chunks/main-app-c46afa2f48f3aaef.js +1 -0
- package/dist/ui/_next/static/chunks/pages/_app-7d307437aca18ad4.js +1 -0
- package/dist/ui/_next/static/chunks/pages/_error-cb2a52f75f2162e2.js +1 -0
- package/dist/ui/_next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
- package/dist/ui/_next/static/chunks/webpack-4a462cecab786e93.js +1 -0
- package/dist/ui/_next/static/css/1bf01240dbfd6088.css +1 -0
- package/dist/ui/index.html +1 -0
- package/dist/ui/index.txt +19 -0
- package/dist/watch/index.d.ts +21 -0
- package/dist/watch/index.js +88 -0
- package/dist/watch/index.js.map +1 -0
- package/dist/watch/reporter.d.ts +11 -0
- package/dist/watch/reporter.js +44 -0
- package/dist/watch/reporter.js.map +1 -0
- package/dist/watch/signals.d.ts +38 -0
- package/dist/watch/signals.js +119 -0
- package/dist/watch/signals.js.map +1 -0
- package/dist/watch/triggers.d.ts +10 -0
- package/dist/watch/triggers.js +67 -0
- package/dist/watch/triggers.js.map +1 -0
- package/package.json +64 -0
- package/registry/index.json +106 -0
- package/starters/generic.yaml +95 -0
- package/starters/go.yaml +99 -0
- package/starters/node-typescript.yaml +108 -0
- package/starters/python.yaml +105 -0
- package/templates/ci/codeloop-pr.yml +29 -0
- package/templates/ci/codeloop-prod.yml +27 -0
- package/templates/ci/codeloop-staging.yml +34 -0
- package/templates/codeloop/board.json +5 -0
- package/templates/codeloop/gotchas.md +13 -0
- package/templates/codeloop/patterns.md +15 -0
- package/templates/codeloop/principles.md +49 -0
- package/templates/codeloop/rules.md +23 -0
- package/templates/commands/commit.md +255 -0
- package/templates/commands/debug.md +142 -0
- package/templates/commands/deploy.md +144 -0
- package/templates/commands/design.md +102 -0
- package/templates/commands/manage.md +77 -0
- package/templates/commands/plan.md +84 -0
- package/templates/commands/qa.md +155 -0
- package/templates/commands/reflect.md +93 -0
- package/templates/commands/ship.md +187 -0
- package/templates/commands/test.md +133 -0
- package/templates/hooks/commit-msg +8 -0
- package/templates/lanes/analyze.yaml +25 -0
- package/templates/lanes/build.yaml +45 -0
- package/templates/lanes/deploy.yaml +24 -0
- package/templates/lanes/learn.yaml +20 -0
- package/templates/lanes/market.yaml +25 -0
- package/templates/lanes/plan.yaml +24 -0
- package/templates/lanes/scan.yaml +11 -0
- package/templates/lanes/triage.yaml +24 -0
- package/templates/mock/template.html +82 -0
- package/templates/seeds/go-gotchas.md +28 -0
- package/templates/seeds/go-patterns.md +22 -0
- package/templates/seeds/node-typescript-gotchas.md +30 -0
- package/templates/seeds/node-typescript-patterns.md +27 -0
- package/templates/seeds/python-gotchas.md +30 -0
- package/templates/seeds/python-patterns.md +19 -0
- package/templates/seeds/universal-gotchas.md +11 -0
- package/templates/seeds/universal-patterns.md +11 -0
- package/templates/spec/plan.md +7 -0
- package/templates/spec/research.md +19 -0
- package/templates/spec/spec.md +14 -0
- package/templates/spec/tasks.md +10 -0
- package/templates/tasks/todo.md +3 -0
|
@@ -0,0 +1,435 @@
|
|
|
1
|
+
import { spawnSync } from 'child_process';
|
|
2
|
+
import { checkEnv } from './shell.js';
|
|
3
|
+
import { existsSync, readFileSync, statSync } from 'fs';
|
|
4
|
+
import { join } from 'path';
|
|
5
|
+
import { createHash } from 'crypto';
|
|
6
|
+
import { appendFindings } from './competitors.js';
|
|
7
|
+
import { clock } from './clock.js';
|
|
8
|
+
import { loadConfig } from './config.js';
|
|
9
|
+
import { CARD_ID, ConflictError, DONE, DROPPED, findCard, inLane, nextCardId, PROPOSAL_GATE, PROPOSED, readCards, RefusalError, writeCards } from './cards.js';
|
|
10
|
+
export { RefusalError };
|
|
11
|
+
import { loadLane, loadLanes, substitute } from './lane.js';
|
|
12
|
+
export function loadEngineConfig(projectDir) {
|
|
13
|
+
const raw = loadConfig(projectDir);
|
|
14
|
+
return {
|
|
15
|
+
gatesMode: raw.gates?.mode === 'trusted' ? 'trusted' : 'all',
|
|
16
|
+
gatesPerDay: raw.capacity?.gates_per_day,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* `--as`, then CODELOOP_ROLE, then the terminal: a person typing at a TTY is the owner, anything
|
|
21
|
+
* piped or spawned (an agent, CI, the MCP server) is an agent.
|
|
22
|
+
*/
|
|
23
|
+
export function resolveRole(flag, tty = Boolean(process.stdin.isTTY)) {
|
|
24
|
+
const role = flag ?? process.env.CODELOOP_ROLE ?? (tty ? 'owner' : 'agent');
|
|
25
|
+
if (role !== 'owner' && role !== 'reviewer' && role !== 'agent') {
|
|
26
|
+
throw new RefusalError(`unknown role "${role}" (owner, reviewer or agent)`);
|
|
27
|
+
}
|
|
28
|
+
// Set by `codeloop run --agent` on the process it starts, so `--as owner` typed by that agent is refused.
|
|
29
|
+
if (process.env.CODELOOP_AGENT_RUN && role !== 'agent') {
|
|
30
|
+
throw new RefusalError(`this process was started by \`codeloop run --agent\` and acts as agent; it cannot act as ${role}`);
|
|
31
|
+
}
|
|
32
|
+
return role;
|
|
33
|
+
}
|
|
34
|
+
function event(now, role, action, stage, note) {
|
|
35
|
+
return {
|
|
36
|
+
at: now.toISOString(),
|
|
37
|
+
actor: role,
|
|
38
|
+
human: role === 'owner' || role === 'reviewer',
|
|
39
|
+
action,
|
|
40
|
+
...(stage ? { stage } : {}),
|
|
41
|
+
...(note ? { note } : {}),
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* HEAD, the list of changed files, the tracked changes themselves, and size and mtime of untracked
|
|
46
|
+
* files. `.codeloop/` is left out: the engine writes there on every attempt. null outside a git repo.
|
|
47
|
+
*/
|
|
48
|
+
function treeState(projectDir) {
|
|
49
|
+
const git = (args) => spawnSync('git', [...args, '--', '.', ':(exclude).codeloop'], { cwd: projectDir, encoding: 'utf-8' });
|
|
50
|
+
const status = git(['status', '--porcelain']);
|
|
51
|
+
if (status.status !== 0)
|
|
52
|
+
return null;
|
|
53
|
+
const untracked = git(['ls-files', '--others', '--exclude-standard']).stdout.split('\n').filter(Boolean).map(f => {
|
|
54
|
+
const s = statSync(join(projectDir, f), { throwIfNoEntry: false });
|
|
55
|
+
return `${f} ${s?.size} ${s?.mtimeMs}`;
|
|
56
|
+
});
|
|
57
|
+
const head = spawnSync('git', ['rev-parse', 'HEAD'], { cwd: projectDir, encoding: 'utf-8' }).stdout;
|
|
58
|
+
return [head, status.stdout, git(['diff', 'HEAD']).stdout, ...untracked].join('\n');
|
|
59
|
+
}
|
|
60
|
+
function tail(text) {
|
|
61
|
+
return text.trimEnd().split('\n').slice(-20).join('\n').slice(-2000);
|
|
62
|
+
}
|
|
63
|
+
function currentStage(lane, card) {
|
|
64
|
+
const stage = lane.stages.find(s => s.id === card.stage);
|
|
65
|
+
if (!stage)
|
|
66
|
+
throw new RefusalError(`card ${card.id} is at stage "${card.stage}", which lane ${lane.id} v${lane.version} does not have`);
|
|
67
|
+
return stage;
|
|
68
|
+
}
|
|
69
|
+
const DECISIONS = ['approve', 'auto-approve', 'reject', 'park'];
|
|
70
|
+
// The latest gate event for the stage decides: a park or a rejection after an approval withdraws it.
|
|
71
|
+
function approval(card, stage) {
|
|
72
|
+
const last = card.events.filter(e => e.stage === stage.id && DECISIONS.includes(e.action)).at(-1);
|
|
73
|
+
return last && (last.action === 'approve' || last.action === 'auto-approve') ? last : undefined;
|
|
74
|
+
}
|
|
75
|
+
const approved = (card, stage) => approval(card, stage) !== undefined;
|
|
76
|
+
/** True for a public step nobody has approved yet: no work and no check may run for it. */
|
|
77
|
+
export const awaitsApproval = (card, stage) => !!stage.gate?.outward && !approved(card, stage);
|
|
78
|
+
/** Runs the stage's done command without touching the card. null when the stage has no command. */
|
|
79
|
+
export function runCheck(projectDir, card, stage) {
|
|
80
|
+
if (!stage.done?.cmd)
|
|
81
|
+
return null;
|
|
82
|
+
const run = spawnSync(substitute(stage.done.cmd, card, { shell: true }), { cwd: projectDir, shell: true, encoding: 'utf-8', timeout: 600_000, env: checkEnv() });
|
|
83
|
+
return { passed: run.status === 0, output: tail(`${run.stdout ?? ''}${run.stderr ?? ''}`) };
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* What an approval is bound to: the check's text and the stage's output file. A public step is
|
|
87
|
+
* approved before its work exists, so only its check is bound.
|
|
88
|
+
*/
|
|
89
|
+
function stageFingerprint(projectDir, card, stage) {
|
|
90
|
+
const hash = createHash('sha1').update(stage.done?.cmd ?? stage.done?.event ?? '');
|
|
91
|
+
const output = !stage.gate?.outward && stage.output ? join(projectDir, substitute(stage.output, card)) : null;
|
|
92
|
+
if (output)
|
|
93
|
+
hash.update('\0').update(existsSync(output) && statSync(output).isFile() ? readFileSync(output) : 'missing');
|
|
94
|
+
return hash.digest('hex');
|
|
95
|
+
}
|
|
96
|
+
// What a research stage found about a competitor is copied to that competitor's wiki page, so the
|
|
97
|
+
// next card's research starts from it. Returns the pages that gained rows.
|
|
98
|
+
function researchFindings(projectDir, card, stage) {
|
|
99
|
+
if (stage.id !== 'research' || !stage.output)
|
|
100
|
+
return [];
|
|
101
|
+
const file = join(projectDir, substitute(stage.output, card));
|
|
102
|
+
return existsSync(file) && statSync(file).isFile() ? appendFindings(projectDir, card, readFileSync(file, 'utf-8')) : [];
|
|
103
|
+
}
|
|
104
|
+
function park(card, stage, now, when) {
|
|
105
|
+
card.gate = stage.gate.name;
|
|
106
|
+
card.awaiting = stage.gate.approver;
|
|
107
|
+
card.events.push(event(now, 'engine', 'park', stage.id, `gate ${stage.gate.name} (${when})`));
|
|
108
|
+
}
|
|
109
|
+
// An outward stage changes something public, so its gate is asked on entry, before any work or check runs.
|
|
110
|
+
function parkIfOutward(card, lane, now) {
|
|
111
|
+
const stage = lane.stages.find(s => s.id === card.stage);
|
|
112
|
+
if (stage && awaitsApproval(card, stage))
|
|
113
|
+
park(card, stage, now, 'before the stage runs');
|
|
114
|
+
}
|
|
115
|
+
function replace(cards, card) {
|
|
116
|
+
return cards.map(c => (c.id === card.id ? card : c));
|
|
117
|
+
}
|
|
118
|
+
function newCard(cards, lane, title, id, now, actor, note) {
|
|
119
|
+
if (lane.stages.length === 0)
|
|
120
|
+
throw new RefusalError(`lane ${lane.id} has no stages`);
|
|
121
|
+
// The id is substituted into shell commands and used in folder names, so its shape is fixed.
|
|
122
|
+
if (!CARD_ID.test(id))
|
|
123
|
+
throw new RefusalError(`card id "${id}" must be letters, a dash and digits, like c-001 or CL-12`);
|
|
124
|
+
if (cards.some(c => c.id === id))
|
|
125
|
+
throw new RefusalError(`card "${id}" already exists`);
|
|
126
|
+
const at = now.toISOString();
|
|
127
|
+
const number = parseInt(id.replace(/\D/g, ''), 10);
|
|
128
|
+
const shared = cards.some(c => parseInt(c.id.replace(/\D/g, '') || '-1', 10) === number);
|
|
129
|
+
const card = {
|
|
130
|
+
id,
|
|
131
|
+
// Two prefixes with one number would otherwise share specs/001, usecases/001 and evidence/001.
|
|
132
|
+
...(shared ? { key: id.toLowerCase() } : {}),
|
|
133
|
+
title,
|
|
134
|
+
lane: lane.id,
|
|
135
|
+
laneVersion: lane.version,
|
|
136
|
+
stage: lane.stages[0].id,
|
|
137
|
+
retries: {},
|
|
138
|
+
evidence: [],
|
|
139
|
+
events: [event(now, actor, 'create', lane.stages[0].id, note)],
|
|
140
|
+
createdAt: at,
|
|
141
|
+
updatedAt: at,
|
|
142
|
+
};
|
|
143
|
+
parkIfOutward(card, lane, now);
|
|
144
|
+
return card;
|
|
145
|
+
}
|
|
146
|
+
/** Records a spec folder or an evidence path on a card. It never changes the stage or the gate. */
|
|
147
|
+
export function annotateCard(projectDir, id, patch, action, opts = {}) {
|
|
148
|
+
const file = readCards(projectDir);
|
|
149
|
+
const before = findCard(file.cards, id);
|
|
150
|
+
const now = opts.now ?? clock();
|
|
151
|
+
const card = {
|
|
152
|
+
...before,
|
|
153
|
+
...(patch.spec ? { spec: patch.spec } : {}),
|
|
154
|
+
evidence: patch.evidence && !before.evidence.includes(patch.evidence) ? [...before.evidence, patch.evidence] : before.evidence,
|
|
155
|
+
events: [...before.events, event(now, opts.role ?? 'agent', action, before.stage, opts.note)],
|
|
156
|
+
updatedAt: now.toISOString(),
|
|
157
|
+
};
|
|
158
|
+
writeCards(projectDir, file, replace(file.cards, card));
|
|
159
|
+
return card;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Appends one event to a card; it never changes the stage or the gate. `build` sees the board the
|
|
163
|
+
* write is checked against, so a limit it enforces by throwing cannot be passed by two writers.
|
|
164
|
+
*/
|
|
165
|
+
export function recordEvent(projectDir, id, build, now = clock()) {
|
|
166
|
+
for (let attempt = 0;; attempt++) {
|
|
167
|
+
const file = readCards(projectDir);
|
|
168
|
+
const before = findCard(file.cards, id);
|
|
169
|
+
const made = { ...event(now, 'engine', '', before.stage), ...build(file.cards, before) };
|
|
170
|
+
try {
|
|
171
|
+
writeCards(projectDir, file, replace(file.cards, { ...before, events: [...before.events, made], updatedAt: now.toISOString() }));
|
|
172
|
+
return made;
|
|
173
|
+
}
|
|
174
|
+
catch (e) {
|
|
175
|
+
// Another process wrote between the read and the write; `build` has to see the new board.
|
|
176
|
+
if (!(e instanceof ConflictError) || attempt >= 5)
|
|
177
|
+
throw e;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Cards for work that already exists elsewhere (Spec Kit, BMAD). They are an inventory, so the
|
|
183
|
+
* wip limit does not apply and each lands at the stage its source status maps to.
|
|
184
|
+
*/
|
|
185
|
+
export function importCards(projectDir, items, now = clock()) {
|
|
186
|
+
const file = readCards(projectDir);
|
|
187
|
+
let cards = file.cards;
|
|
188
|
+
const made = [];
|
|
189
|
+
for (const item of items) {
|
|
190
|
+
const lane = loadLane(projectDir, item.lane);
|
|
191
|
+
const card = newCard(cards, lane, item.title, nextCardId(cards), now, 'engine');
|
|
192
|
+
const stage = item.stage === DONE || lane.stages.some(s => s.id === item.stage) ? item.stage : card.stage;
|
|
193
|
+
const { gate: _gate, awaiting: _awaiting, ...rest } = card;
|
|
194
|
+
const placed = { ...rest, stage, spec: item.spec(card.id), events: [event(now, 'engine', 'import', stage, item.note)] };
|
|
195
|
+
made.push(placed);
|
|
196
|
+
cards = [...cards, placed];
|
|
197
|
+
}
|
|
198
|
+
if (made.length)
|
|
199
|
+
writeCards(projectDir, file, cards);
|
|
200
|
+
return made;
|
|
201
|
+
}
|
|
202
|
+
/** Started work that is parked at a gate. Proposals are not started work, so they do not use up capacity.gates_per_day. */
|
|
203
|
+
export const waitingOnOwner = (cards) => cards.filter(c => c.gate && c.stage !== PROPOSED).length;
|
|
204
|
+
/**
|
|
205
|
+
* A card that waits for the owner before it enters its lane: `approve` promotes it to the first
|
|
206
|
+
* stage, `reject` drops it. Nothing starts it. With `dedupe`, a second proposal made from the same
|
|
207
|
+
* finding returns the first card instead of creating another.
|
|
208
|
+
*/
|
|
209
|
+
export function proposeCard(projectDir, input) {
|
|
210
|
+
const lane = loadLane(projectDir, input.lane);
|
|
211
|
+
if (lane.stages.length === 0)
|
|
212
|
+
throw new RefusalError(`lane ${lane.id} has no stages`);
|
|
213
|
+
const now = input.now ?? clock();
|
|
214
|
+
for (let attempt = 0;; attempt++) {
|
|
215
|
+
const file = readCards(projectDir);
|
|
216
|
+
const known = input.dedupe ? file.cards.find(c => c.dedupe === input.dedupe) : undefined;
|
|
217
|
+
if (known)
|
|
218
|
+
return { card: known, created: false };
|
|
219
|
+
const at = now.toISOString();
|
|
220
|
+
const card = {
|
|
221
|
+
id: nextCardId(file.cards),
|
|
222
|
+
title: input.title,
|
|
223
|
+
lane: lane.id,
|
|
224
|
+
laneVersion: lane.version,
|
|
225
|
+
stage: PROPOSED,
|
|
226
|
+
...(input.description ? { description: input.description } : {}),
|
|
227
|
+
...(input.source ? { source: input.source } : {}),
|
|
228
|
+
...(input.dedupe ? { dedupe: input.dedupe } : {}),
|
|
229
|
+
gate: PROPOSAL_GATE,
|
|
230
|
+
awaiting: 'owner',
|
|
231
|
+
retries: {},
|
|
232
|
+
evidence: [],
|
|
233
|
+
events: [event(now, input.role ?? 'agent', 'propose', PROPOSED, input.source)],
|
|
234
|
+
createdAt: at,
|
|
235
|
+
updatedAt: at,
|
|
236
|
+
};
|
|
237
|
+
try {
|
|
238
|
+
writeCards(projectDir, file, [...file.cards, card]);
|
|
239
|
+
return { card, created: true };
|
|
240
|
+
}
|
|
241
|
+
catch (e) {
|
|
242
|
+
// A proposal depends on nothing else on the board, so it is made again on the newer one.
|
|
243
|
+
if (!(e instanceof ConflictError) || attempt >= 5)
|
|
244
|
+
throw e;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
export function createCard(projectDir, input) {
|
|
249
|
+
const lane = loadLane(projectDir, input.lane);
|
|
250
|
+
const file = readCards(projectDir);
|
|
251
|
+
const config = loadEngineConfig(projectDir);
|
|
252
|
+
const parked = waitingOnOwner(file.cards);
|
|
253
|
+
if (config.gatesPerDay !== undefined && parked >= config.gatesPerDay) {
|
|
254
|
+
throw new RefusalError(`${parked} ${parked === 1 ? 'card is' : 'cards are'} waiting on you (capacity.gates_per_day is ${config.gatesPerDay}); clear the inbox before starting new work`);
|
|
255
|
+
}
|
|
256
|
+
const active = file.cards.filter(c => c.lane === lane.id && inLane(c)).length;
|
|
257
|
+
if (lane.wip !== undefined && active >= lane.wip) {
|
|
258
|
+
throw new RefusalError(`lane ${lane.id} already has ${active} active cards (wip ${lane.wip})`);
|
|
259
|
+
}
|
|
260
|
+
const card = newCard(file.cards, lane, input.title, input.id ?? nextCardId(file.cards), input.now ?? clock(), input.role ?? 'agent', input.note);
|
|
261
|
+
writeCards(projectDir, file, [...file.cards, card]);
|
|
262
|
+
return card;
|
|
263
|
+
}
|
|
264
|
+
export function advanceCard(projectDir, ref, opts = {}) {
|
|
265
|
+
let file = readCards(projectDir);
|
|
266
|
+
let before = findCard(file.cards, ref);
|
|
267
|
+
const id = before.id;
|
|
268
|
+
if (before.stage === DONE)
|
|
269
|
+
throw new RefusalError(`card ${id} is already done`);
|
|
270
|
+
if (before.stage === DROPPED)
|
|
271
|
+
throw new RefusalError(`card ${id} was dropped as a proposal`);
|
|
272
|
+
if (before.gate)
|
|
273
|
+
throw new RefusalError(`card ${id} is waiting for you at gate "${before.gate}" (${before.awaiting} approves)`);
|
|
274
|
+
const lane = loadLane(projectDir, before.lane);
|
|
275
|
+
const stage = currentStage(lane, before);
|
|
276
|
+
const now = opts.now ?? clock();
|
|
277
|
+
const draft = (from) => ({ ...from, retries: { ...from.retries }, events: [...from.events], evidence: [...from.evidence], updatedAt: now.toISOString() });
|
|
278
|
+
let card = draft(before);
|
|
279
|
+
// Covers a card whose outward gate was rejected, or that sat in the stage before the gate was added.
|
|
280
|
+
if (awaitsApproval(card, stage)) {
|
|
281
|
+
park(card, stage, now, 'before the stage runs');
|
|
282
|
+
writeCards(projectDir, file, replace(file.cards, card));
|
|
283
|
+
return { card, outcome: 'parked', started: [] };
|
|
284
|
+
}
|
|
285
|
+
const check = runCheck(projectDir, card, stage);
|
|
286
|
+
const output = check?.output ?? '';
|
|
287
|
+
// A check may itself write the board: the scan stage proposes cards, and `verify` records its
|
|
288
|
+
// evidence on this card. The advance is then written on the board as the check left it. A card
|
|
289
|
+
// that was moved or parked meanwhile is someone else's decision, and that is a conflict.
|
|
290
|
+
const after = readCards(projectDir);
|
|
291
|
+
if (after.version !== file.version) {
|
|
292
|
+
const current = after.cards.find(c => c.id === id);
|
|
293
|
+
if (!current || current.stage !== before.stage || current.gate !== before.gate) {
|
|
294
|
+
throw new ConflictError(`card ${id} was moved while its ${stage.id} check ran; re-read and retry`);
|
|
295
|
+
}
|
|
296
|
+
file = after;
|
|
297
|
+
before = current;
|
|
298
|
+
card = draft(current);
|
|
299
|
+
}
|
|
300
|
+
if (check) {
|
|
301
|
+
if (!check.passed) {
|
|
302
|
+
// An unattended run retries on a schedule. If the work has not changed since the last failure
|
|
303
|
+
// there is nothing new to judge, so it must not use up a retry.
|
|
304
|
+
// The check's own output is no guide (test runners print timings), so a stage with no output
|
|
305
|
+
// file is judged by the working tree instead.
|
|
306
|
+
const stageOutput = stage.output ? join(projectDir, substitute(stage.output, card)) : null;
|
|
307
|
+
const work = stageOutput ? (existsSync(stageOutput) && statSync(stageOutput).isFile() ? readFileSync(stageOutput) : 'missing') : treeState(projectDir) ?? output;
|
|
308
|
+
const fingerprint = createHash('sha1').update(work).digest('hex');
|
|
309
|
+
if (opts.unattended && before.failures?.[stage.id] === fingerprint)
|
|
310
|
+
return { card: before, outcome: 'unchanged', output, started: [] };
|
|
311
|
+
card.failures = { ...before.failures, [stage.id]: fingerprint };
|
|
312
|
+
const failures = (card.retries[stage.id] ?? 0) + 1;
|
|
313
|
+
card.retries[stage.id] = failures;
|
|
314
|
+
card.events.push(event(now, 'engine', 'fail', stage.id, output));
|
|
315
|
+
const stuck = failures >= lane.retries;
|
|
316
|
+
if (stuck) {
|
|
317
|
+
card.gate = 'stuck';
|
|
318
|
+
card.awaiting = 'owner';
|
|
319
|
+
card.events.push(event(now, 'engine', 'stuck', stage.id, output));
|
|
320
|
+
}
|
|
321
|
+
writeCards(projectDir, file, replace(file.cards, card));
|
|
322
|
+
return { card, outcome: stuck ? 'stuck' : 'failed', output, started: [] };
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
else if (stage.done?.event) {
|
|
326
|
+
if (opts.event !== stage.done.event)
|
|
327
|
+
throw new RefusalError(`card ${id} stage ${stage.id} is waiting for event "${stage.done.event}"`);
|
|
328
|
+
}
|
|
329
|
+
else {
|
|
330
|
+
throw new RefusalError(`lane ${lane.id} stage ${stage.id} has no done check`);
|
|
331
|
+
}
|
|
332
|
+
const given = stage.gate ? approval(card, stage) : undefined;
|
|
333
|
+
if (given?.fingerprint && given.fingerprint !== stageFingerprint(projectDir, card, stage)) {
|
|
334
|
+
park(card, stage, now, 'the output or the check changed since it was approved');
|
|
335
|
+
writeCards(projectDir, file, replace(file.cards, card));
|
|
336
|
+
return { card, outcome: 'parked', output, started: [] };
|
|
337
|
+
}
|
|
338
|
+
if (stage.gate && !given) {
|
|
339
|
+
if (loadEngineConfig(projectDir).gatesMode === 'trusted') {
|
|
340
|
+
card.events.push(event(now, 'engine', 'auto-approve', stage.id, `gate ${stage.gate.name} (gates.mode trusted)`));
|
|
341
|
+
}
|
|
342
|
+
else {
|
|
343
|
+
park(card, stage, now, 'after the check passed');
|
|
344
|
+
writeCards(projectDir, file, replace(file.cards, card));
|
|
345
|
+
return { card, outcome: 'parked', output, started: [] };
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
const next = lane.stages[lane.stages.indexOf(stage) + 1];
|
|
349
|
+
card.stage = next ? next.id : DONE;
|
|
350
|
+
if (stage.output)
|
|
351
|
+
card.evidence.push(substitute(stage.output, card));
|
|
352
|
+
card.events.push(event(now, 'engine', 'advance', stage.id, `to ${card.stage}`));
|
|
353
|
+
for (const page of researchFindings(projectDir, card, stage))
|
|
354
|
+
card.events.push(event(now, 'engine', 'findings', stage.id, page));
|
|
355
|
+
if (next)
|
|
356
|
+
parkIfOutward(card, lane, now);
|
|
357
|
+
let cards = replace(file.cards, card);
|
|
358
|
+
const started = [];
|
|
359
|
+
if (!next) {
|
|
360
|
+
// on_done.start here and `trigger: { on: lane.done, lane }` there mean the same thing; a Set
|
|
361
|
+
// keeps a lane that declares both from getting two cards.
|
|
362
|
+
const targets = new Set(lane.on_done?.start ? [lane.on_done.start] : []);
|
|
363
|
+
for (const other of loadLanes(projectDir)) {
|
|
364
|
+
if (other.trigger?.on === 'lane.done' && other.trigger.lane === lane.id)
|
|
365
|
+
targets.add(other.id);
|
|
366
|
+
}
|
|
367
|
+
// Not subject to wip or capacity: refusing here would drop the follow-on for a finished card.
|
|
368
|
+
for (const target of targets) {
|
|
369
|
+
// A follow-on that cannot start (its lane file is missing or names no stages) is recorded
|
|
370
|
+
// on the finished card. It must not undo the finish.
|
|
371
|
+
try {
|
|
372
|
+
const follow = newCard(cards, loadLane(projectDir, target), card.title, nextCardId(cards), now, 'engine', `started by ${card.id} finishing lane ${lane.id}`);
|
|
373
|
+
started.push(follow);
|
|
374
|
+
cards = [...cards, follow];
|
|
375
|
+
}
|
|
376
|
+
catch (e) {
|
|
377
|
+
if (!(e instanceof RefusalError))
|
|
378
|
+
throw e;
|
|
379
|
+
card.events.push(event(now, 'engine', 'on_done-failed', stage.id, e.message));
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
writeCards(projectDir, file, cards);
|
|
384
|
+
return { card, outcome: !next ? 'done' : card.gate ? 'parked' : 'moved', output, started };
|
|
385
|
+
}
|
|
386
|
+
export function approveCard(projectDir, ref, role, opts = {}) {
|
|
387
|
+
const file = readCards(projectDir);
|
|
388
|
+
const before = findCard(file.cards, ref);
|
|
389
|
+
const id = before.id;
|
|
390
|
+
if (!before.gate)
|
|
391
|
+
throw new RefusalError(`card ${id} is not waiting at a gate`);
|
|
392
|
+
if (role !== before.awaiting)
|
|
393
|
+
throw new RefusalError(`gate "${before.gate}" needs ${before.awaiting}; ${role} cannot approve it`);
|
|
394
|
+
const now = opts.now ?? clock();
|
|
395
|
+
const { gate, awaiting: _awaiting, ...rest } = before;
|
|
396
|
+
const card = { ...rest, retries: { ...before.retries }, updatedAt: now.toISOString() };
|
|
397
|
+
if (before.stage === PROPOSED) {
|
|
398
|
+
// Not subject to wip: the owner chose this card. A run still works a lane `wip` cards at a time.
|
|
399
|
+
const lane = loadLane(projectDir, before.lane);
|
|
400
|
+
card.stage = lane.stages[0].id;
|
|
401
|
+
card.laneVersion = lane.version;
|
|
402
|
+
card.events = [...before.events, event(now, role, 'promote', card.stage, opts.note)];
|
|
403
|
+
parkIfOutward(card, lane, now);
|
|
404
|
+
}
|
|
405
|
+
else if (gate === 'stuck') {
|
|
406
|
+
card.retries[card.stage] = 0;
|
|
407
|
+
card.events = [...before.events, event(now, role, 'unstick', card.stage, opts.note)];
|
|
408
|
+
}
|
|
409
|
+
else {
|
|
410
|
+
const stage = loadLane(projectDir, before.lane).stages.find(s => s.id === before.stage);
|
|
411
|
+
const fingerprint = stage ? stageFingerprint(projectDir, before, stage) : undefined;
|
|
412
|
+
card.events = [...before.events, { ...event(now, role, 'approve', card.stage, opts.note ?? `gate ${gate}`), ...(fingerprint ? { fingerprint } : {}) }];
|
|
413
|
+
}
|
|
414
|
+
writeCards(projectDir, file, replace(file.cards, card));
|
|
415
|
+
return card;
|
|
416
|
+
}
|
|
417
|
+
export function rejectCard(projectDir, ref, role, note, opts = {}) {
|
|
418
|
+
const file = readCards(projectDir);
|
|
419
|
+
const before = findCard(file.cards, ref);
|
|
420
|
+
const id = before.id;
|
|
421
|
+
if (!before.gate)
|
|
422
|
+
throw new RefusalError(`card ${id} is not waiting at a gate`);
|
|
423
|
+
if (before.gate === 'stuck')
|
|
424
|
+
throw new RefusalError(`card ${id} is stuck, not at a gate; approve it to retry`);
|
|
425
|
+
if (role !== before.awaiting)
|
|
426
|
+
throw new RefusalError(`gate "${before.gate}" needs ${before.awaiting}; ${role} cannot reject it`);
|
|
427
|
+
if (!note?.trim())
|
|
428
|
+
throw new RefusalError('a rejection needs a note saying what to change');
|
|
429
|
+
const now = opts.now ?? clock();
|
|
430
|
+
const { gate: _gate, awaiting: _awaiting, ...rest } = before;
|
|
431
|
+
const card = { ...rest, ...(before.stage === PROPOSED ? { stage: DROPPED } : {}), events: [...before.events, event(now, role, 'reject', before.stage, note.trim())], updatedAt: now.toISOString() };
|
|
432
|
+
writeCards(projectDir, file, replace(file.cards, card));
|
|
433
|
+
return card;
|
|
434
|
+
}
|
|
435
|
+
//# sourceMappingURL=engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/lib/engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { type Card } from './cards.js';
|
|
2
|
+
import { type AdvanceResult, type Role } from './engine.js';
|
|
3
|
+
/** Creates the card and, for a lane whose stages work in a spec folder, the folder too. */
|
|
4
|
+
export declare function startCard(projectDir: string, input: {
|
|
5
|
+
lane: string;
|
|
6
|
+
title: string;
|
|
7
|
+
id?: string;
|
|
8
|
+
role?: Role;
|
|
9
|
+
}): Card;
|
|
10
|
+
/**
|
|
11
|
+
* Approves, then advances once when the stage's check had already passed before the gate. A public
|
|
12
|
+
* step is approved before its work exists and a stuck card needs a fix first, so neither is advanced.
|
|
13
|
+
*/
|
|
14
|
+
export declare function approveFlow(projectDir: string, ref: string, role: Role, note?: string): {
|
|
15
|
+
card: Card;
|
|
16
|
+
gate: string;
|
|
17
|
+
advanced?: AdvanceResult;
|
|
18
|
+
};
|
|
19
|
+
/** What whoever runs the current stage needs: the skill, where output goes, the check, and prior feedback. */
|
|
20
|
+
export declare function stageBrief(projectDir: string, card: Card): {
|
|
21
|
+
skill: string | undefined;
|
|
22
|
+
role: string | string[] | undefined;
|
|
23
|
+
output: string | undefined;
|
|
24
|
+
done: string | undefined;
|
|
25
|
+
notes: string[];
|
|
26
|
+
rejections: (string | undefined)[];
|
|
27
|
+
} | null;
|
|
28
|
+
/** One line saying what to do with the card now. `failure` is the output of a check that just failed. */
|
|
29
|
+
export declare function nextHint(projectDir: string, card: Card, failure?: string): string;
|
|
30
|
+
/** Text for an advance result, the Next line last. Exit 2 when the check failed. */
|
|
31
|
+
export declare function describeAdvance(projectDir: string, result: AdvanceResult): {
|
|
32
|
+
lines: string[];
|
|
33
|
+
exitCode: number;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* The approval a card holds for a named gate. `authenticated` is true only when the event carries
|
|
37
|
+
* an `approvalId` from a store that knows who approved; a local approval is whatever role the
|
|
38
|
+
* caller claimed, so CI must not treat it as proof that a person approved.
|
|
39
|
+
*/
|
|
40
|
+
export declare function gateApproval(projectDir: string, ref: string, gate: string): {
|
|
41
|
+
actor: string;
|
|
42
|
+
at: string;
|
|
43
|
+
authenticated: boolean;
|
|
44
|
+
};
|
package/dist/lib/flow.js
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { DONE, DROPPED, findCard, PROPOSAL_GATE, PROPOSED, readCards, RefusalError } from './cards.js';
|
|
2
|
+
import { advanceCard, approveCard, createCard } from './engine.js';
|
|
3
|
+
import { loadLane, substitute } from './lane.js';
|
|
4
|
+
import { newSpec } from './spec.js';
|
|
5
|
+
const usesSpec = (lane) => lane.stages.some(s => `${s.output ?? ''} ${s.done?.cmd ?? ''}`.includes('{spec}') || s.done?.cmd?.includes('codeloop spec check'));
|
|
6
|
+
/** Creates the card and, for a lane whose stages work in a spec folder, the folder too. */
|
|
7
|
+
export function startCard(projectDir, input) {
|
|
8
|
+
const card = createCard(projectDir, input);
|
|
9
|
+
if (!usesSpec(loadLane(projectDir, card.lane)))
|
|
10
|
+
return card;
|
|
11
|
+
newSpec(projectDir, card.id, input.role);
|
|
12
|
+
return findCard(readCards(projectDir).cards, card.id);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Approves, then advances once when the stage's check had already passed before the gate. A public
|
|
16
|
+
* step is approved before its work exists and a stuck card needs a fix first, so neither is advanced.
|
|
17
|
+
*/
|
|
18
|
+
export function approveFlow(projectDir, ref, role, note) {
|
|
19
|
+
const before = findCard(readCards(projectDir).cards, ref);
|
|
20
|
+
const gate = before.gate ?? '';
|
|
21
|
+
const stage = currentStage(projectDir, before);
|
|
22
|
+
const card = approveCard(projectDir, before.id, role, { note });
|
|
23
|
+
// A promoted proposal enters its first stage with no work done yet, so its check is not run either.
|
|
24
|
+
if (gate === 'stuck' || gate === PROPOSAL_GATE || stage?.gate?.outward)
|
|
25
|
+
return { card, gate };
|
|
26
|
+
// A stage that waits for an event reaches its gate only once that event has been reported, so
|
|
27
|
+
// the advance after approval carries it. Without this the approval was recorded and the advance
|
|
28
|
+
// then refused, asking for an event that had already arrived.
|
|
29
|
+
const event = !stage?.done?.cmd ? stage?.done?.event : undefined;
|
|
30
|
+
return { card, gate, advanced: advanceCard(projectDir, card.id, { event }) };
|
|
31
|
+
}
|
|
32
|
+
function currentStage(projectDir, card) {
|
|
33
|
+
return card.stage === DONE || card.stage === PROPOSED || card.stage === DROPPED ? undefined : loadLane(projectDir, card.lane).stages.find(s => s.id === card.stage);
|
|
34
|
+
}
|
|
35
|
+
/** What whoever runs the current stage needs: the skill, where output goes, the check, and prior feedback. */
|
|
36
|
+
export function stageBrief(projectDir, card) {
|
|
37
|
+
const stage = currentStage(projectDir, card);
|
|
38
|
+
if (!stage)
|
|
39
|
+
return null;
|
|
40
|
+
return {
|
|
41
|
+
skill: stage.skill,
|
|
42
|
+
role: stage.role,
|
|
43
|
+
output: stage.output && substitute(stage.output, card),
|
|
44
|
+
done: stage.done?.cmd ? substitute(stage.done.cmd, card, { shell: true }) : stage.done?.event && `event ${stage.done.event}`,
|
|
45
|
+
notes: stage.notes ?? [],
|
|
46
|
+
rejections: card.events.filter(e => e.action === 'reject' && e.stage === stage.id).map(e => e.note),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
// Where to look when the last agent started on this stage did not finish cleanly.
|
|
50
|
+
function agentTrouble(card, stage) {
|
|
51
|
+
const last = card.events.filter(e => e.action === 'agent-run' && e.stage === stage.id).at(-1);
|
|
52
|
+
return last && last.exit !== 0 ? ` Agent ${last.agent} ${last.note ?? `exited ${last.exit}`}; its output is in ${last.log}.` : '';
|
|
53
|
+
}
|
|
54
|
+
/** One line saying what to do with the card now. `failure` is the output of a check that just failed. */
|
|
55
|
+
export function nextHint(projectDir, card, failure) {
|
|
56
|
+
if (card.stage === PROPOSED)
|
|
57
|
+
return `Next: \`codeloop approve ${card.id}\` puts it in the ${card.lane} lane, or \`codeloop reject ${card.id} "<why not>"\` drops it.`;
|
|
58
|
+
const stage = currentStage(projectDir, card);
|
|
59
|
+
if (!stage)
|
|
60
|
+
return 'Next: nothing left on this card. `codeloop inbox` shows what else is waiting.';
|
|
61
|
+
const output = stage.output ? substitute(stage.output, card) : undefined;
|
|
62
|
+
const skill = stage.skill ? `the /${stage.skill} skill` : `the ${stage.id} stage`;
|
|
63
|
+
if (card.gate === 'stuck')
|
|
64
|
+
return `Next: fix what the check reports${output ? ` in ${output}` : ''}, then \`codeloop approve ${card.id}\` to allow another try.${agentTrouble(card, stage)}`;
|
|
65
|
+
if (card.gate && stage.gate?.outward) {
|
|
66
|
+
return `Next: ${stage.id} is a public step and has not run. \`codeloop approve ${card.id}\` to let it run, or \`codeloop reject ${card.id} "<what to change>"\`.`;
|
|
67
|
+
}
|
|
68
|
+
if (card.gate)
|
|
69
|
+
return `Next: ${output ? `read ${output}, then ` : ''}\`codeloop approve ${card.id}\`, or \`codeloop reject ${card.id} "<what to change>"\`.`;
|
|
70
|
+
if (!stage.done?.cmd && stage.done?.event)
|
|
71
|
+
return `Next: ${stage.id} waits for the event "${stage.done.event}". When it has happened: \`codeloop next ${card.id} --event ${stage.done.event}\`.`;
|
|
72
|
+
if (failure !== undefined) {
|
|
73
|
+
const reason = failure.split('\n').map(l => l.trim()).filter(Boolean).at(-1) ?? 'the check failed';
|
|
74
|
+
return `Next: ${reason}. ${skill[0].toUpperCase()}${skill.slice(1)} produces ${output ?? 'what the check needs'}. Then \`codeloop next ${card.id}\`.${agentTrouble(card, stage)}`;
|
|
75
|
+
}
|
|
76
|
+
return `Next: run ${skill}${output ? ` to write ${output}` : ''}, then \`codeloop next ${card.id}\`.${agentTrouble(card, stage)}`;
|
|
77
|
+
}
|
|
78
|
+
/** Text for an advance result, the Next line last. Exit 2 when the check failed. */
|
|
79
|
+
export function describeAdvance(projectDir, result) {
|
|
80
|
+
const { card } = result;
|
|
81
|
+
const lines = [];
|
|
82
|
+
switch (result.outcome) {
|
|
83
|
+
case 'moved':
|
|
84
|
+
lines.push(`${card.id} moved to ${card.stage}`);
|
|
85
|
+
break;
|
|
86
|
+
case 'done':
|
|
87
|
+
lines.push(`${card.id} done`, ...result.started.map(s => `started ${s.id} in ${s.lane}`));
|
|
88
|
+
break;
|
|
89
|
+
case 'parked':
|
|
90
|
+
lines.push(`${card.id} is waiting for you at ${card.stage} (gate ${card.gate}, ${card.awaiting} approves)`);
|
|
91
|
+
break;
|
|
92
|
+
case 'unchanged':
|
|
93
|
+
lines.push(`${card.id} unchanged, waiting for work at ${card.stage}`);
|
|
94
|
+
break;
|
|
95
|
+
case 'stuck':
|
|
96
|
+
lines.push(result.output ?? '', `${card.id} is stuck at ${card.stage} after ${card.retries[card.stage]} failed checks`);
|
|
97
|
+
break;
|
|
98
|
+
case 'failed':
|
|
99
|
+
lines.push(result.output ?? '', `${card.id} failed the ${card.stage} check (${card.retries[card.stage]} so far)`);
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
const failed = result.outcome === 'failed' || result.outcome === 'stuck' || result.outcome === 'unchanged';
|
|
103
|
+
lines.push(nextHint(projectDir, card, result.outcome === 'failed' || result.outcome === 'unchanged' ? result.output ?? '' : undefined));
|
|
104
|
+
return { lines: lines.filter(Boolean), exitCode: failed ? 2 : 0 };
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* The approval a card holds for a named gate. `authenticated` is true only when the event carries
|
|
108
|
+
* an `approvalId` from a store that knows who approved; a local approval is whatever role the
|
|
109
|
+
* caller claimed, so CI must not treat it as proof that a person approved.
|
|
110
|
+
*/
|
|
111
|
+
export function gateApproval(projectDir, ref, gate) {
|
|
112
|
+
const card = findCard(readCards(projectDir).cards, ref);
|
|
113
|
+
const stages = loadLane(projectDir, card.lane).stages.filter(s => s.gate?.name === gate).map(s => s.id);
|
|
114
|
+
if (stages.length === 0)
|
|
115
|
+
throw new RefusalError(`lane ${card.lane} has no gate named "${gate}"`);
|
|
116
|
+
const event = card.events.find(e => (e.action === 'approve' || e.action === 'auto-approve') && stages.includes(e.stage ?? ''));
|
|
117
|
+
if (!event)
|
|
118
|
+
throw new RefusalError(`card ${card.id} has no approval for gate "${gate}"`);
|
|
119
|
+
return { actor: event.actor, at: event.at, authenticated: !!event.approvalId };
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=flow.js.map
|