@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,66 @@
|
|
|
1
|
+
import { spawnSync } from 'child_process';
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, statSync } from 'fs';
|
|
3
|
+
import { dirname, join } from 'path';
|
|
4
|
+
import { RefusalError } from './cards.js';
|
|
5
|
+
import { cronError } from './cron.js';
|
|
6
|
+
export const RUN_LOG = '.codeloop/state/run.log';
|
|
7
|
+
const quote = (value) => `'${value.replaceAll("'", `'\\''`)}'`;
|
|
8
|
+
const marker = (projectDir) => `# codeloop:${projectDir}`;
|
|
9
|
+
/** `30m`, `1h`, `6h`: only intervals that divide the hour or the day, since cron cannot say "every 45 minutes". */
|
|
10
|
+
export function everyToCron(every) {
|
|
11
|
+
const m = /^(\d+)(m|h)$/.exec(every);
|
|
12
|
+
const n = m ? parseInt(m[1], 10) : 0;
|
|
13
|
+
if (m?.[2] === 'm' && n >= 1 && n < 60 && 60 % n === 0)
|
|
14
|
+
return `*/${n} * * * *`;
|
|
15
|
+
if (m?.[2] === 'h' && n >= 1 && n <= 24 && 24 % n === 0)
|
|
16
|
+
return n === 1 ? '0 * * * *' : n === 24 ? '0 0 * * *' : `0 */${n} * * *`;
|
|
17
|
+
throw new RefusalError(`--every "${every}" is not an interval cron can run (5m, 10m, 15m, 20m, 30m, 1h, 2h, 3h, 4h, 6h, 12h, 24h); use --cron for anything else`);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* One crontab line. cron starts with a bare PATH, so the PATH of the installing shell is written
|
|
21
|
+
* into the line: the agent command (claude, codex) has to be found at 3am too.
|
|
22
|
+
*/
|
|
23
|
+
export function scheduleLine(projectDir, opts) {
|
|
24
|
+
const problem = cronError(opts.cron);
|
|
25
|
+
if (problem)
|
|
26
|
+
throw new RefusalError(problem);
|
|
27
|
+
const entry = opts.entry ?? process.argv[1];
|
|
28
|
+
const run = opts.agent ? ` --agent${opts.agent === true ? '' : ` ${opts.agent}`}` : '';
|
|
29
|
+
const command = `cd ${quote(projectDir)} && PATH=${quote(opts.path ?? process.env.PATH ?? '')} ${quote(process.execPath)} ${quote(entry)} run${run} >> ${RUN_LOG} 2>&1`;
|
|
30
|
+
// cron reads an unescaped % as the end of the command.
|
|
31
|
+
return `${opts.cron} ${command.replaceAll('%', '\\%')} ${marker(projectDir)}`;
|
|
32
|
+
}
|
|
33
|
+
function readTable(crontab) {
|
|
34
|
+
const run = spawnSync(crontab, ['-l'], { encoding: 'utf-8' });
|
|
35
|
+
if (run.error)
|
|
36
|
+
throw new RefusalError(`could not run ${crontab}: ${run.error.message}`);
|
|
37
|
+
// `crontab -l` exits 1 when the user has no crontab yet.
|
|
38
|
+
return run.status === 0 ? run.stdout.split('\n').filter(l => l !== '') : [];
|
|
39
|
+
}
|
|
40
|
+
function writeTable(crontab, lines) {
|
|
41
|
+
const run = spawnSync(crontab, ['-'], { input: lines.length ? lines.join('\n') + '\n' : '', encoding: 'utf-8' });
|
|
42
|
+
if (run.error || run.status !== 0)
|
|
43
|
+
throw new RefusalError(`${crontab} refused the new table: ${run.error?.message ?? run.stderr.trim()}`);
|
|
44
|
+
}
|
|
45
|
+
const mine = (projectDir) => (line) => line.endsWith(marker(projectDir));
|
|
46
|
+
export function installSchedule(projectDir, line, crontab = 'crontab') {
|
|
47
|
+
mkdirSync(dirname(join(projectDir, RUN_LOG)), { recursive: true });
|
|
48
|
+
writeTable(crontab, [...readTable(crontab).filter(l => !mine(projectDir)(l)), line]);
|
|
49
|
+
}
|
|
50
|
+
export function removeSchedule(projectDir, crontab = 'crontab') {
|
|
51
|
+
const table = readTable(crontab);
|
|
52
|
+
const kept = table.filter(l => !mine(projectDir)(l));
|
|
53
|
+
if (kept.length === table.length)
|
|
54
|
+
return false;
|
|
55
|
+
writeTable(crontab, kept);
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
export function scheduleStatus(projectDir, crontab = 'crontab') {
|
|
59
|
+
const log = join(projectDir, RUN_LOG);
|
|
60
|
+
const ran = existsSync(log);
|
|
61
|
+
return {
|
|
62
|
+
line: readTable(crontab).find(mine(projectDir)),
|
|
63
|
+
...(ran ? { lastRun: statSync(log).mtime, lastOutput: readFileSync(log, 'utf-8').trimEnd().split('\n').slice(-5).join('\n') } : {}),
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=schedule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schedule.js","sourceRoot":"","sources":["../../src/lib/schedule.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { Hono } from 'hono';
|
|
2
|
+
/** Cards, the lanes they move through and the inbox summary: everything the Cards view draws. */
|
|
3
|
+
export declare function cardsPayload(projectDir: string, owner: boolean): {
|
|
4
|
+
version: number;
|
|
5
|
+
owner: boolean;
|
|
6
|
+
cards: (import("./cards.js").Card | {
|
|
7
|
+
mock: string;
|
|
8
|
+
id: string;
|
|
9
|
+
title: string;
|
|
10
|
+
lane: string;
|
|
11
|
+
laneVersion: number;
|
|
12
|
+
stage: string;
|
|
13
|
+
key?: string;
|
|
14
|
+
spec?: string;
|
|
15
|
+
description?: string;
|
|
16
|
+
source?: string;
|
|
17
|
+
dedupe?: string;
|
|
18
|
+
gate?: string;
|
|
19
|
+
awaiting?: string;
|
|
20
|
+
retries: Record<string, number>;
|
|
21
|
+
failures?: Record<string, string>;
|
|
22
|
+
evidence: string[];
|
|
23
|
+
events: import("./cards.js").CardEvent[];
|
|
24
|
+
createdAt: string;
|
|
25
|
+
updatedAt: string;
|
|
26
|
+
})[];
|
|
27
|
+
lanes: {
|
|
28
|
+
id: string;
|
|
29
|
+
version: number;
|
|
30
|
+
stages: {
|
|
31
|
+
id: string;
|
|
32
|
+
skill: string | undefined;
|
|
33
|
+
output: string | undefined;
|
|
34
|
+
gate: import("./lane.js").Gate | undefined;
|
|
35
|
+
}[];
|
|
36
|
+
}[];
|
|
37
|
+
inbox: {
|
|
38
|
+
summary: string;
|
|
39
|
+
needs_you: {
|
|
40
|
+
id: string;
|
|
41
|
+
title: string;
|
|
42
|
+
lane: string;
|
|
43
|
+
stage: string;
|
|
44
|
+
gate: string;
|
|
45
|
+
awaiting?: string;
|
|
46
|
+
read?: string;
|
|
47
|
+
mock?: string;
|
|
48
|
+
source?: string;
|
|
49
|
+
last_check: string;
|
|
50
|
+
since: string;
|
|
51
|
+
last_event?: import("./cards.js").CardEvent;
|
|
52
|
+
}[];
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* `owner` is set only by `codeloop serve --owner`. Without it the board is read-only for cards.
|
|
57
|
+
* With it, approve and reject still need the start-up token like every other write.
|
|
58
|
+
*/
|
|
59
|
+
export declare function createApp(projectDir: string, uiDir?: string, opts?: {
|
|
60
|
+
owner?: boolean;
|
|
61
|
+
token?: string;
|
|
62
|
+
anyHost?: boolean;
|
|
63
|
+
}): {
|
|
64
|
+
app: Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
|
|
65
|
+
broadcast: () => void;
|
|
66
|
+
broadcastCards: () => void;
|
|
67
|
+
token: string;
|
|
68
|
+
};
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import { Hono } from 'hono';
|
|
2
|
+
import { streamSSE } from 'hono/streaming';
|
|
3
|
+
import { randomBytes, timingSafeEqual } from 'crypto';
|
|
4
|
+
import { existsSync, readFileSync, statSync } from 'fs';
|
|
5
|
+
import { join, extname, resolve, sep } from 'path';
|
|
6
|
+
import { loadBoard, saveBoard, addTask, updateTask, deleteTask, getTask, } from './board.js';
|
|
7
|
+
import { ConflictError, readCards, RefusalError } from './cards.js';
|
|
8
|
+
import { rejectCard } from './engine.js';
|
|
9
|
+
import { approveFlow } from './flow.js';
|
|
10
|
+
import { buildInbox } from './inbox.js';
|
|
11
|
+
import { loadLanes } from './lane.js';
|
|
12
|
+
import { findMock, MOCKS_DIR } from './mock.js';
|
|
13
|
+
const MIME_TYPES = {
|
|
14
|
+
'.html': 'text/html',
|
|
15
|
+
'.js': 'application/javascript',
|
|
16
|
+
'.css': 'text/css',
|
|
17
|
+
'.json': 'application/json',
|
|
18
|
+
'.png': 'image/png',
|
|
19
|
+
'.svg': 'image/svg+xml',
|
|
20
|
+
'.ico': 'image/x-icon',
|
|
21
|
+
'.txt': 'text/plain',
|
|
22
|
+
};
|
|
23
|
+
/** Cards, the lanes they move through and the inbox summary: everything the Cards view draws. */
|
|
24
|
+
export function cardsPayload(projectDir, owner) {
|
|
25
|
+
const file = readCards(projectDir);
|
|
26
|
+
const inbox = buildInbox(projectDir);
|
|
27
|
+
return {
|
|
28
|
+
version: file.version,
|
|
29
|
+
owner,
|
|
30
|
+
// `mock` is where the board serves the card's mock, when it has one.
|
|
31
|
+
cards: file.cards.map(c => {
|
|
32
|
+
const mock = findMock(projectDir, c.id);
|
|
33
|
+
return mock ? { ...c, mock: `/${mock.replace(`${MOCKS_DIR}/`, 'mocks/')}` } : c;
|
|
34
|
+
}),
|
|
35
|
+
lanes: loadLanes(projectDir).map(l => ({ id: l.id, version: l.version, stages: l.stages.map(s => ({ id: s.id, skill: s.skill, output: s.output, gate: s.gate })) })),
|
|
36
|
+
inbox: { summary: inbox.summary, needs_you: inbox.needs_you },
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* `owner` is set only by `codeloop serve --owner`. Without it the board is read-only for cards.
|
|
41
|
+
* With it, approve and reject still need the start-up token like every other write.
|
|
42
|
+
*/
|
|
43
|
+
export function createApp(projectDir, uiDir, opts = {}) {
|
|
44
|
+
const app = new Hono();
|
|
45
|
+
const token = opts.token ?? randomBytes(24).toString('hex');
|
|
46
|
+
const sameToken = (given) => !!given && given.length === token.length && timingSafeEqual(Buffer.from(given), Buffer.from(token));
|
|
47
|
+
const LOOPBACK = new Set(['localhost', '127.0.0.1', '[::1]']);
|
|
48
|
+
const sameHost = (origin, host) => {
|
|
49
|
+
try {
|
|
50
|
+
return new URL(origin).host === host;
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
// There is no login, so the server protects itself three ways. It answers only to a loopback
|
|
57
|
+
// host name (a rebound DNS name cannot read the board). It sends no CORS headers, so other
|
|
58
|
+
// origins cannot read responses. And every write needs the token printed at start-up, a JSON
|
|
59
|
+
// content type, and no foreign Origin, which a page on another site cannot provide.
|
|
60
|
+
app.use('*', async (c, next) => {
|
|
61
|
+
const host = c.req.header('host') ?? new URL(c.req.url).host;
|
|
62
|
+
if (!opts.anyHost && !LOOPBACK.has(host.replace(/:\d+$/, '')))
|
|
63
|
+
return c.json({ error: `this board answers only on localhost, not ${host}` }, 403);
|
|
64
|
+
if (c.req.method === 'GET' || c.req.method === 'HEAD')
|
|
65
|
+
return next();
|
|
66
|
+
const origin = c.req.header('origin');
|
|
67
|
+
if (origin && !sameHost(origin, host))
|
|
68
|
+
return c.json({ error: 'cross-origin requests are not accepted' }, 403);
|
|
69
|
+
if (!sameToken(c.req.header('x-codeloop-token')))
|
|
70
|
+
return c.json({ error: 'missing or wrong token: open the URL that `codeloop serve` printed' }, 403);
|
|
71
|
+
if (c.req.method !== 'DELETE' && !(c.req.header('content-type') ?? '').startsWith('application/json'))
|
|
72
|
+
return c.json({ error: 'content type must be application/json' }, 415);
|
|
73
|
+
return next();
|
|
74
|
+
});
|
|
75
|
+
// Track SSE clients for broadcasting
|
|
76
|
+
const sseClients = new Set();
|
|
77
|
+
const cardClients = new Set();
|
|
78
|
+
const owner = opts.owner === true;
|
|
79
|
+
function broadcast() {
|
|
80
|
+
const board = loadBoard(projectDir);
|
|
81
|
+
for (const send of sseClients) {
|
|
82
|
+
send(board);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function broadcastCards() {
|
|
86
|
+
const payload = JSON.stringify(cardsPayload(projectDir, owner));
|
|
87
|
+
for (const send of cardClients)
|
|
88
|
+
send(payload);
|
|
89
|
+
}
|
|
90
|
+
app.get('/api/cards', (c) => c.json(cardsPayload(projectDir, owner)));
|
|
91
|
+
// Approve and reject go through the same engine as the CLI, as the owner.
|
|
92
|
+
const decide = (run) => async (c) => {
|
|
93
|
+
if (!owner)
|
|
94
|
+
return c.json({ error: 'read-only: start the server with `codeloop serve --owner` to approve or reject from the board' }, 403);
|
|
95
|
+
const body = await c.req.json().catch(() => ({ note: undefined }));
|
|
96
|
+
try {
|
|
97
|
+
run(c.req.param('id'), body.note ?? '');
|
|
98
|
+
}
|
|
99
|
+
catch (e) {
|
|
100
|
+
if (e instanceof RefusalError)
|
|
101
|
+
return c.json({ error: e.message }, 400);
|
|
102
|
+
if (e instanceof ConflictError)
|
|
103
|
+
return c.json({ error: e.message }, 409);
|
|
104
|
+
throw e;
|
|
105
|
+
}
|
|
106
|
+
broadcastCards();
|
|
107
|
+
return c.json(cardsPayload(projectDir, owner));
|
|
108
|
+
};
|
|
109
|
+
app.post('/api/cards/:id/approve', decide((id, note) => void approveFlow(projectDir, id, 'owner', note || undefined)));
|
|
110
|
+
app.post('/api/cards/:id/reject', decide((id, note) => void rejectCard(projectDir, id, 'owner', note)));
|
|
111
|
+
// The mock gallery and each mock, straight from docs/mocks. Read-only, and nothing outside that folder.
|
|
112
|
+
app.get('/mocks/*', (c) => {
|
|
113
|
+
const root = resolve(projectDir, MOCKS_DIR);
|
|
114
|
+
let wanted;
|
|
115
|
+
try {
|
|
116
|
+
wanted = decodeURIComponent(c.req.path.replace(/^\/mocks\/?/, '')) || 'index.html';
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
return c.text('Not found', 404);
|
|
120
|
+
}
|
|
121
|
+
const file = resolve(root, wanted);
|
|
122
|
+
if (!file.startsWith(root + sep) || !existsSync(file) || !statSync(file).isFile())
|
|
123
|
+
return c.text('Not found', 404);
|
|
124
|
+
return new Response(readFileSync(file), { headers: { 'Content-Type': MIME_TYPES[extname(file)] || 'application/octet-stream' } });
|
|
125
|
+
});
|
|
126
|
+
app.get('/mocks', (c) => c.redirect('/mocks/'));
|
|
127
|
+
// GET /api/board — full board
|
|
128
|
+
app.get('/api/board', (c) => {
|
|
129
|
+
const board = loadBoard(projectDir);
|
|
130
|
+
return c.json(board);
|
|
131
|
+
});
|
|
132
|
+
// POST /api/tasks — create task
|
|
133
|
+
app.post('/api/tasks', async (c) => {
|
|
134
|
+
const body = await c.req.json();
|
|
135
|
+
let board = loadBoard(projectDir);
|
|
136
|
+
board = addTask(board, body);
|
|
137
|
+
saveBoard(projectDir, board);
|
|
138
|
+
const task = board.tasks[board.tasks.length - 1];
|
|
139
|
+
broadcast();
|
|
140
|
+
return c.json(task, 201);
|
|
141
|
+
});
|
|
142
|
+
// PATCH /api/tasks/:id — update task
|
|
143
|
+
app.patch('/api/tasks/:id', async (c) => {
|
|
144
|
+
const id = c.req.param('id');
|
|
145
|
+
const patch = await c.req.json();
|
|
146
|
+
let board = loadBoard(projectDir);
|
|
147
|
+
try {
|
|
148
|
+
board = updateTask(board, id, patch);
|
|
149
|
+
}
|
|
150
|
+
catch (e) {
|
|
151
|
+
return c.json({ error: e.message }, 404);
|
|
152
|
+
}
|
|
153
|
+
saveBoard(projectDir, board);
|
|
154
|
+
const task = getTask(board, id);
|
|
155
|
+
broadcast();
|
|
156
|
+
return c.json(task);
|
|
157
|
+
});
|
|
158
|
+
// DELETE /api/tasks/:id — remove task
|
|
159
|
+
app.delete('/api/tasks/:id', (c) => {
|
|
160
|
+
const id = c.req.param('id');
|
|
161
|
+
let board = loadBoard(projectDir);
|
|
162
|
+
try {
|
|
163
|
+
board = deleteTask(board, id);
|
|
164
|
+
}
|
|
165
|
+
catch (e) {
|
|
166
|
+
return c.json({ error: e.message }, 404);
|
|
167
|
+
}
|
|
168
|
+
saveBoard(projectDir, board);
|
|
169
|
+
broadcast();
|
|
170
|
+
return c.json({ ok: true });
|
|
171
|
+
});
|
|
172
|
+
// GET /api/events — SSE stream
|
|
173
|
+
app.get('/api/events', (c) => {
|
|
174
|
+
return streamSSE(c, async (stream) => {
|
|
175
|
+
// Send initial board state
|
|
176
|
+
const board = loadBoard(projectDir);
|
|
177
|
+
await stream.writeSSE({ data: JSON.stringify(board), event: 'board' });
|
|
178
|
+
// Register for broadcasts
|
|
179
|
+
const handler = async (board) => {
|
|
180
|
+
try {
|
|
181
|
+
await stream.writeSSE({ data: JSON.stringify(board), event: 'board' });
|
|
182
|
+
}
|
|
183
|
+
catch {
|
|
184
|
+
// Client disconnected
|
|
185
|
+
sseClients.delete(handler);
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
sseClients.add(handler);
|
|
189
|
+
const sendCards = async (payload) => {
|
|
190
|
+
try {
|
|
191
|
+
await stream.writeSSE({ data: payload, event: 'cards' });
|
|
192
|
+
}
|
|
193
|
+
catch {
|
|
194
|
+
cardClients.delete(sendCards);
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
await sendCards(JSON.stringify(cardsPayload(projectDir, owner)));
|
|
198
|
+
cardClients.add(sendCards);
|
|
199
|
+
// Keep alive until client disconnects
|
|
200
|
+
await new Promise((resolve) => {
|
|
201
|
+
stream.onAbort(() => {
|
|
202
|
+
sseClients.delete(handler);
|
|
203
|
+
cardClients.delete(sendCards);
|
|
204
|
+
resolve();
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
// Static file serving for the UI
|
|
210
|
+
if (uiDir) {
|
|
211
|
+
app.get('*', (c) => {
|
|
212
|
+
const urlPath = c.req.path === '/' ? '/index.html' : c.req.path;
|
|
213
|
+
const filePath = join(uiDir, urlPath);
|
|
214
|
+
if (existsSync(filePath)) {
|
|
215
|
+
const content = readFileSync(filePath);
|
|
216
|
+
const ext = extname(filePath);
|
|
217
|
+
const mime = MIME_TYPES[ext] || 'application/octet-stream';
|
|
218
|
+
return new Response(content, {
|
|
219
|
+
headers: { 'Content-Type': mime },
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
// SPA fallback — serve index.html for unmatched routes
|
|
223
|
+
const indexPath = join(uiDir, 'index.html');
|
|
224
|
+
if (existsSync(indexPath)) {
|
|
225
|
+
const content = readFileSync(indexPath);
|
|
226
|
+
return new Response(content, {
|
|
227
|
+
headers: { 'Content-Type': 'text/html' },
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
return c.text('Not found', 404);
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
return { app, broadcast, broadcastCards, token };
|
|
234
|
+
}
|
|
235
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/lib/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function checkEnv(entry?: string | undefined): NodeJS.ProcessEnv;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { chmodSync, mkdtempSync, rmSync, writeFileSync } from 'fs';
|
|
2
|
+
import { tmpdir } from 'os';
|
|
3
|
+
import { delimiter, join } from 'path';
|
|
4
|
+
const shims = new Map();
|
|
5
|
+
// Lane checks call `codeloop check ...`. The CLI is often run via npx or a local build and is not
|
|
6
|
+
// on PATH, so checks run with a shim that points back at the entry script of this process.
|
|
7
|
+
// The shim goes first on PATH, so its directory must be one nobody else can write to: mkdtemp
|
|
8
|
+
// gives a fresh 0700 directory with an unguessable name, removed when this process exits.
|
|
9
|
+
export function checkEnv(entry = process.argv[1]) {
|
|
10
|
+
if (!entry)
|
|
11
|
+
return { ...process.env, CODELOOP_NO_SYNC: '1' };
|
|
12
|
+
let dir = shims.get(entry);
|
|
13
|
+
if (!dir) {
|
|
14
|
+
dir = mkdtempSync(join(tmpdir(), 'codeloop-shim-'));
|
|
15
|
+
const shim = join(dir, 'codeloop');
|
|
16
|
+
writeFileSync(shim, `#!/bin/sh\nexec "${process.execPath}" "${entry}" "$@"\n`);
|
|
17
|
+
chmodSync(shim, 0o700);
|
|
18
|
+
if (shims.size === 0)
|
|
19
|
+
process.on('exit', () => shims.forEach(d => rmSync(d, { recursive: true, force: true })));
|
|
20
|
+
shims.set(entry, dir);
|
|
21
|
+
}
|
|
22
|
+
// The command that started this check or agent has already synced with the cloud.
|
|
23
|
+
return { ...process.env, CODELOOP_NO_SYNC: '1', PATH: `${dir}${delimiter}${process.env.PATH ?? ''}` };
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=shell.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shell.js","sourceRoot":"","sources":["../../src/lib/shell.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AACnE,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AAC5B,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAEvC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;AAExC,kGAAkG;AAClG,2FAA2F;AAC3F,8FAA8F;AAC9F,0FAA0F;AAC1F,MAAM,UAAU,QAAQ,CAAC,QAA4B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IAClE,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,gBAAgB,EAAE,GAAG,EAAE,CAAC;IAC7D,IAAI,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAC3B,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC;QACpD,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;QACnC,aAAa,CAAC,IAAI,EAAE,oBAAoB,OAAO,CAAC,QAAQ,MAAM,KAAK,UAAU,CAAC,CAAC;QAC/E,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACvB,IAAI,KAAK,CAAC,IAAI,KAAK,CAAC;YAAE,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAChH,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACxB,CAAC;IACD,kFAAkF;IAClF,OAAO,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,gBAAgB,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,GAAG,GAAG,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,EAAE,EAAE,CAAC;AACxG,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type Lane, type SkillEntry } from './lane.js';
|
|
2
|
+
export declare function defaultSkillDirs(projectDir: string): string[];
|
|
3
|
+
export declare function parseFrontmatter(text: string): {
|
|
4
|
+
data: Record<string, unknown>;
|
|
5
|
+
body: string;
|
|
6
|
+
};
|
|
7
|
+
/** `<name>/SKILL.md` is a skill; `*.md` is a command; `<group>/*.md` is the command `group:name`. */
|
|
8
|
+
export declare function scanSkills(projectDir: string, dirs: string[]): SkillEntry[];
|
|
9
|
+
export declare function writeSkillsIndex(projectDir: string, entries: SkillEntry[]): void;
|
|
10
|
+
/** Writes the index only when there is none: an existing one may hold entries from `adopt --from`. */
|
|
11
|
+
export declare function ensureSkillsIndex(projectDir: string, scan: () => SkillEntry[]): void;
|
|
12
|
+
export declare function duplicateSkills(entries: SkillEntry[]): {
|
|
13
|
+
name: string;
|
|
14
|
+
sources: string[];
|
|
15
|
+
}[];
|
|
16
|
+
export declare function doneGaps(lanes: Lane[]): {
|
|
17
|
+
lane: string;
|
|
18
|
+
stage: string;
|
|
19
|
+
reason: string;
|
|
20
|
+
}[];
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { existsSync, readdirSync, readFileSync, statSync, writeFileSync } from 'fs';
|
|
2
|
+
import { homedir } from 'os';
|
|
3
|
+
import { basename, join, relative, resolve } from 'path';
|
|
4
|
+
import { parse as parseYaml, stringify } from 'yaml';
|
|
5
|
+
import { SKILLS_INDEX } from './lane.js';
|
|
6
|
+
import { withLock } from './lock.js';
|
|
7
|
+
export function defaultSkillDirs(projectDir) {
|
|
8
|
+
return [
|
|
9
|
+
join(projectDir, '.claude/skills'),
|
|
10
|
+
join(projectDir, '.claude/commands'),
|
|
11
|
+
join(projectDir, '.cursor/commands'),
|
|
12
|
+
join(projectDir, '.agents/skills'),
|
|
13
|
+
join(homedir(), '.claude/skills'),
|
|
14
|
+
join(homedir(), '.claude/commands'),
|
|
15
|
+
];
|
|
16
|
+
}
|
|
17
|
+
export function parseFrontmatter(text) {
|
|
18
|
+
const m = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/.exec(text);
|
|
19
|
+
if (!m)
|
|
20
|
+
return { data: {}, body: text };
|
|
21
|
+
try {
|
|
22
|
+
return { data: (parseYaml(m[1]) ?? {}), body: m[2] };
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
// Command frontmatter in the wild is not always valid YAML (unquoted colons in descriptions).
|
|
26
|
+
const data = {};
|
|
27
|
+
for (const line of m[1].split('\n')) {
|
|
28
|
+
const kv = /^(\w[\w-]*):\s*(.*)$/.exec(line);
|
|
29
|
+
if (kv)
|
|
30
|
+
data[kv[1]] = kv[2];
|
|
31
|
+
}
|
|
32
|
+
return { data, body: m[2] };
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function entry(projectDir, file, kind, fallbackName) {
|
|
36
|
+
const { data } = parseFrontmatter(readFileSync(file, 'utf-8'));
|
|
37
|
+
const inProject = !relative(projectDir, file).startsWith('..');
|
|
38
|
+
return {
|
|
39
|
+
name: typeof data.name === 'string' && data.name ? data.name : fallbackName,
|
|
40
|
+
source: inProject ? relative(projectDir, file) : file,
|
|
41
|
+
kind,
|
|
42
|
+
description: typeof data.description === 'string' ? data.description.trim() : '',
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
const isDir = (p) => statSync(p).isDirectory();
|
|
46
|
+
/** `<name>/SKILL.md` is a skill; `*.md` is a command; `<group>/*.md` is the command `group:name`. */
|
|
47
|
+
export function scanSkills(projectDir, dirs) {
|
|
48
|
+
const found = [];
|
|
49
|
+
for (const dir of dirs.map(d => resolve(projectDir, d))) {
|
|
50
|
+
if (!existsSync(dir))
|
|
51
|
+
continue;
|
|
52
|
+
for (const name of readdirSync(dir).sort()) {
|
|
53
|
+
const path = join(dir, name);
|
|
54
|
+
if (name.endsWith('.md') && !isDir(path)) {
|
|
55
|
+
found.push(entry(projectDir, path, 'command', basename(name, '.md')));
|
|
56
|
+
}
|
|
57
|
+
else if (isDir(path) && existsSync(join(path, 'SKILL.md'))) {
|
|
58
|
+
found.push(entry(projectDir, join(path, 'SKILL.md'), 'skill', name));
|
|
59
|
+
}
|
|
60
|
+
else if (isDir(path)) {
|
|
61
|
+
for (const sub of readdirSync(path).filter(f => f.endsWith('.md')).sort()) {
|
|
62
|
+
found.push(entry(projectDir, join(path, sub), 'command', `${name}:${basename(sub, '.md')}`));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return found;
|
|
68
|
+
}
|
|
69
|
+
export function writeSkillsIndex(projectDir, entries) {
|
|
70
|
+
const file = join(projectDir, SKILLS_INDEX);
|
|
71
|
+
withLock(file, () => writeFileSync(file, stringify(entries)));
|
|
72
|
+
}
|
|
73
|
+
/** Writes the index only when there is none: an existing one may hold entries from `adopt --from`. */
|
|
74
|
+
export function ensureSkillsIndex(projectDir, scan) {
|
|
75
|
+
const file = join(projectDir, SKILLS_INDEX);
|
|
76
|
+
withLock(file, () => {
|
|
77
|
+
if (!existsSync(file))
|
|
78
|
+
writeFileSync(file, stringify(scan()));
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
export function duplicateSkills(entries) {
|
|
82
|
+
const byName = new Map();
|
|
83
|
+
for (const e of entries)
|
|
84
|
+
byName.set(e.name, [...(byName.get(e.name) ?? []), e.source]);
|
|
85
|
+
return [...byName].filter(([, sources]) => sources.length > 1).map(([name, sources]) => ({ name, sources }));
|
|
86
|
+
}
|
|
87
|
+
export function doneGaps(lanes) {
|
|
88
|
+
return lanes.flatMap(lane => lane.stages
|
|
89
|
+
.filter(s => !s.done?.cmd)
|
|
90
|
+
.map(s => ({ lane: lane.id, stage: s.id, reason: s.done?.event ? `done is only the event "${s.done.event}"` : 'no done check' })));
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=skills.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/lib/skills.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type Role } from './engine.js';
|
|
2
|
+
export declare const LAYERS: readonly ["api", "sdk", "ui", "test", "docs"];
|
|
3
|
+
export interface Task {
|
|
4
|
+
id: string;
|
|
5
|
+
done: boolean;
|
|
6
|
+
parallel: boolean;
|
|
7
|
+
accept?: string;
|
|
8
|
+
layer: string;
|
|
9
|
+
text: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function slugify(text: string): string;
|
|
12
|
+
/** `ref` is a card id or its number. A folder recorded on the card wins over a folder found by number. */
|
|
13
|
+
export declare function resolveSpecDir(projectDir: string, ref: string): string;
|
|
14
|
+
export declare function newSpec(projectDir: string, cardId: string, role?: Role): {
|
|
15
|
+
dir: string;
|
|
16
|
+
created: string[];
|
|
17
|
+
};
|
|
18
|
+
export declare function readTasks(projectDir: string, dir: string): {
|
|
19
|
+
tasks: Task[];
|
|
20
|
+
malformed: string[];
|
|
21
|
+
};
|
|
22
|
+
export declare function readAcceptance(projectDir: string, dir: string): string[];
|
|
23
|
+
export declare function checkSpec(projectDir: string, dir: string): string[];
|
|
24
|
+
export declare function tickTask(projectDir: string, dir: string, taskId: string): void;
|