@citadel-labs/citadel 0.1.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/README.md +145 -0
- package/dist/__tests__/append-bead.test.d.ts +2 -0
- package/dist/__tests__/append-bead.test.d.ts.map +1 -0
- package/dist/__tests__/append-bead.test.js +88 -0
- package/dist/__tests__/append-bead.test.js.map +1 -0
- package/dist/__tests__/blocked-outposts.test.d.ts +2 -0
- package/dist/__tests__/blocked-outposts.test.d.ts.map +1 -0
- package/dist/__tests__/blocked-outposts.test.js +142 -0
- package/dist/__tests__/blocked-outposts.test.js.map +1 -0
- package/dist/__tests__/bugfixes.test.d.ts +2 -0
- package/dist/__tests__/bugfixes.test.d.ts.map +1 -0
- package/dist/__tests__/bugfixes.test.js +503 -0
- package/dist/__tests__/bugfixes.test.js.map +1 -0
- package/dist/__tests__/citizen-tribute.test.d.ts +2 -0
- package/dist/__tests__/citizen-tribute.test.d.ts.map +1 -0
- package/dist/__tests__/citizen-tribute.test.js +106 -0
- package/dist/__tests__/citizen-tribute.test.js.map +1 -0
- package/dist/__tests__/cli-e2e/dispatch-note-resolve.test.d.ts +2 -0
- package/dist/__tests__/cli-e2e/dispatch-note-resolve.test.d.ts.map +1 -0
- package/dist/__tests__/cli-e2e/dispatch-note-resolve.test.js +65 -0
- package/dist/__tests__/cli-e2e/dispatch-note-resolve.test.js.map +1 -0
- package/dist/__tests__/cli-e2e/full-lifecycle.test.d.ts +2 -0
- package/dist/__tests__/cli-e2e/full-lifecycle.test.d.ts.map +1 -0
- package/dist/__tests__/cli-e2e/full-lifecycle.test.js +157 -0
- package/dist/__tests__/cli-e2e/full-lifecycle.test.js.map +1 -0
- package/dist/__tests__/cli-e2e/helpers.d.ts +28 -0
- package/dist/__tests__/cli-e2e/helpers.d.ts.map +1 -0
- package/dist/__tests__/cli-e2e/helpers.js +76 -0
- package/dist/__tests__/cli-e2e/helpers.js.map +1 -0
- package/dist/__tests__/cli-e2e/init-outpost-status.test.d.ts +2 -0
- package/dist/__tests__/cli-e2e/init-outpost-status.test.d.ts.map +1 -0
- package/dist/__tests__/cli-e2e/init-outpost-status.test.js +79 -0
- package/dist/__tests__/cli-e2e/init-outpost-status.test.js.map +1 -0
- package/dist/__tests__/cli-e2e/reset-stop-tribute-trace.test.d.ts +2 -0
- package/dist/__tests__/cli-e2e/reset-stop-tribute-trace.test.d.ts.map +1 -0
- package/dist/__tests__/cli-e2e/reset-stop-tribute-trace.test.js +158 -0
- package/dist/__tests__/cli-e2e/reset-stop-tribute-trace.test.js.map +1 -0
- package/dist/__tests__/courier.test.d.ts +2 -0
- package/dist/__tests__/courier.test.d.ts.map +1 -0
- package/dist/__tests__/courier.test.js +97 -0
- package/dist/__tests__/courier.test.js.map +1 -0
- package/dist/__tests__/e2e-smoke.test.d.ts +2 -0
- package/dist/__tests__/e2e-smoke.test.d.ts.map +1 -0
- package/dist/__tests__/e2e-smoke.test.js +137 -0
- package/dist/__tests__/e2e-smoke.test.js.map +1 -0
- package/dist/__tests__/fo-broadcast.test.d.ts +2 -0
- package/dist/__tests__/fo-broadcast.test.d.ts.map +1 -0
- package/dist/__tests__/fo-broadcast.test.js +134 -0
- package/dist/__tests__/fo-broadcast.test.js.map +1 -0
- package/dist/__tests__/fo-command-processor.test.d.ts +2 -0
- package/dist/__tests__/fo-command-processor.test.d.ts.map +1 -0
- package/dist/__tests__/fo-command-processor.test.js +86 -0
- package/dist/__tests__/fo-command-processor.test.js.map +1 -0
- package/dist/__tests__/fo-escalation.test.d.ts +2 -0
- package/dist/__tests__/fo-escalation.test.d.ts.map +1 -0
- package/dist/__tests__/fo-escalation.test.js +126 -0
- package/dist/__tests__/fo-escalation.test.js.map +1 -0
- package/dist/__tests__/fo-nudge-watcher.test.d.ts +2 -0
- package/dist/__tests__/fo-nudge-watcher.test.d.ts.map +1 -0
- package/dist/__tests__/fo-nudge-watcher.test.js +154 -0
- package/dist/__tests__/fo-nudge-watcher.test.js.map +1 -0
- package/dist/__tests__/fo-nudge-wiring.test.d.ts +2 -0
- package/dist/__tests__/fo-nudge-wiring.test.d.ts.map +1 -0
- package/dist/__tests__/fo-nudge-wiring.test.js +31 -0
- package/dist/__tests__/fo-nudge-wiring.test.js.map +1 -0
- package/dist/__tests__/fo-relay.test.d.ts +2 -0
- package/dist/__tests__/fo-relay.test.d.ts.map +1 -0
- package/dist/__tests__/fo-relay.test.js +90 -0
- package/dist/__tests__/fo-relay.test.js.map +1 -0
- package/dist/__tests__/fo-task-report.test.d.ts +2 -0
- package/dist/__tests__/fo-task-report.test.d.ts.map +1 -0
- package/dist/__tests__/fo-task-report.test.js +81 -0
- package/dist/__tests__/fo-task-report.test.js.map +1 -0
- package/dist/__tests__/fo-webhook.test.d.ts +2 -0
- package/dist/__tests__/fo-webhook.test.d.ts.map +1 -0
- package/dist/__tests__/fo-webhook.test.js +70 -0
- package/dist/__tests__/fo-webhook.test.js.map +1 -0
- package/dist/__tests__/integration.test.d.ts +2 -0
- package/dist/__tests__/integration.test.d.ts.map +1 -0
- package/dist/__tests__/integration.test.js +763 -0
- package/dist/__tests__/integration.test.js.map +1 -0
- package/dist/__tests__/multi-outpost-dep.test.d.ts +2 -0
- package/dist/__tests__/multi-outpost-dep.test.d.ts.map +1 -0
- package/dist/__tests__/multi-outpost-dep.test.js +173 -0
- package/dist/__tests__/multi-outpost-dep.test.js.map +1 -0
- package/dist/__tests__/nudge.test.d.ts +2 -0
- package/dist/__tests__/nudge.test.d.ts.map +1 -0
- package/dist/__tests__/nudge.test.js +103 -0
- package/dist/__tests__/nudge.test.js.map +1 -0
- package/dist/__tests__/outpost-registry.test.d.ts +2 -0
- package/dist/__tests__/outpost-registry.test.d.ts.map +1 -0
- package/dist/__tests__/outpost-registry.test.js +72 -0
- package/dist/__tests__/outpost-registry.test.js.map +1 -0
- package/dist/__tests__/process-registry.test.d.ts +2 -0
- package/dist/__tests__/process-registry.test.d.ts.map +1 -0
- package/dist/__tests__/process-registry.test.js +108 -0
- package/dist/__tests__/process-registry.test.js.map +1 -0
- package/dist/__tests__/session-log.test.d.ts +2 -0
- package/dist/__tests__/session-log.test.d.ts.map +1 -0
- package/dist/__tests__/session-log.test.js +60 -0
- package/dist/__tests__/session-log.test.js.map +1 -0
- package/dist/__tests__/spawn-citizen.test.d.ts +2 -0
- package/dist/__tests__/spawn-citizen.test.d.ts.map +1 -0
- package/dist/__tests__/spawn-citizen.test.js +48 -0
- package/dist/__tests__/spawn-citizen.test.js.map +1 -0
- package/dist/__tests__/timeout-watchdog.test.d.ts +2 -0
- package/dist/__tests__/timeout-watchdog.test.d.ts.map +1 -0
- package/dist/__tests__/timeout-watchdog.test.js +81 -0
- package/dist/__tests__/timeout-watchdog.test.js.map +1 -0
- package/dist/__tests__/worktree-manager.test.d.ts +2 -0
- package/dist/__tests__/worktree-manager.test.d.ts.map +1 -0
- package/dist/__tests__/worktree-manager.test.js +98 -0
- package/dist/__tests__/worktree-manager.test.js.map +1 -0
- package/dist/cli/aliases.d.ts +10 -0
- package/dist/cli/aliases.d.ts.map +1 -0
- package/dist/cli/aliases.js +56 -0
- package/dist/cli/aliases.js.map +1 -0
- package/dist/cli/command.d.ts +3 -0
- package/dist/cli/command.d.ts.map +1 -0
- package/dist/cli/command.js +63 -0
- package/dist/cli/command.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +29 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/init.d.ts +3 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +57 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/outpost.d.ts +3 -0
- package/dist/cli/outpost.d.ts.map +1 -0
- package/dist/cli/outpost.js +65 -0
- package/dist/cli/outpost.js.map +1 -0
- package/dist/cli/reset.d.ts +3 -0
- package/dist/cli/reset.d.ts.map +1 -0
- package/dist/cli/reset.js +67 -0
- package/dist/cli/reset.js.map +1 -0
- package/dist/cli/session.d.ts +3 -0
- package/dist/cli/session.d.ts.map +1 -0
- package/dist/cli/session.js +112 -0
- package/dist/cli/session.js.map +1 -0
- package/dist/cli/start.d.ts +3 -0
- package/dist/cli/start.d.ts.map +1 -0
- package/dist/cli/start.js +105 -0
- package/dist/cli/start.js.map +1 -0
- package/dist/cli/status.d.ts +3 -0
- package/dist/cli/status.d.ts.map +1 -0
- package/dist/cli/status.js +128 -0
- package/dist/cli/status.js.map +1 -0
- package/dist/cli/tribute.d.ts +3 -0
- package/dist/cli/tribute.d.ts.map +1 -0
- package/dist/cli/tribute.js +160 -0
- package/dist/cli/tribute.js.map +1 -0
- package/dist/cli/worktree.d.ts +3 -0
- package/dist/cli/worktree.d.ts.map +1 -0
- package/dist/cli/worktree.js +64 -0
- package/dist/cli/worktree.js.map +1 -0
- package/dist/core/append-bead.d.ts +13 -0
- package/dist/core/append-bead.d.ts.map +1 -0
- package/dist/core/append-bead.js +68 -0
- package/dist/core/append-bead.js.map +1 -0
- package/dist/core/blocked-outposts.d.ts +15 -0
- package/dist/core/blocked-outposts.d.ts.map +1 -0
- package/dist/core/blocked-outposts.js +77 -0
- package/dist/core/blocked-outposts.js.map +1 -0
- package/dist/core/citizen-bootstrap.d.ts +17 -0
- package/dist/core/citizen-bootstrap.d.ts.map +1 -0
- package/dist/core/citizen-bootstrap.js +118 -0
- package/dist/core/citizen-bootstrap.js.map +1 -0
- package/dist/core/citizen-tribute.d.ts +17 -0
- package/dist/core/citizen-tribute.d.ts.map +1 -0
- package/dist/core/citizen-tribute.js +55 -0
- package/dist/core/citizen-tribute.js.map +1 -0
- package/dist/core/command-bead.d.ts +6 -0
- package/dist/core/command-bead.d.ts.map +1 -0
- package/dist/core/command-bead.js +20 -0
- package/dist/core/command-bead.js.map +1 -0
- package/dist/core/courier.d.ts +52 -0
- package/dist/core/courier.d.ts.map +1 -0
- package/dist/core/courier.js +167 -0
- package/dist/core/courier.js.map +1 -0
- package/dist/core/fo-broadcast.d.ts +15 -0
- package/dist/core/fo-broadcast.d.ts.map +1 -0
- package/dist/core/fo-broadcast.js +57 -0
- package/dist/core/fo-broadcast.js.map +1 -0
- package/dist/core/fo-command-processor.d.ts +7 -0
- package/dist/core/fo-command-processor.d.ts.map +1 -0
- package/dist/core/fo-command-processor.js +123 -0
- package/dist/core/fo-command-processor.js.map +1 -0
- package/dist/core/fo-dispatch.d.ts +24 -0
- package/dist/core/fo-dispatch.d.ts.map +1 -0
- package/dist/core/fo-dispatch.js +76 -0
- package/dist/core/fo-dispatch.js.map +1 -0
- package/dist/core/fo-escalation.d.ts +20 -0
- package/dist/core/fo-escalation.d.ts.map +1 -0
- package/dist/core/fo-escalation.js +83 -0
- package/dist/core/fo-escalation.js.map +1 -0
- package/dist/core/fo-handlers/ceiling-hit.d.ts +8 -0
- package/dist/core/fo-handlers/ceiling-hit.d.ts.map +1 -0
- package/dist/core/fo-handlers/ceiling-hit.js +10 -0
- package/dist/core/fo-handlers/ceiling-hit.js.map +1 -0
- package/dist/core/fo-handlers/slot-open.d.ts +13 -0
- package/dist/core/fo-handlers/slot-open.d.ts.map +1 -0
- package/dist/core/fo-handlers/slot-open.js +63 -0
- package/dist/core/fo-handlers/slot-open.js.map +1 -0
- package/dist/core/fo-nudge-watcher.d.ts +19 -0
- package/dist/core/fo-nudge-watcher.d.ts.map +1 -0
- package/dist/core/fo-nudge-watcher.js +71 -0
- package/dist/core/fo-nudge-watcher.js.map +1 -0
- package/dist/core/fo-nudge-wiring.d.ts +13 -0
- package/dist/core/fo-nudge-wiring.d.ts.map +1 -0
- package/dist/core/fo-nudge-wiring.js +120 -0
- package/dist/core/fo-nudge-wiring.js.map +1 -0
- package/dist/core/fo-relay.d.ts +7 -0
- package/dist/core/fo-relay.d.ts.map +1 -0
- package/dist/core/fo-relay.js +47 -0
- package/dist/core/fo-relay.js.map +1 -0
- package/dist/core/fo-retry-policy.d.ts +17 -0
- package/dist/core/fo-retry-policy.d.ts.map +1 -0
- package/dist/core/fo-retry-policy.js +89 -0
- package/dist/core/fo-retry-policy.js.map +1 -0
- package/dist/core/fo-state.d.ts +25 -0
- package/dist/core/fo-state.d.ts.map +1 -0
- package/dist/core/fo-state.js +99 -0
- package/dist/core/fo-state.js.map +1 -0
- package/dist/core/fo-task-report.d.ts +16 -0
- package/dist/core/fo-task-report.d.ts.map +1 -0
- package/dist/core/fo-task-report.js +63 -0
- package/dist/core/fo-task-report.js.map +1 -0
- package/dist/core/fo-webhook.d.ts +22 -0
- package/dist/core/fo-webhook.d.ts.map +1 -0
- package/dist/core/fo-webhook.js +43 -0
- package/dist/core/fo-webhook.js.map +1 -0
- package/dist/core/grand-archives.d.ts +14 -0
- package/dist/core/grand-archives.d.ts.map +1 -0
- package/dist/core/grand-archives.js +79 -0
- package/dist/core/grand-archives.js.map +1 -0
- package/dist/core/nudge.d.ts +6 -0
- package/dist/core/nudge.d.ts.map +1 -0
- package/dist/core/nudge.js +19 -0
- package/dist/core/nudge.js.map +1 -0
- package/dist/core/outpost-registry.d.ts +16 -0
- package/dist/core/outpost-registry.d.ts.map +1 -0
- package/dist/core/outpost-registry.js +27 -0
- package/dist/core/outpost-registry.js.map +1 -0
- package/dist/core/pre-spawn-check.d.ts +16 -0
- package/dist/core/pre-spawn-check.d.ts.map +1 -0
- package/dist/core/pre-spawn-check.js +50 -0
- package/dist/core/pre-spawn-check.js.map +1 -0
- package/dist/core/process-registry.d.ts +17 -0
- package/dist/core/process-registry.d.ts.map +1 -0
- package/dist/core/process-registry.js +71 -0
- package/dist/core/process-registry.js.map +1 -0
- package/dist/core/spawn-citizen.d.ts +23 -0
- package/dist/core/spawn-citizen.d.ts.map +1 -0
- package/dist/core/spawn-citizen.js +99 -0
- package/dist/core/spawn-citizen.js.map +1 -0
- package/dist/core/timeout-watchdog.d.ts +14 -0
- package/dist/core/timeout-watchdog.d.ts.map +1 -0
- package/dist/core/timeout-watchdog.js +68 -0
- package/dist/core/timeout-watchdog.js.map +1 -0
- package/dist/core/validate-tribute.d.ts +11 -0
- package/dist/core/validate-tribute.d.ts.map +1 -0
- package/dist/core/validate-tribute.js +44 -0
- package/dist/core/validate-tribute.js.map +1 -0
- package/dist/core/worktree-manager.d.ts +20 -0
- package/dist/core/worktree-manager.d.ts.map +1 -0
- package/dist/core/worktree-manager.js +123 -0
- package/dist/core/worktree-manager.js.map +1 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +30 -0
- package/dist/index.js.map +1 -0
- package/dist/types/agent.d.ts +47 -0
- package/dist/types/agent.d.ts.map +1 -0
- package/dist/types/agent.js +4 -0
- package/dist/types/agent.js.map +1 -0
- package/dist/types/beads.d.ts +175 -0
- package/dist/types/beads.d.ts.map +1 -0
- package/dist/types/beads.js +4 -0
- package/dist/types/beads.js.map +1 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +4 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/registry.d.ts +110 -0
- package/dist/types/registry.d.ts.map +1 -0
- package/dist/types/registry.js +3 -0
- package/dist/types/registry.js.map +1 -0
- package/docs/README.md +7 -0
- package/docs/architecture.md +106 -0
- package/docs/cli-reference.md +81 -0
- package/docs/configuration.md +143 -0
- package/docs/contributing.md +65 -0
- package/docs/getting-started.md +88 -0
- package/grand-archives/archetypes/architect/archetype.json +18 -0
- package/grand-archives/archetypes/qa-engineer/archetype.json +18 -0
- package/grand-archives/archetypes/software-engineer/archetype.json +18 -0
- package/grand-archives/archetypes/software-engineer/system-prompt.md +39 -0
- package/grand-archives/archetypes/software-engineer/toolset.json +15 -0
- package/grand-archives/first-officer/config.json +21 -0
- package/grand-archives/first-officer/system-prompt.md +47 -0
- package/grand-archives/first-officer/toolset.json +19 -0
- package/grand-archives/registry.json +8 -0
- package/grand-archives/shared/base-prompt-preamble.md +25 -0
- package/grand-archives/shared/base-tools.json +10 -0
- package/package.json +73 -0
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { readBeads } from '../core/append-bead.js';
|
|
4
|
+
async function loadOutposts(citadelDir) {
|
|
5
|
+
try {
|
|
6
|
+
const raw = await fs.readFile(path.join(citadelDir, 'outposts.json'), 'utf-8');
|
|
7
|
+
const registry = JSON.parse(raw);
|
|
8
|
+
return registry.outposts;
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return [];
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
async function listJsonlFiles(dirPath) {
|
|
15
|
+
try {
|
|
16
|
+
const entries = await fs.readdir(dirPath);
|
|
17
|
+
return entries
|
|
18
|
+
.filter((e) => e.endsWith('.jsonl'))
|
|
19
|
+
.map((e) => path.join(dirPath, e));
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return [];
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
async function readAllBeadsFromDir(dirPath) {
|
|
26
|
+
const files = await listJsonlFiles(dirPath);
|
|
27
|
+
const results = [];
|
|
28
|
+
for (const file of files) {
|
|
29
|
+
const beads = await readBeads(file);
|
|
30
|
+
results.push(...beads);
|
|
31
|
+
}
|
|
32
|
+
return results;
|
|
33
|
+
}
|
|
34
|
+
function nudgePayloadHasTaskId(payload, taskId) {
|
|
35
|
+
if ('task_id' in payload && payload.task_id === taskId) {
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
function commandBeadReferencesTask(bead, taskId) {
|
|
41
|
+
const args = bead.args;
|
|
42
|
+
return args.task_id === taskId;
|
|
43
|
+
}
|
|
44
|
+
export function registerTributeCommand(program) {
|
|
45
|
+
program
|
|
46
|
+
.command('tribute')
|
|
47
|
+
.description('List tributes for a task')
|
|
48
|
+
.requiredOption('--task <id>', 'Task ID to look up')
|
|
49
|
+
.action(async (opts) => {
|
|
50
|
+
const citadelDir = path.resolve('.citadel');
|
|
51
|
+
try {
|
|
52
|
+
await fs.access(citadelDir);
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
console.error('Not a Citadel workspace');
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
const outposts = await loadOutposts(citadelDir);
|
|
59
|
+
const allTributes = [];
|
|
60
|
+
for (const op of outposts) {
|
|
61
|
+
const tributeDir = path.join(op.path, '.beads', 'tribute');
|
|
62
|
+
const tributes = await readAllBeadsFromDir(tributeDir);
|
|
63
|
+
allTributes.push(...tributes);
|
|
64
|
+
}
|
|
65
|
+
const matched = allTributes
|
|
66
|
+
.filter((t) => t.task_id === opts.task)
|
|
67
|
+
.sort((a, b) => a.created_at.localeCompare(b.created_at));
|
|
68
|
+
if (matched.length === 0) {
|
|
69
|
+
console.log(`No tributes found for task ${opts.task}`);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
for (const t of matched) {
|
|
73
|
+
const criteria = t.acceptance_met
|
|
74
|
+
.map((met) => (met ? '[x]' : '[ ]'))
|
|
75
|
+
.join(' ');
|
|
76
|
+
console.log(`--- Attempt ${t.attempt} ---`);
|
|
77
|
+
console.log(` status: ${t.status}`);
|
|
78
|
+
console.log(` citizen_id: ${t.citizen_id}`);
|
|
79
|
+
console.log(` elapsed: ${t.elapsed_seconds}s`);
|
|
80
|
+
console.log(` summary: ${t.summary}`);
|
|
81
|
+
console.log(` acceptance: ${criteria}`);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
program
|
|
85
|
+
.command('trace')
|
|
86
|
+
.description('Show full event timeline for a task')
|
|
87
|
+
.requiredOption('--task <id>', 'Task ID to trace')
|
|
88
|
+
.action(async (opts) => {
|
|
89
|
+
const citadelDir = path.resolve('.citadel');
|
|
90
|
+
try {
|
|
91
|
+
await fs.access(citadelDir);
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
console.error('Not a Citadel workspace');
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
const events = [];
|
|
98
|
+
const outposts = await loadOutposts(citadelDir);
|
|
99
|
+
// 1. CommandBeads from .citadel/commands/*.jsonl
|
|
100
|
+
const commandBeads = await readAllBeadsFromDir(path.join(citadelDir, 'commands'));
|
|
101
|
+
for (const cb of commandBeads) {
|
|
102
|
+
if (commandBeadReferencesTask(cb, opts.task)) {
|
|
103
|
+
events.push({
|
|
104
|
+
created_at: cb.created_at,
|
|
105
|
+
bead_type: 'COMMAND',
|
|
106
|
+
summary: `${cb.command} (${cb.bead_id})`,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
// 2. MailBeads from all outposts
|
|
111
|
+
for (const op of outposts) {
|
|
112
|
+
const mailDir = path.join(op.path, '.beads', 'mail');
|
|
113
|
+
const mails = await readAllBeadsFromDir(mailDir);
|
|
114
|
+
for (const m of mails) {
|
|
115
|
+
if (m.task_id === opts.task) {
|
|
116
|
+
events.push({
|
|
117
|
+
created_at: m.created_at,
|
|
118
|
+
bead_type: 'MAIL',
|
|
119
|
+
summary: `${m.mail_type} from=${m.from} to=${m.to} "${m.subject}"`,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// 3. TributeBeads from all outposts
|
|
125
|
+
for (const op of outposts) {
|
|
126
|
+
const tributeDir = path.join(op.path, '.beads', 'tribute');
|
|
127
|
+
const tributes = await readAllBeadsFromDir(tributeDir);
|
|
128
|
+
for (const t of tributes) {
|
|
129
|
+
if (t.task_id === opts.task) {
|
|
130
|
+
events.push({
|
|
131
|
+
created_at: t.created_at,
|
|
132
|
+
bead_type: 'TRIBUTE',
|
|
133
|
+
summary: `attempt=${t.attempt} status=${t.status} "${t.summary}"`,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
// 4. NudgeBeads from .citadel/nudges.jsonl
|
|
139
|
+
const nudges = await readBeads(path.join(citadelDir, 'nudges.jsonl'));
|
|
140
|
+
for (const n of nudges) {
|
|
141
|
+
if (nudgePayloadHasTaskId(n.payload, opts.task)) {
|
|
142
|
+
events.push({
|
|
143
|
+
created_at: n.created_at,
|
|
144
|
+
bead_type: 'NUDGE',
|
|
145
|
+
summary: `${n.signal_type} (${n.bead_id})`,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
// Sort and print
|
|
150
|
+
events.sort((a, b) => a.created_at.localeCompare(b.created_at));
|
|
151
|
+
if (events.length === 0) {
|
|
152
|
+
console.log(`No trace found for task ${opts.task}`);
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
for (const e of events) {
|
|
156
|
+
console.log(`[${e.created_at}] [${e.bead_type}] ${e.summary}`);
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=tribute.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tribute.js","sourceRoot":"","sources":["../../src/cli/tribute.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worktree.d.ts","sourceRoot":"","sources":["../../src/cli/worktree.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAoE9D"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { WorktreeManager } from '../core/worktree-manager.js';
|
|
4
|
+
export function registerWorktreeCommand(program) {
|
|
5
|
+
const worktree = program
|
|
6
|
+
.command('worktree')
|
|
7
|
+
.description('Manage git worktrees for outposts');
|
|
8
|
+
worktree
|
|
9
|
+
.command('list')
|
|
10
|
+
.description('List worktrees for an outpost')
|
|
11
|
+
.requiredOption('--outpost <slug>', 'Outpost slug')
|
|
12
|
+
.action(async (opts) => {
|
|
13
|
+
const citadelRoot = process.cwd();
|
|
14
|
+
const dotCitadel = path.join(citadelRoot, '.citadel');
|
|
15
|
+
try {
|
|
16
|
+
await fs.access(dotCitadel);
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
console.error('No .citadel/ directory found in current working directory.');
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
const manager = new WorktreeManager(citadelRoot);
|
|
23
|
+
const entries = await manager.list(opts.outpost);
|
|
24
|
+
if (entries.length === 0) {
|
|
25
|
+
console.log(`No worktrees for ${opts.outpost}`);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
for (const entry of entries) {
|
|
29
|
+
console.log(`${entry.path} ${entry.branch} ${entry.head.slice(0, 8)}`);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
worktree
|
|
33
|
+
.command('prune')
|
|
34
|
+
.description('Prune orphaned worktrees')
|
|
35
|
+
.option('--outpost <slug>', 'Scope to a single outpost')
|
|
36
|
+
.action(async (opts) => {
|
|
37
|
+
const citadelRoot = process.cwd();
|
|
38
|
+
const dotCitadel = path.join(citadelRoot, '.citadel');
|
|
39
|
+
try {
|
|
40
|
+
await fs.access(dotCitadel);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
console.error('No .citadel/ directory found in current working directory.');
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
const manager = new WorktreeManager(citadelRoot);
|
|
47
|
+
let slugs;
|
|
48
|
+
if (opts.outpost) {
|
|
49
|
+
slugs = [opts.outpost];
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
const raw = await fs.readFile(path.join(dotCitadel, 'outposts.json'), 'utf-8');
|
|
53
|
+
const registry = JSON.parse(raw);
|
|
54
|
+
slugs = registry.outposts
|
|
55
|
+
.filter(o => o.status === 'ACTIVE')
|
|
56
|
+
.map(o => o.slug);
|
|
57
|
+
}
|
|
58
|
+
for (const slug of slugs) {
|
|
59
|
+
const pruned = await manager.pruneOrphaned(slug, new Set());
|
|
60
|
+
console.log(`Pruned ${pruned} worktree(s) from ${slug}`);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=worktree.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worktree.js","sourceRoot":"","sources":["../../src/cli/worktree.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { BaseBead } from '../types/index.js';
|
|
2
|
+
/** Generate a bead ID with a type-specific prefix per PRD §3.1. */
|
|
3
|
+
export declare function mintBeadId(beadType?: string): string;
|
|
4
|
+
/**
|
|
5
|
+
* Append a bead as a single JSON line to the given file.
|
|
6
|
+
* Acquires a lockfile, appends, git commits, then releases.
|
|
7
|
+
*/
|
|
8
|
+
export declare function appendBead<T extends BaseBead>(filePath: string, bead: T): Promise<T>;
|
|
9
|
+
/**
|
|
10
|
+
* Read a JSONL bead file and parse each line into T.
|
|
11
|
+
*/
|
|
12
|
+
export declare function readBeads<T extends BaseBead>(filePath: string): Promise<T[]>;
|
|
13
|
+
//# sourceMappingURL=append-bead.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"append-bead.d.ts","sourceRoot":"","sources":["../../src/core/append-bead.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAYlD,mEAAmE;AACnE,wBAAgB,UAAU,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAGpD;AAED;;;GAGG;AACH,wBAAsB,UAAU,CAAC,CAAC,SAAS,QAAQ,EACjD,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,CAAC,GACN,OAAO,CAAC,CAAC,CAAC,CAkCZ;AAED;;GAEG;AACH,wBAAsB,SAAS,CAAC,CAAC,SAAS,QAAQ,EAChD,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,CAAC,EAAE,CAAC,CAad"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { execFile as execFileCb } from 'node:child_process';
|
|
4
|
+
import { promisify } from 'node:util';
|
|
5
|
+
import { lock, unlock } from 'proper-lockfile';
|
|
6
|
+
import { nanoid } from 'nanoid';
|
|
7
|
+
const execFile = promisify(execFileCb);
|
|
8
|
+
const BEAD_PREFIX_MAP = {
|
|
9
|
+
MAIL: 'mail_',
|
|
10
|
+
TRIBUTE: 'tribute_',
|
|
11
|
+
NUDGE: 'nudge_',
|
|
12
|
+
COMMAND: 'cmd_',
|
|
13
|
+
IDENTITY: 'identity_',
|
|
14
|
+
};
|
|
15
|
+
/** Generate a bead ID with a type-specific prefix per PRD §3.1. */
|
|
16
|
+
export function mintBeadId(beadType) {
|
|
17
|
+
const prefix = beadType ? (BEAD_PREFIX_MAP[beadType] ?? 'bead-') : 'bead-';
|
|
18
|
+
return `${prefix}${nanoid()}`;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Append a bead as a single JSON line to the given file.
|
|
22
|
+
* Acquires a lockfile, appends, git commits, then releases.
|
|
23
|
+
*/
|
|
24
|
+
export async function appendBead(filePath, bead) {
|
|
25
|
+
const absPath = path.resolve(filePath);
|
|
26
|
+
const dir = path.dirname(absPath);
|
|
27
|
+
// Ensure the parent directory exists
|
|
28
|
+
await fs.mkdir(dir, { recursive: true });
|
|
29
|
+
// Ensure the file exists (lockfile requires it)
|
|
30
|
+
await fs.appendFile(absPath, '');
|
|
31
|
+
await lock(absPath, {
|
|
32
|
+
retries: { retries: 3, minTimeout: 50, maxTimeout: 200, factor: 2 },
|
|
33
|
+
stale: 5000,
|
|
34
|
+
});
|
|
35
|
+
try {
|
|
36
|
+
await fs.appendFile(absPath, JSON.stringify(bead) + '\n');
|
|
37
|
+
// Best-effort git commit
|
|
38
|
+
try {
|
|
39
|
+
await execFile('git', ['add', absPath], { cwd: dir });
|
|
40
|
+
await execFile('git', ['commit', '-m', `bead: ${bead.bead_type} ${bead.bead_id}`], { cwd: dir });
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
console.warn(`[appendBead] git commit failed: ${err.message}`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
finally {
|
|
47
|
+
await unlock(absPath);
|
|
48
|
+
}
|
|
49
|
+
return bead;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Read a JSONL bead file and parse each line into T.
|
|
53
|
+
*/
|
|
54
|
+
export async function readBeads(filePath) {
|
|
55
|
+
const absPath = path.resolve(filePath);
|
|
56
|
+
let content;
|
|
57
|
+
try {
|
|
58
|
+
content = await fs.readFile(absPath, 'utf-8');
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
return content
|
|
64
|
+
.split('\n')
|
|
65
|
+
.filter((line) => line.trim() !== '')
|
|
66
|
+
.map((line) => JSON.parse(line));
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=append-bead.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"append-bead.js","sourceRoot":"","sources":["../../src/core/append-bead.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { MailBead } from '../types/index.js';
|
|
2
|
+
export interface BlockedTask {
|
|
3
|
+
outpost: string;
|
|
4
|
+
taskId: string;
|
|
5
|
+
mail: MailBead;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Find tasks across all ACTIVE outposts that are blocked on the given resolvedTaskId.
|
|
9
|
+
*
|
|
10
|
+
* A task is "blocked" if:
|
|
11
|
+
* 1. It has a TASK_ASSIGNMENT mail whose dependencies[] includes resolvedTaskId
|
|
12
|
+
* 2. It does NOT yet have a SUCCESS tribute
|
|
13
|
+
*/
|
|
14
|
+
export declare function getBlockedOutposts(citadelRoot: string, resolvedTaskId: string): Promise<BlockedTask[]>;
|
|
15
|
+
//# sourceMappingURL=blocked-outposts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blocked-outposts.d.ts","sourceRoot":"","sources":["../../src/core/blocked-outposts.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAsC,MAAM,mBAAmB,CAAC;AAEtF,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,QAAQ,CAAC;CAChB;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,WAAW,EAAE,CAAC,CA+BxB"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import fs from 'node:fs/promises';
|
|
3
|
+
import { readBeads } from './append-bead.js';
|
|
4
|
+
import { getActiveOutposts } from './outpost-registry.js';
|
|
5
|
+
/**
|
|
6
|
+
* Find tasks across all ACTIVE outposts that are blocked on the given resolvedTaskId.
|
|
7
|
+
*
|
|
8
|
+
* A task is "blocked" if:
|
|
9
|
+
* 1. It has a TASK_ASSIGNMENT mail whose dependencies[] includes resolvedTaskId
|
|
10
|
+
* 2. It does NOT yet have a SUCCESS tribute
|
|
11
|
+
*/
|
|
12
|
+
export async function getBlockedOutposts(citadelRoot, resolvedTaskId) {
|
|
13
|
+
const activeOutposts = await getActiveOutposts(citadelRoot);
|
|
14
|
+
const blocked = [];
|
|
15
|
+
for (const outpost of activeOutposts) {
|
|
16
|
+
const mailDir = path.join(outpost.path, '.beads', 'mail');
|
|
17
|
+
const tributeDir = path.join(outpost.path, '.beads', 'tribute');
|
|
18
|
+
// Read all mail beads
|
|
19
|
+
const mails = await readMailDir(mailDir);
|
|
20
|
+
// Find TASK_ASSIGNMENT mails that depend on resolvedTaskId
|
|
21
|
+
const dependentMails = mails.filter(m => {
|
|
22
|
+
if (m.mail_type !== 'TASK_ASSIGNMENT')
|
|
23
|
+
return false;
|
|
24
|
+
const payload = m.payload;
|
|
25
|
+
return payload.dependencies.includes(resolvedTaskId);
|
|
26
|
+
});
|
|
27
|
+
if (dependentMails.length === 0)
|
|
28
|
+
continue;
|
|
29
|
+
// Read tributes to check which tasks already succeeded
|
|
30
|
+
const succeededTaskIds = await getSucceededTaskIds(tributeDir);
|
|
31
|
+
for (const mail of dependentMails) {
|
|
32
|
+
const taskId = mail.task_id ?? mail.bead_id;
|
|
33
|
+
if (succeededTaskIds.has(taskId))
|
|
34
|
+
continue;
|
|
35
|
+
blocked.push({ outpost: outpost.slug, taskId, mail });
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return blocked;
|
|
39
|
+
}
|
|
40
|
+
async function readMailDir(mailDir) {
|
|
41
|
+
let files;
|
|
42
|
+
try {
|
|
43
|
+
files = await fs.readdir(mailDir);
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return [];
|
|
47
|
+
}
|
|
48
|
+
const mails = [];
|
|
49
|
+
for (const file of files) {
|
|
50
|
+
if (!file.endsWith('.jsonl'))
|
|
51
|
+
continue;
|
|
52
|
+
const beads = await readBeads(path.join(mailDir, file));
|
|
53
|
+
mails.push(...beads);
|
|
54
|
+
}
|
|
55
|
+
return mails;
|
|
56
|
+
}
|
|
57
|
+
async function getSucceededTaskIds(tributeDir) {
|
|
58
|
+
let files;
|
|
59
|
+
try {
|
|
60
|
+
files = await fs.readdir(tributeDir);
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return new Set();
|
|
64
|
+
}
|
|
65
|
+
const succeeded = new Set();
|
|
66
|
+
for (const file of files) {
|
|
67
|
+
if (!file.endsWith('.jsonl'))
|
|
68
|
+
continue;
|
|
69
|
+
const beads = await readBeads(path.join(tributeDir, file));
|
|
70
|
+
for (const t of beads) {
|
|
71
|
+
if (t.status === 'SUCCESS')
|
|
72
|
+
succeeded.add(t.task_id);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return succeeded;
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=blocked-outposts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blocked-outposts.js","sourceRoot":"","sources":["../../src/core/blocked-outposts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { MailBead } from '../types/index.js';
|
|
2
|
+
export interface CitizenContext {
|
|
3
|
+
citizenId: string;
|
|
4
|
+
outpost: string;
|
|
5
|
+
taskId: string;
|
|
6
|
+
worktree: string;
|
|
7
|
+
beadsRoot: string;
|
|
8
|
+
taskAssignment: MailBead | null;
|
|
9
|
+
isRetry: boolean;
|
|
10
|
+
retryErrors: string[];
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Bootstrap a citizen: validate env, scan inbox, synthesize context.
|
|
14
|
+
* Called at the start of a citizen's lifecycle.
|
|
15
|
+
*/
|
|
16
|
+
export declare function citizenBootstrap(): Promise<CitizenContext>;
|
|
17
|
+
//# sourceMappingURL=citizen-bootstrap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"citizen-bootstrap.d.ts","sourceRoot":"","sources":["../../src/core/citizen-bootstrap.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAElD,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,QAAQ,GAAG,IAAI,CAAC;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,cAAc,CAAC,CA8GhE"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import fs from 'node:fs/promises';
|
|
3
|
+
import { readBeads, appendBead, mintBeadId } from './append-bead.js';
|
|
4
|
+
import { SCHEMA_VERSION } from '../types/index.js';
|
|
5
|
+
/**
|
|
6
|
+
* Bootstrap a citizen: validate env, scan inbox, synthesize context.
|
|
7
|
+
* Called at the start of a citizen's lifecycle.
|
|
8
|
+
*/
|
|
9
|
+
export async function citizenBootstrap() {
|
|
10
|
+
// 1. Check required env vars
|
|
11
|
+
const citizenId = requireEnv('CITADEL_CITIZEN_ID');
|
|
12
|
+
const beadsRoot = requireEnv('CITADEL_BEADS_ROOT');
|
|
13
|
+
const outpost = requireEnv('CITADEL_OUTPOST');
|
|
14
|
+
const taskId = requireEnv('CITADEL_TASK_ID');
|
|
15
|
+
const worktree = requireEnv('CITADEL_WORKTREE');
|
|
16
|
+
// 2. Resolve outpost path from outposts.json
|
|
17
|
+
const outpostsPath = path.join(beadsRoot, '.citadel', 'outposts.json');
|
|
18
|
+
let outpostPath = '';
|
|
19
|
+
try {
|
|
20
|
+
const raw = await fs.readFile(outpostsPath, 'utf-8');
|
|
21
|
+
const registry = JSON.parse(raw);
|
|
22
|
+
const entry = registry.outposts.find((o) => o.slug === outpost);
|
|
23
|
+
if (entry)
|
|
24
|
+
outpostPath = entry.path;
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
throw new Error('Cannot read outposts.json');
|
|
28
|
+
}
|
|
29
|
+
// 3. Scan inbox: read all mail files, sorted by created_at
|
|
30
|
+
const inboxDir = path.join(outpostPath, '.beads', 'mail');
|
|
31
|
+
const allMail = [];
|
|
32
|
+
try {
|
|
33
|
+
const files = await fs.readdir(inboxDir);
|
|
34
|
+
for (const file of files) {
|
|
35
|
+
if (!file.endsWith('.jsonl'))
|
|
36
|
+
continue;
|
|
37
|
+
const beads = await readBeads(path.join(inboxDir, file));
|
|
38
|
+
allMail.push(...beads);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
// no mail dir yet
|
|
43
|
+
}
|
|
44
|
+
// Sort by created_at
|
|
45
|
+
allMail.sort((a, b) => a.created_at.localeCompare(b.created_at));
|
|
46
|
+
// 4. Find TASK_ASSIGNMENT for this citizen
|
|
47
|
+
const taskAssignment = allMail.find(m => m.mail_type === 'TASK_ASSIGNMENT' &&
|
|
48
|
+
m.spawn_hint?.citizen_id === citizenId) ?? null;
|
|
49
|
+
// If no TASK_ASSIGNMENT: write TASK_REPORT BLOCKED and return early
|
|
50
|
+
if (!taskAssignment) {
|
|
51
|
+
const reportMail = {
|
|
52
|
+
bead_id: mintBeadId('MAIL'),
|
|
53
|
+
bead_type: 'MAIL',
|
|
54
|
+
schema_version: SCHEMA_VERSION,
|
|
55
|
+
created_at: new Date().toISOString(),
|
|
56
|
+
mail_type: 'TASK_REPORT',
|
|
57
|
+
from: outpost,
|
|
58
|
+
to: 'citadel',
|
|
59
|
+
subject: `No task assignment found for citizen ${citizenId}`,
|
|
60
|
+
read: false,
|
|
61
|
+
retry_of: null,
|
|
62
|
+
payload: {
|
|
63
|
+
status: 'BLOCKED',
|
|
64
|
+
summary: `Citizen ${citizenId} found no TASK_ASSIGNMENT mail`,
|
|
65
|
+
blockers: ['No TASK_ASSIGNMENT mail in inbox'],
|
|
66
|
+
questions: [],
|
|
67
|
+
context_refs: [],
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
await appendBead(path.join(inboxDir, `report-${reportMail.bead_id}.jsonl`), reportMail);
|
|
71
|
+
return {
|
|
72
|
+
citizenId, outpost, taskId, worktree, beadsRoot,
|
|
73
|
+
taskAssignment: null,
|
|
74
|
+
isRetry: false,
|
|
75
|
+
retryErrors: [],
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
// 5. Check for TRIBUTE_INVALID (retry scenario)
|
|
79
|
+
let isRetry = false;
|
|
80
|
+
let retryErrors = [];
|
|
81
|
+
const tributeInvalid = allMail.find(m => m.mail_type === 'TRIBUTE_INVALID' && !m.read);
|
|
82
|
+
if (tributeInvalid) {
|
|
83
|
+
isRetry = true;
|
|
84
|
+
const payload = tributeInvalid.payload;
|
|
85
|
+
retryErrors = payload.errors ?? [];
|
|
86
|
+
}
|
|
87
|
+
// 6. Mark unread mail as read by appending a read marker line to the JSONL.
|
|
88
|
+
// PRD §3.4.2 step 6: For each unread Mail, mark read via appendBead().
|
|
89
|
+
const unreadMail = allMail.filter(m => !m.read);
|
|
90
|
+
for (const mail of unreadMail) {
|
|
91
|
+
// Find which file this bead came from and append a read marker
|
|
92
|
+
const files = await fs.readdir(inboxDir).catch(() => []);
|
|
93
|
+
for (const file of files) {
|
|
94
|
+
if (!file.endsWith('.jsonl'))
|
|
95
|
+
continue;
|
|
96
|
+
const filePath = path.join(inboxDir, file);
|
|
97
|
+
const beads = await readBeads(filePath);
|
|
98
|
+
if (beads.some(b => b.bead_id === mail.bead_id)) {
|
|
99
|
+
const readMarker = { ...mail, read: true };
|
|
100
|
+
await appendBead(filePath, readMarker);
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
citizenId, outpost, taskId, worktree, beadsRoot,
|
|
107
|
+
taskAssignment,
|
|
108
|
+
isRetry,
|
|
109
|
+
retryErrors,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
function requireEnv(name) {
|
|
113
|
+
const value = process.env[name];
|
|
114
|
+
if (!value)
|
|
115
|
+
throw new Error(`Missing required env var: ${name}`);
|
|
116
|
+
return value;
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=citizen-bootstrap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"citizen-bootstrap.js","sourceRoot":"","sources":["../../src/core/citizen-bootstrap.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { TributeBead, TributeStatus } from '../types/index.js';
|
|
2
|
+
export interface WriteTributeOptions {
|
|
3
|
+
originatingMailRef: string;
|
|
4
|
+
status: TributeStatus;
|
|
5
|
+
summary: string;
|
|
6
|
+
artifacts: string[];
|
|
7
|
+
acceptanceMet: boolean[];
|
|
8
|
+
elapsedSeconds: number;
|
|
9
|
+
prUrl?: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Write a Tribute bead from within a Citizen process.
|
|
13
|
+
* Reads env vars for context. Writes to <outpost_path>/.beads/tribute/<task_id>_tribute.jsonl
|
|
14
|
+
* Attempt number is determined from existing lines + 1.
|
|
15
|
+
*/
|
|
16
|
+
export declare function writeTribute(opts: WriteTributeOptions): Promise<TributeBead>;
|
|
17
|
+
//# sourceMappingURL=citizen-tribute.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"citizen-tribute.d.ts","sourceRoot":"","sources":["../../src/core/citizen-tribute.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEpE,MAAM,WAAW,mBAAmB;IAClC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,MAAM,EAAE,aAAa,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,aAAa,EAAE,OAAO,EAAE,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,WAAW,CAAC,CA0ClF"}
|