@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,111 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { existsSync, readFileSync, writeFileSync, unlinkSync } from 'fs';
|
|
4
|
+
import { join } from 'path';
|
|
5
|
+
import { createWatchEngine, loadWatchConfig } from '../watch/index.js';
|
|
6
|
+
const PID_FILE = '.codeloop/.watch.pid';
|
|
7
|
+
export const watchCommand = new Command('watch')
|
|
8
|
+
.description('Watch project for changes, track progress on the board')
|
|
9
|
+
.option('--with-serve', 'Also start the board server')
|
|
10
|
+
.option('--stop', 'Stop background watcher')
|
|
11
|
+
.option('--bg', 'Run in background')
|
|
12
|
+
.action(async (options) => {
|
|
13
|
+
const projectDir = process.cwd();
|
|
14
|
+
// --stop: kill background watcher
|
|
15
|
+
if (options.stop) {
|
|
16
|
+
const pidPath = join(projectDir, PID_FILE);
|
|
17
|
+
if (!existsSync(pidPath)) {
|
|
18
|
+
console.log(chalk.dim(' Not running'));
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const pid = parseInt(readFileSync(pidPath, 'utf-8').trim(), 10);
|
|
22
|
+
try {
|
|
23
|
+
process.kill(pid);
|
|
24
|
+
console.log(chalk.green(` Stopped watcher (PID ${pid})`));
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
console.log(chalk.yellow(` Process ${pid} not found (already stopped?)`));
|
|
28
|
+
}
|
|
29
|
+
unlinkSync(pidPath);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
// Check project is initialized
|
|
33
|
+
const configPath = join(projectDir, '.codeloop', 'config.yaml');
|
|
34
|
+
if (!existsSync(configPath)) {
|
|
35
|
+
console.log(chalk.red(' No config.yaml found. Run `codeloop init` first.'));
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
const config = loadWatchConfig(projectDir);
|
|
39
|
+
if (!config.enabled) {
|
|
40
|
+
console.log(chalk.yellow(' Watch mode is disabled in config.yaml (watch.enabled: false)'));
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
// --bg: fork as background process
|
|
44
|
+
if (options.bg) {
|
|
45
|
+
const { fork } = await import('child_process');
|
|
46
|
+
const args = ['watch'];
|
|
47
|
+
if (options.withServe)
|
|
48
|
+
args.push('--with-serve');
|
|
49
|
+
const child = fork(process.argv[1], args, {
|
|
50
|
+
detached: true,
|
|
51
|
+
stdio: 'ignore',
|
|
52
|
+
});
|
|
53
|
+
child.unref();
|
|
54
|
+
if (child.pid) {
|
|
55
|
+
const pidPath = join(projectDir, PID_FILE);
|
|
56
|
+
writeFileSync(pidPath, String(child.pid), 'utf-8');
|
|
57
|
+
console.log(chalk.green(` Watcher started in background (PID ${child.pid})`));
|
|
58
|
+
}
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
// Foreground mode
|
|
62
|
+
let broadcastFn;
|
|
63
|
+
// --with-serve: also start board server
|
|
64
|
+
if (options.withServe) {
|
|
65
|
+
const { createApp } = await import('../lib/server.js');
|
|
66
|
+
const { serve } = await import('@hono/node-server');
|
|
67
|
+
const { app, broadcast } = createApp(projectDir);
|
|
68
|
+
broadcastFn = broadcast;
|
|
69
|
+
const port = 4040;
|
|
70
|
+
serve({ fetch: app.fetch, port }, () => {
|
|
71
|
+
console.log(chalk.bold(` Board: ${chalk.cyan(`http://localhost:${port}`)}`));
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
const engine = createWatchEngine(projectDir, broadcastFn);
|
|
75
|
+
console.log();
|
|
76
|
+
console.log(chalk.bold(' Codeloop Watch'));
|
|
77
|
+
const signals = Object.entries(config.signals)
|
|
78
|
+
.filter(([, v]) => v)
|
|
79
|
+
.map(([k]) => k);
|
|
80
|
+
console.log(chalk.dim(` Signals: ${signals.join(', ')}`));
|
|
81
|
+
console.log(chalk.dim(` Idle timeout: ${config.idle_timeout}s`));
|
|
82
|
+
console.log(chalk.dim(' Press Ctrl+C to stop'));
|
|
83
|
+
console.log();
|
|
84
|
+
engine.start();
|
|
85
|
+
// Graceful shutdown
|
|
86
|
+
const shutdown = () => {
|
|
87
|
+
console.log(chalk.dim('\n Stopping watcher...'));
|
|
88
|
+
engine.stop();
|
|
89
|
+
process.exit(0);
|
|
90
|
+
};
|
|
91
|
+
process.on('SIGINT', shutdown);
|
|
92
|
+
process.on('SIGTERM', shutdown);
|
|
93
|
+
});
|
|
94
|
+
export function getWatchStatus(projectDir) {
|
|
95
|
+
const pidPath = join(projectDir, PID_FILE);
|
|
96
|
+
if (!existsSync(pidPath))
|
|
97
|
+
return { running: false };
|
|
98
|
+
const pid = parseInt(readFileSync(pidPath, 'utf-8').trim(), 10);
|
|
99
|
+
try {
|
|
100
|
+
process.kill(pid, 0);
|
|
101
|
+
return { running: true, pid };
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
try {
|
|
105
|
+
unlinkSync(pidPath);
|
|
106
|
+
}
|
|
107
|
+
catch { /* ignore */ }
|
|
108
|
+
return { running: false };
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=watch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watch.js","sourceRoot":"","sources":["../../src/commands/watch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { addCompetitor, listCompetitors } from '../lib/competitors.js';
|
|
4
|
+
import { capture, inject, learn, lintWiki, listPages } from '../lib/wiki.js';
|
|
5
|
+
import { guard } from './guard.js';
|
|
6
|
+
const row = (p) => ` ${p.severity === 'critical' ? chalk.red('critical') : 'warning '} freq ${String(p.freq).padEnd(3)} ${p.title} ${chalk.dim(p.path)}`;
|
|
7
|
+
export const wikiCommand = new Command('wiki').description('Gotchas, decisions and concepts that agents read before a stage and write after it');
|
|
8
|
+
wikiCommand
|
|
9
|
+
.command('capture')
|
|
10
|
+
.description('Write a page; capturing an existing title raises its frequency')
|
|
11
|
+
.requiredOption('--title <title>', 'Page title')
|
|
12
|
+
.option('--scope <glob...>', 'File globs the page applies to', [])
|
|
13
|
+
.option('--body <text>', 'Page body', '')
|
|
14
|
+
.option('--kind <kind>', 'gotcha | decision | concept', 'gotcha')
|
|
15
|
+
.option('--card <id>', 'Card this came from')
|
|
16
|
+
.action(guard((opts) => {
|
|
17
|
+
console.log(row(capture(process.cwd(), opts)));
|
|
18
|
+
}));
|
|
19
|
+
wikiCommand
|
|
20
|
+
.command('inject')
|
|
21
|
+
.description('Print the pages whose scope matches the given files')
|
|
22
|
+
.requiredOption('--files <path...>', 'Changed or soon-to-change files')
|
|
23
|
+
.option('--json', 'JSON output')
|
|
24
|
+
.action(guard((opts) => {
|
|
25
|
+
const pages = inject(process.cwd(), opts.files);
|
|
26
|
+
if (opts.json) {
|
|
27
|
+
console.log(JSON.stringify(pages, null, 2));
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
for (const p of pages)
|
|
31
|
+
console.log(`## ${p.title} (${p.kind}, freq ${p.freq}, ${p.severity})\n\n${p.body}\n`);
|
|
32
|
+
if (pages.length === 0)
|
|
33
|
+
console.log(' no wiki pages apply to these files');
|
|
34
|
+
}));
|
|
35
|
+
wikiCommand
|
|
36
|
+
.command('list')
|
|
37
|
+
.description('List pages')
|
|
38
|
+
.action(guard(() => {
|
|
39
|
+
const pages = listPages(process.cwd());
|
|
40
|
+
if (pages.length === 0)
|
|
41
|
+
console.log(' no wiki pages');
|
|
42
|
+
pages.forEach(p => console.log(row(p)));
|
|
43
|
+
}));
|
|
44
|
+
wikiCommand
|
|
45
|
+
.command('lint')
|
|
46
|
+
.description('Report broken links (exit 1), stale pages and duplicate titles')
|
|
47
|
+
.action(guard(() => {
|
|
48
|
+
const { broken, stale, duplicates } = lintWiki(process.cwd());
|
|
49
|
+
broken.forEach(b => console.error(chalk.red(` broken: ${b}`)));
|
|
50
|
+
stale.forEach(s => console.log(chalk.yellow(` stale: ${s}`)));
|
|
51
|
+
duplicates.forEach(d => console.log(chalk.yellow(` duplicate: ${d}`)));
|
|
52
|
+
if (broken.length)
|
|
53
|
+
process.exit(1);
|
|
54
|
+
console.log(` wiki ok${stale.length + duplicates.length ? ` (${stale.length} stale, ${duplicates.length} duplicate)` : ''}`);
|
|
55
|
+
}));
|
|
56
|
+
const competitorCommand = wikiCommand.command('competitor').description('One wiki page per competitor: links at the top, findings from each research stage below');
|
|
57
|
+
competitorCommand
|
|
58
|
+
.command('add <name>')
|
|
59
|
+
.description('Create .codeloop/wiki/competitors/<name>.md, or update the links of an existing page')
|
|
60
|
+
.option('--docs <url>', 'Where their product docs are')
|
|
61
|
+
.option('--changelog <url>', 'Where they announce what shipped; `codeloop scan competitors` reads it')
|
|
62
|
+
.option('--title <title>', 'Display name (default: the name)')
|
|
63
|
+
.action(guard((name, opts) => {
|
|
64
|
+
const page = addCompetitor(process.cwd(), { name, ...opts });
|
|
65
|
+
console.log(` ${page.path} ${chalk.dim(`docs ${page.docs ?? '-'} changelog ${page.changelog ?? '-'}`)}`);
|
|
66
|
+
}));
|
|
67
|
+
competitorCommand
|
|
68
|
+
.command('list')
|
|
69
|
+
.description('List competitor pages')
|
|
70
|
+
.action(guard(() => {
|
|
71
|
+
const pages = listCompetitors(process.cwd());
|
|
72
|
+
if (pages.length === 0)
|
|
73
|
+
console.log(' no competitor pages; `codeloop wiki competitor add <name> --docs <url> --changelog <url>`');
|
|
74
|
+
pages.forEach(c => console.log(` ${c.title.padEnd(16)} ${chalk.dim(c.path)} changelog ${c.changelog ?? '-'}`));
|
|
75
|
+
}));
|
|
76
|
+
export const learnCommand = new Command('learn')
|
|
77
|
+
.description('Apply frequency thresholds: critical at critical_frequency, promoted to rules.md at promote_frequency')
|
|
78
|
+
.action(guard(() => {
|
|
79
|
+
const { critical, promoted } = learn(process.cwd());
|
|
80
|
+
critical.forEach(t => console.log(` now critical: ${t}`));
|
|
81
|
+
promoted.forEach(t => console.log(` promoted to .codeloop/rules.md: ${t}`));
|
|
82
|
+
if (critical.length + promoted.length === 0)
|
|
83
|
+
console.log(' nothing crossed a threshold');
|
|
84
|
+
}));
|
|
85
|
+
//# sourceMappingURL=wiki.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wiki.js","sourceRoot":"","sources":["../../src/commands/wiki.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import { initCommand } from './commands/init.js';
|
|
4
|
+
import { updateCommand } from './commands/update.js';
|
|
5
|
+
import { statusCommand } from './commands/status.js';
|
|
6
|
+
import { serveCommand } from './commands/serve.js';
|
|
7
|
+
import { watchCommand } from './commands/watch.js';
|
|
8
|
+
import { installCommand } from './commands/install.js';
|
|
9
|
+
import { searchCommand } from './commands/search.js';
|
|
10
|
+
import { listCommand } from './commands/list.js';
|
|
11
|
+
import { removeCommand } from './commands/remove.js';
|
|
12
|
+
import { publishCommand } from './commands/publish.js';
|
|
13
|
+
import { loginCommand } from './commands/login.js';
|
|
14
|
+
import { laneCommand } from './commands/lane.js';
|
|
15
|
+
import { approveCommand, cardCommand, nextCommand, rejectCommand, startCommand } from './commands/card.js';
|
|
16
|
+
import { inboxCommand } from './commands/inbox.js';
|
|
17
|
+
import { runCommand } from './commands/run.js';
|
|
18
|
+
import { briefCommand } from './commands/brief.js';
|
|
19
|
+
import { scheduleCommand } from './commands/schedule.js';
|
|
20
|
+
import { adoptCommand } from './commands/adopt.js';
|
|
21
|
+
import { checkCommand } from './commands/check.js';
|
|
22
|
+
import { packCommand } from './commands/pack.js';
|
|
23
|
+
import { specCommand, taskCommand } from './commands/spec.js';
|
|
24
|
+
import { importCommand } from './commands/import.js';
|
|
25
|
+
import { statsCommand, verifyCommand } from './commands/verify.js';
|
|
26
|
+
import { learnCommand, wikiCommand } from './commands/wiki.js';
|
|
27
|
+
import { configCommand, gateCommand, mcpCommand, renderCommand } from './commands/render.js';
|
|
28
|
+
import { cloudCommand, syncBeforeCommand } from './commands/cloud.js';
|
|
29
|
+
import { mockCommand, mocksCommand } from './commands/mock.js';
|
|
30
|
+
import { scanCommand } from './commands/scan.js';
|
|
31
|
+
const program = new Command();
|
|
32
|
+
program
|
|
33
|
+
.name('codeloop')
|
|
34
|
+
.description('Self-improving development workflow for AI coding agents')
|
|
35
|
+
.version('0.3.0');
|
|
36
|
+
// With the cloud connected, every command first pushes pending writes and takes what changed there.
|
|
37
|
+
program.hook('preAction', (_program, action) => {
|
|
38
|
+
let top = action;
|
|
39
|
+
while (top.parent && top.parent !== program)
|
|
40
|
+
top = top.parent;
|
|
41
|
+
syncBeforeCommand(top.name());
|
|
42
|
+
});
|
|
43
|
+
// Project management
|
|
44
|
+
program.addCommand(initCommand);
|
|
45
|
+
program.addCommand(updateCommand);
|
|
46
|
+
program.addCommand(statusCommand);
|
|
47
|
+
program.addCommand(serveCommand);
|
|
48
|
+
program.addCommand(watchCommand);
|
|
49
|
+
// Lane engine
|
|
50
|
+
program.addCommand(laneCommand);
|
|
51
|
+
program.addCommand(cardCommand);
|
|
52
|
+
program.addCommand(startCommand);
|
|
53
|
+
program.addCommand(nextCommand);
|
|
54
|
+
program.addCommand(approveCommand);
|
|
55
|
+
program.addCommand(rejectCommand);
|
|
56
|
+
program.addCommand(inboxCommand);
|
|
57
|
+
program.addCommand(runCommand);
|
|
58
|
+
program.addCommand(briefCommand);
|
|
59
|
+
program.addCommand(scheduleCommand);
|
|
60
|
+
program.addCommand(adoptCommand);
|
|
61
|
+
program.addCommand(checkCommand);
|
|
62
|
+
program.addCommand(packCommand);
|
|
63
|
+
program.addCommand(specCommand);
|
|
64
|
+
program.addCommand(mockCommand);
|
|
65
|
+
program.addCommand(mocksCommand);
|
|
66
|
+
program.addCommand(scanCommand);
|
|
67
|
+
program.addCommand(taskCommand);
|
|
68
|
+
program.addCommand(importCommand);
|
|
69
|
+
program.addCommand(verifyCommand);
|
|
70
|
+
program.addCommand(statsCommand);
|
|
71
|
+
program.addCommand(wikiCommand);
|
|
72
|
+
program.addCommand(learnCommand);
|
|
73
|
+
program.addCommand(renderCommand);
|
|
74
|
+
program.addCommand(mcpCommand);
|
|
75
|
+
program.addCommand(gateCommand);
|
|
76
|
+
program.addCommand(configCommand);
|
|
77
|
+
program.addCommand(cloudCommand);
|
|
78
|
+
// Skill registry
|
|
79
|
+
program.addCommand(installCommand);
|
|
80
|
+
program.addCommand(searchCommand);
|
|
81
|
+
program.addCommand(listCommand);
|
|
82
|
+
program.addCommand(removeCommand);
|
|
83
|
+
program.addCommand(publishCommand);
|
|
84
|
+
program.addCommand(loginCommand);
|
|
85
|
+
program.parse();
|
|
86
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type Card } from './cards.js';
|
|
2
|
+
export declare const BRIEFS_DIR = ".codeloop/state/briefs";
|
|
3
|
+
export declare const AGENT_RUNS_DIR = ".codeloop/state/agent-runs";
|
|
4
|
+
export interface AgentConfig {
|
|
5
|
+
name: string;
|
|
6
|
+
cmd: string;
|
|
7
|
+
timeoutMinutes: number;
|
|
8
|
+
maxRunsPerDay: number;
|
|
9
|
+
}
|
|
10
|
+
export interface AgentsConfig {
|
|
11
|
+
agents: Record<string, AgentConfig>;
|
|
12
|
+
default?: string;
|
|
13
|
+
/** `run.agent: true`: a plain `codeloop run` starts agents too. */
|
|
14
|
+
runByDefault: boolean;
|
|
15
|
+
}
|
|
16
|
+
export declare function loadAgents(projectDir: string): AgentsConfig;
|
|
17
|
+
export declare function resolveAgent(projectDir: string, name?: string): AgentConfig;
|
|
18
|
+
export declare function briefPath(card: Card): string;
|
|
19
|
+
/** Everything a headless agent is given to do the card's current stage. */
|
|
20
|
+
export declare function buildBrief(projectDir: string, card: Card): string;
|
|
21
|
+
export interface AgentRun {
|
|
22
|
+
exit: number | null;
|
|
23
|
+
timedOut: boolean;
|
|
24
|
+
durationMs: number;
|
|
25
|
+
}
|
|
26
|
+
/** Runs the agent command in the project with `{brief}` filled in. Output goes to `logFile`. */
|
|
27
|
+
export declare function runAgent(projectDir: string, agent: AgentConfig, briefFile: string, logFile: string): Promise<AgentRun>;
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { spawn } from 'child_process';
|
|
2
|
+
import { closeSync, existsSync, mkdirSync, openSync, readdirSync, readFileSync, readSync, statSync, writeFileSync } from 'fs';
|
|
3
|
+
import { dirname, isAbsolute, join } from 'path';
|
|
4
|
+
import { RefusalError, safeName } from './cards.js';
|
|
5
|
+
import { listCompetitors } from './competitors.js';
|
|
6
|
+
import { loadConfig } from './config.js';
|
|
7
|
+
import { stageBrief } from './flow.js';
|
|
8
|
+
import { loadLane, loadSkillsIndex, shellQuote, SKILLS_INDEX } from './lane.js';
|
|
9
|
+
import { checkEnv } from './shell.js';
|
|
10
|
+
import { parseFrontmatter } from './skills.js';
|
|
11
|
+
import { readTasks } from './spec.js';
|
|
12
|
+
import { inject } from './wiki.js';
|
|
13
|
+
export const BRIEFS_DIR = '.codeloop/state/briefs';
|
|
14
|
+
export const AGENT_RUNS_DIR = '.codeloop/state/agent-runs';
|
|
15
|
+
const DEFAULT_TIMEOUT_MINUTES = 20;
|
|
16
|
+
const DEFAULT_MAX_RUNS_PER_DAY = 20;
|
|
17
|
+
const LOG_TAIL_BYTES = 64_000;
|
|
18
|
+
export function loadAgents(projectDir) {
|
|
19
|
+
const raw = loadConfig(projectDir);
|
|
20
|
+
const agents = {};
|
|
21
|
+
for (const [name, value] of Object.entries((raw.agents ?? {}))) {
|
|
22
|
+
if (name === 'default')
|
|
23
|
+
continue;
|
|
24
|
+
if (typeof value?.cmd !== 'string' || !value.cmd.trim())
|
|
25
|
+
throw new RefusalError(`agents.${name} in .codeloop/config.yaml has no cmd`);
|
|
26
|
+
agents[name] = {
|
|
27
|
+
name,
|
|
28
|
+
cmd: value.cmd,
|
|
29
|
+
timeoutMinutes: Number(value.timeout_minutes ?? DEFAULT_TIMEOUT_MINUTES),
|
|
30
|
+
maxRunsPerDay: Number(value.max_runs_per_day ?? DEFAULT_MAX_RUNS_PER_DAY),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
return { agents, default: raw.agents?.default, runByDefault: raw.run?.agent === true };
|
|
34
|
+
}
|
|
35
|
+
export function resolveAgent(projectDir, name) {
|
|
36
|
+
const config = loadAgents(projectDir);
|
|
37
|
+
const names = Object.keys(config.agents);
|
|
38
|
+
if (names.length === 0)
|
|
39
|
+
throw new RefusalError('no agent is configured; add `agents:` to .codeloop/config.yaml (the starter config has presets for claude and codex)');
|
|
40
|
+
const wanted = name ?? config.default ?? (names.length === 1 ? names[0] : undefined);
|
|
41
|
+
if (!wanted)
|
|
42
|
+
throw new RefusalError(`several agents are configured (${names.join(', ')}); name one or set agents.default`);
|
|
43
|
+
const agent = config.agents[wanted];
|
|
44
|
+
if (!agent)
|
|
45
|
+
throw new RefusalError(`agent "${wanted}" is not in .codeloop/config.yaml (configured: ${names.join(', ')})`);
|
|
46
|
+
return agent;
|
|
47
|
+
}
|
|
48
|
+
export function briefPath(card) {
|
|
49
|
+
return `${BRIEFS_DIR}/${card.id}-${safeName(card.stage, 'stage id')}.md`;
|
|
50
|
+
}
|
|
51
|
+
function skillBody(projectDir, name) {
|
|
52
|
+
const source = loadSkillsIndex(projectDir)?.find(s => s.name === name)?.source;
|
|
53
|
+
if (!source)
|
|
54
|
+
return null;
|
|
55
|
+
const file = isAbsolute(source) ? source : join(projectDir, source);
|
|
56
|
+
return existsSync(file) ? parseFrontmatter(readFileSync(file, 'utf-8')).body.trim() : null;
|
|
57
|
+
}
|
|
58
|
+
// The stage output, what is already in the card's spec folder, and the paths its open tasks name.
|
|
59
|
+
function filesInScope(projectDir, card, output) {
|
|
60
|
+
const files = output ? [output] : [];
|
|
61
|
+
if (card.spec && existsSync(join(projectDir, card.spec))) {
|
|
62
|
+
files.push(...readdirSync(join(projectDir, card.spec)).map(f => `${card.spec}/${f}`));
|
|
63
|
+
if (existsSync(join(projectDir, card.spec, 'tasks.md'))) {
|
|
64
|
+
for (const task of readTasks(projectDir, card.spec).tasks.filter(t => !t.done)) {
|
|
65
|
+
files.push(...(task.text.match(/(?:[\w.-]+\/)+[\w.-]+/g) ?? []));
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return [...new Set(files)];
|
|
70
|
+
}
|
|
71
|
+
/** Everything a headless agent is given to do the card's current stage. */
|
|
72
|
+
export function buildBrief(projectDir, card) {
|
|
73
|
+
const stage = stageBrief(projectDir, card);
|
|
74
|
+
if (!stage)
|
|
75
|
+
throw new RefusalError(`card ${card.id} has no stage to brief (it is ${card.stage})`);
|
|
76
|
+
const lane = loadLane(projectDir, card.lane);
|
|
77
|
+
const events = card.events.filter(e => e.stage === card.stage);
|
|
78
|
+
const lines = [
|
|
79
|
+
`# Stage brief: ${card.id} ${card.stage}`,
|
|
80
|
+
'',
|
|
81
|
+
`Card: ${card.id}`,
|
|
82
|
+
`Title: ${card.title}`,
|
|
83
|
+
`Lane: ${lane.id} (version ${lane.version})`,
|
|
84
|
+
`Stage: ${card.stage}`,
|
|
85
|
+
...(stage.skill ? [`Skill: ${stage.skill}`] : []),
|
|
86
|
+
...(stage.output ? [`Output: ${stage.output}`] : []),
|
|
87
|
+
'',
|
|
88
|
+
'## The check that must pass',
|
|
89
|
+
'',
|
|
90
|
+
`The stage is finished when this command, run from the project root, exits 0${stage.output ? `. It judges ${stage.output}, which this stage writes` : ''}:`,
|
|
91
|
+
'',
|
|
92
|
+
` ${stage.done}`,
|
|
93
|
+
'',
|
|
94
|
+
];
|
|
95
|
+
const failed = events.filter(e => e.action === 'fail' || e.action === 'stuck').at(-1);
|
|
96
|
+
if (stage.notes.length || stage.rejections.length || failed?.note) {
|
|
97
|
+
lines.push('## Feedback on this stage', '');
|
|
98
|
+
for (const note of stage.notes)
|
|
99
|
+
lines.push(`- Stage note: ${note}`);
|
|
100
|
+
stage.rejections.forEach((note, i) => lines.push(`- ${i === stage.rejections.length - 1 ? 'Latest rejection' : 'Earlier rejection'}: ${note}`));
|
|
101
|
+
if (failed?.note)
|
|
102
|
+
lines.push('', `The check last failed${failed.action === 'stuck' ? ' and the card was marked stuck' : ''} with:`, '', ...failed.note.split('\n').map(l => ` ${l}`));
|
|
103
|
+
lines.push('');
|
|
104
|
+
}
|
|
105
|
+
if (stage.skill) {
|
|
106
|
+
const body = skillBody(projectDir, stage.skill);
|
|
107
|
+
lines.push(`## Skill: ${stage.skill}`, '', body ?? `The skill's text is not in ${SKILLS_INDEX}; use the /${stage.skill} skill if your tool has it.`, '');
|
|
108
|
+
}
|
|
109
|
+
const pages = inject(projectDir, filesInScope(projectDir, card, stage.output));
|
|
110
|
+
if (pages.length) {
|
|
111
|
+
lines.push('## Wiki pages that apply', '');
|
|
112
|
+
for (const p of pages)
|
|
113
|
+
lines.push(`### ${p.title} (${p.kind}, freq ${p.freq}, ${p.severity})`, '', p.body, '');
|
|
114
|
+
}
|
|
115
|
+
const competitors = card.stage === 'research' ? listCompetitors(projectDir) : [];
|
|
116
|
+
if (competitors.length) {
|
|
117
|
+
lines.push('## Competitors', '', `Read each one's docs and changelog for this feature. Give each a row in ${stage.output ?? 'the research file'} that starts with its name: the row is copied to its page when the stage passes.`, '');
|
|
118
|
+
for (const c of competitors)
|
|
119
|
+
lines.push(`### ${c.title} (${c.path})`, '', ...(c.docs ? [`Docs: ${c.docs}`] : []), ...(c.changelog ? [`Changelog: ${c.changelog}`] : []), '', c.body, '');
|
|
120
|
+
}
|
|
121
|
+
lines.push('## Rules', '', `- Do only the ${card.stage} stage of ${card.id}.`, stage.output ? `- Write the output to ${stage.output}.` : '- Leave the project in the state the check asks for.', '- Do not run `codeloop approve`, `codeloop next` or `codeloop card advance`. The run that started you checks the work and moves the card.', '- Do not edit .codeloop/cards.json or anything in .codeloop/lanes/.', '- Stop when the output is written.', '');
|
|
122
|
+
return lines.join('\n');
|
|
123
|
+
}
|
|
124
|
+
// Keeps the end of the log, where an agent says what it did or why it stopped.
|
|
125
|
+
function keepTail(file) {
|
|
126
|
+
const size = statSync(file).size;
|
|
127
|
+
if (size <= LOG_TAIL_BYTES)
|
|
128
|
+
return;
|
|
129
|
+
const fd = openSync(file, 'r');
|
|
130
|
+
const buffer = Buffer.alloc(LOG_TAIL_BYTES);
|
|
131
|
+
readSync(fd, buffer, 0, LOG_TAIL_BYTES, size - LOG_TAIL_BYTES);
|
|
132
|
+
closeSync(fd);
|
|
133
|
+
writeFileSync(file, `[first ${size - LOG_TAIL_BYTES} bytes dropped]\n${buffer.toString('utf-8')}`);
|
|
134
|
+
}
|
|
135
|
+
/** Runs the agent command in the project with `{brief}` filled in. Output goes to `logFile`. */
|
|
136
|
+
export function runAgent(projectDir, agent, briefFile, logFile) {
|
|
137
|
+
mkdirSync(dirname(logFile), { recursive: true });
|
|
138
|
+
const out = openSync(logFile, 'w');
|
|
139
|
+
const started = Date.now();
|
|
140
|
+
return new Promise(done => {
|
|
141
|
+
let timedOut = false;
|
|
142
|
+
let finished = false;
|
|
143
|
+
const finish = (exit) => {
|
|
144
|
+
if (finished)
|
|
145
|
+
return;
|
|
146
|
+
finished = true;
|
|
147
|
+
clearTimeout(timer);
|
|
148
|
+
closeSync(out);
|
|
149
|
+
keepTail(logFile);
|
|
150
|
+
done({ exit, timedOut, durationMs: Date.now() - started });
|
|
151
|
+
};
|
|
152
|
+
// The command's output goes straight to the file: a pipe held open by a child the agent left
|
|
153
|
+
// behind would keep this process waiting after the agent itself has gone.
|
|
154
|
+
const child = spawn(agent.cmd.replaceAll('{brief}', shellQuote(briefFile)), {
|
|
155
|
+
cwd: projectDir,
|
|
156
|
+
shell: true,
|
|
157
|
+
detached: true,
|
|
158
|
+
stdio: ['ignore', out, out],
|
|
159
|
+
env: { ...checkEnv(), CODELOOP_ROLE: 'agent', CODELOOP_AGENT_RUN: agent.name },
|
|
160
|
+
});
|
|
161
|
+
const timer = setTimeout(() => {
|
|
162
|
+
timedOut = true;
|
|
163
|
+
// `detached` made the shell a process group leader, so this reaches the agent and its children.
|
|
164
|
+
try {
|
|
165
|
+
process.kill(-child.pid, 'SIGKILL');
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
child.kill('SIGKILL');
|
|
169
|
+
}
|
|
170
|
+
}, agent.timeoutMinutes * 60_000);
|
|
171
|
+
child.on('error', e => {
|
|
172
|
+
writeFileSync(logFile, `could not start: ${e.message}\n`, { flag: 'a' });
|
|
173
|
+
finish(null);
|
|
174
|
+
});
|
|
175
|
+
child.on('exit', code => finish(code));
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/lib/agent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export interface TaskStep {
|
|
2
|
+
text: string;
|
|
3
|
+
done: boolean;
|
|
4
|
+
}
|
|
5
|
+
export interface Task {
|
|
6
|
+
id: string;
|
|
7
|
+
title: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
status: 'backlog' | 'planned' | 'in_progress' | 'review' | 'done';
|
|
10
|
+
labels: string[];
|
|
11
|
+
steps: TaskStep[];
|
|
12
|
+
commits: string[];
|
|
13
|
+
acceptanceCriteria?: string[];
|
|
14
|
+
createdAt: string;
|
|
15
|
+
updatedAt: string;
|
|
16
|
+
}
|
|
17
|
+
export interface Board {
|
|
18
|
+
version: 1;
|
|
19
|
+
columns: string[];
|
|
20
|
+
tasks: Task[];
|
|
21
|
+
}
|
|
22
|
+
export declare function createBoard(): Board;
|
|
23
|
+
export declare function nextId(board: Board): string;
|
|
24
|
+
export interface AddTaskInput {
|
|
25
|
+
title: string;
|
|
26
|
+
description?: string;
|
|
27
|
+
status?: Task['status'];
|
|
28
|
+
labels?: string[];
|
|
29
|
+
steps?: TaskStep[];
|
|
30
|
+
acceptanceCriteria?: string[];
|
|
31
|
+
}
|
|
32
|
+
export declare function addTask(board: Board, input: AddTaskInput): Board;
|
|
33
|
+
export declare function updateTask(board: Board, id: string, patch: Partial<Omit<Task, 'id' | 'createdAt'>>): Board;
|
|
34
|
+
export declare function moveTask(board: Board, id: string, newStatus: Task['status']): Board;
|
|
35
|
+
export declare function deleteTask(board: Board, id: string): Board;
|
|
36
|
+
export declare function getTask(board: Board, id: string): Task | undefined;
|
|
37
|
+
export declare function loadBoard(dir: string): Board;
|
|
38
|
+
export declare function saveBoard(dir: string, board: Board): void;
|