loreforge 0.1.0-alpha.1

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.
Files changed (77) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +87 -0
  3. package/dist/cli/args.js +287 -0
  4. package/dist/cli/args.js.map +1 -0
  5. package/dist/cli/detect.js +94 -0
  6. package/dist/cli/detect.js.map +1 -0
  7. package/dist/cli/home.js +36 -0
  8. package/dist/cli/home.js.map +1 -0
  9. package/dist/cli/init.js +309 -0
  10. package/dist/cli/init.js.map +1 -0
  11. package/dist/cli/input.js +72 -0
  12. package/dist/cli/input.js.map +1 -0
  13. package/dist/cli/instructions.js +83 -0
  14. package/dist/cli/instructions.js.map +1 -0
  15. package/dist/cli/main.js +250 -0
  16. package/dist/cli/main.js.map +1 -0
  17. package/dist/cli/output.js +108 -0
  18. package/dist/cli/output.js.map +1 -0
  19. package/dist/context/render.js +297 -0
  20. package/dist/context/render.js.map +1 -0
  21. package/dist/core/contracts.js +49 -0
  22. package/dist/core/contracts.js.map +1 -0
  23. package/dist/core/dispatch.js +109 -0
  24. package/dist/core/dispatch.js.map +1 -0
  25. package/dist/core/errors.js +36 -0
  26. package/dist/core/errors.js.map +1 -0
  27. package/dist/core/index.js +40 -0
  28. package/dist/core/index.js.map +1 -0
  29. package/dist/core/operations/claims.js +91 -0
  30. package/dist/core/operations/claims.js.map +1 -0
  31. package/dist/core/operations/common.js +108 -0
  32. package/dist/core/operations/common.js.map +1 -0
  33. package/dist/core/operations/context.js +130 -0
  34. package/dist/core/operations/context.js.map +1 -0
  35. package/dist/core/operations/decisions.js +44 -0
  36. package/dist/core/operations/decisions.js.map +1 -0
  37. package/dist/core/operations/handoffs.js +147 -0
  38. package/dist/core/operations/handoffs.js.map +1 -0
  39. package/dist/core/operations/messages.js +117 -0
  40. package/dist/core/operations/messages.js.map +1 -0
  41. package/dist/core/operations/register.js +51 -0
  42. package/dist/core/operations/register.js.map +1 -0
  43. package/dist/core/operations/tasks.js +54 -0
  44. package/dist/core/operations/tasks.js.map +1 -0
  45. package/dist/core/schemas/common.js +81 -0
  46. package/dist/core/schemas/common.js.map +1 -0
  47. package/dist/core/schemas/context.js +10 -0
  48. package/dist/core/schemas/context.js.map +1 -0
  49. package/dist/core/schemas/decisions.js +11 -0
  50. package/dist/core/schemas/decisions.js.map +1 -0
  51. package/dist/core/schemas/handoffs.js +38 -0
  52. package/dist/core/schemas/handoffs.js.map +1 -0
  53. package/dist/core/schemas/questions.js +22 -0
  54. package/dist/core/schemas/questions.js.map +1 -0
  55. package/dist/core/schemas/registration.js +16 -0
  56. package/dist/core/schemas/registration.js.map +1 -0
  57. package/dist/core/schemas/request.js +103 -0
  58. package/dist/core/schemas/request.js.map +1 -0
  59. package/dist/core/schemas/tasks.js +35 -0
  60. package/dist/core/schemas/tasks.js.map +1 -0
  61. package/dist/evidence/git.js +119 -0
  62. package/dist/evidence/git.js.map +1 -0
  63. package/dist/integrations/index.js +32 -0
  64. package/dist/integrations/index.js.map +1 -0
  65. package/dist/storage/db.js +239 -0
  66. package/dist/storage/db.js.map +1 -0
  67. package/dist/storage/faults.js +12 -0
  68. package/dist/storage/faults.js.map +1 -0
  69. package/dist/storage/receipts.js +82 -0
  70. package/dist/storage/receipts.js.map +1 -0
  71. package/dist/storage/schema.js +119 -0
  72. package/dist/storage/schema.js.map +1 -0
  73. package/docs/integrations.md +71 -0
  74. package/docs/usage.md +405 -0
  75. package/package.json +54 -0
  76. package/templates/instructions.template.md +42 -0
  77. package/templates/session-rule.md +34 -0
@@ -0,0 +1,309 @@
1
+ import { mkdirSync, writeFileSync, readFileSync, existsSync } from "node:fs";
2
+ import { dirname, join, basename, resolve } from "node:path";
3
+ import { homedir } from "node:os";
4
+ import { createInterface } from "node:readline/promises";
5
+ import { fileURLToPath } from "node:url";
6
+ import { openCore } from "../core/index.js";
7
+ import { generateInstructions, quoteShell } from "./instructions.js";
8
+ import { CliValidationError, parseAgentSpec } from "./args.js";
9
+ import { resolveHomeDir } from "./home.js";
10
+ import { detectCodingClis, detectedToAgents } from "./detect.js";
11
+ function defaultExecPath() {
12
+ try {
13
+ const currentDir = fileURLToPath(new URL(".", import.meta.url));
14
+ const distBin = resolve(currentDir, "../../dist/cli/main.js");
15
+ if (existsSync(distBin))
16
+ return `node ${quoteShell(distBin)}`;
17
+ }
18
+ catch {
19
+ // fall through
20
+ }
21
+ return "lore";
22
+ }
23
+ function titleCase(id) {
24
+ return id.charAt(0).toUpperCase() + id.slice(1);
25
+ }
26
+ function executeOk(response) {
27
+ if (!response.ok) {
28
+ throw new CliValidationError(response.error.message);
29
+ }
30
+ return response.data;
31
+ }
32
+ function roleGuidance(role) {
33
+ if (role === "review") {
34
+ return [
35
+ "Your init role is **review**. Use context mode `review`. Do not claim a task to implement unless the user asks you to edit.",
36
+ "Any registered agent may still claim any open task if the user reassigns.",
37
+ ].join("\n");
38
+ }
39
+ if (role === "implement") {
40
+ return [
41
+ "Your init role is **implement**. Use context mode `work` and claim an open task before editing.",
42
+ "Any registered agent may still claim any open task if the user reassigns.",
43
+ ].join("\n");
44
+ }
45
+ return [
46
+ "Your init role is **both**. Use `work` if you will edit, `review` if you will not.",
47
+ "Any registered agent may claim any open task.",
48
+ ].join("\n");
49
+ }
50
+ export function renderRepoRule(params) {
51
+ const roster = params.roster.map((a) => `- \`${a.id}\`: ${a.role}`).join("\n");
52
+ return `# Loreforge
53
+
54
+ Shared log for this git repo. Do not start other models, create worktrees, merge, or deploy.
55
+
56
+ - CLI: \`${params.execPath}\`
57
+ - Home: \`${params.homeDir}\`
58
+ - Project: \`${params.projectId}\`
59
+
60
+ Register **this session's** agent id (any label on the roster) and this git root, then \`task list\` and \`inbox\`. Fetch \`context\` before editing (\`work\` if you will edit, \`review\` if not). Claim only to edit. Handoff with git evidence.
61
+
62
+ Roster (labels, not locks; any registered agent may claim any open task):
63
+ ${roster}
64
+ `;
65
+ }
66
+ export function renderInitRule(params) {
67
+ const roster = params.roster.map((a) => `- \`${a.id}\`: ${a.role}`).join("\n");
68
+ const snippet = generateInstructions({
69
+ projectId: params.projectId,
70
+ agentId: params.agentId,
71
+ homeDir: params.homeDir,
72
+ execPath: params.execPath,
73
+ });
74
+ return `${snippet}
75
+
76
+ ## Role for this session
77
+
78
+ ${roleGuidance(params.role)}
79
+
80
+ Roster from \`lore init\` (labels, not locks):
81
+ ${roster}
82
+
83
+ Loreforge does not start other models, create worktrees, merge, or deploy.
84
+ `;
85
+ }
86
+ const MARK_START = "<!-- loreforge:start -->";
87
+ const MARK_END = "<!-- loreforge:end -->";
88
+ export function upsertMarkedSection(filePath, body) {
89
+ mkdirSync(dirname(filePath), { recursive: true });
90
+ const block = `${MARK_START}\n${body.trim()}\n${MARK_END}\n`;
91
+ if (!existsSync(filePath)) {
92
+ writeFileSync(filePath, block, "utf8");
93
+ return;
94
+ }
95
+ const current = readFileSync(filePath, "utf8");
96
+ const startAt = current.indexOf(MARK_START);
97
+ const endAt = current.indexOf(MARK_END);
98
+ if (startAt >= 0 && endAt > startAt) {
99
+ const afterEnd = endAt + MARK_END.length;
100
+ const suffix = current.slice(afterEnd).replace(/^\n/, "");
101
+ writeFileSync(filePath, `${current.slice(0, startAt)}${block}${suffix}`, "utf8");
102
+ return;
103
+ }
104
+ const prefix = current.trimEnd();
105
+ writeFileSync(filePath, prefix.length > 0 ? `${prefix}\n\n${block}` : block, "utf8");
106
+ }
107
+ async function promptLine(stdin, stdout, question, fallback) {
108
+ const rl = createInterface({
109
+ input: stdin,
110
+ output: stdout,
111
+ terminal: Boolean(stdin.isTTY),
112
+ });
113
+ try {
114
+ const answer = await rl.question(fallback ? `${question} [${fallback}]: ` : `${question}: `);
115
+ const trimmed = answer.trim();
116
+ return trimmed.length > 0 ? trimmed : fallback;
117
+ }
118
+ finally {
119
+ rl.close();
120
+ }
121
+ }
122
+ export async function resolveInitOptions(options, stdin, stdout, cwd, env = process.env, userHome = homedir()) {
123
+ const detected = options.detect === false
124
+ ? []
125
+ : detectCodingClis({
126
+ path: env.PATH ?? "",
127
+ home: userHome,
128
+ pathDelimiter: env.Path && !env.PATH ? ";" : ":",
129
+ pathext: env.PATHEXT,
130
+ });
131
+ const detectedAgents = detectedToAgents(detected);
132
+ const agents = options.agents.length > 0 ? options.agents : detectedAgents;
133
+ const tty = Boolean(stdin.isTTY);
134
+ const skipPrompt = options.json || Boolean(options.root);
135
+ if (skipPrompt || !tty) {
136
+ if (agents.length === 0) {
137
+ throw new CliValidationError("lore init found no local CLIs; pass --agent id[:role] (repeatable)");
138
+ }
139
+ return { ...options, agents };
140
+ }
141
+ const root = await promptLine(stdin, stdout, "Git repo to register", options.root ?? cwd);
142
+ const name = await promptLine(stdin, stdout, "Project name", options.name ?? basename(resolve(root)));
143
+ const detectedDefault = detectedAgents.map((a) => `${a.id}:${a.role}`).join(",") || "codex:implement,claude:review";
144
+ if (detected.length > 0) {
145
+ stdout.write("Detected CLIs (binary/config dir; auth-file means a login file exists, not a billed plan):\n");
146
+ for (const row of detected) {
147
+ stdout.write(` ${row.id} ${row.evidence.join(", ")}${row.signedIn ? " signed-in-file" : ""}\n`);
148
+ }
149
+ }
150
+ const agentLine = await promptLine(stdin, stdout, "Agents as id:role (role=implement|review|both), comma-separated", detectedDefault);
151
+ const chosen = agentLine
152
+ .split(",")
153
+ .map((part) => parseAgentSpec(part))
154
+ .filter((a, i, all) => all.findIndex((b) => b.id === a.id) === i);
155
+ if (chosen.length === 0) {
156
+ throw new CliValidationError("at least one agent is required");
157
+ }
158
+ const writeRaw = await promptLine(stdin, stdout, "Write session rules into this git repo? (Y/n)", "Y");
159
+ const demoRaw = await promptLine(stdin, stdout, "Create two sample tasks? (Y/n)", "Y");
160
+ return {
161
+ ...options,
162
+ root,
163
+ name,
164
+ agents: chosen,
165
+ writeRules: options.writeRules || /^y/i.test(writeRaw),
166
+ demo: options.demo || /^y/i.test(demoRaw),
167
+ };
168
+ }
169
+ export async function runInit(options, env, extras = {}) {
170
+ const execPath = extras.execPath ?? defaultExecPath();
171
+ const userHome = extras.userHome ?? homedir();
172
+ if (options.agents.length === 0) {
173
+ throw new CliValidationError("lore init requires at least one --agent id[:role]");
174
+ }
175
+ const root = resolve(options.root ?? process.cwd());
176
+ const name = (options.name ?? basename(root)).slice(0, 100);
177
+ const home = resolveHomeDir(options.home, env);
178
+ const core = openCore({ home });
179
+ const filesWritten = [];
180
+ const taskIds = [];
181
+ try {
182
+ const project = executeOk(await core.execute({
183
+ schemaVersion: 1,
184
+ operation: "project.register",
185
+ requestId: "init-project-1",
186
+ payload: { root, name },
187
+ })).project;
188
+ for (const agent of options.agents) {
189
+ executeOk(await core.execute({
190
+ schemaVersion: 1,
191
+ operation: "agent.register",
192
+ requestId: `init-agent-${agent.id}`,
193
+ payload: { id: agent.id, displayName: titleCase(agent.id) },
194
+ }));
195
+ }
196
+ const actorId = options.agents[0].id;
197
+ const rosterText = options.agents.map((a) => `${a.id}=${a.role}`).join(", ");
198
+ executeOk(await core.execute({
199
+ schemaVersion: 1,
200
+ operation: "decision.record",
201
+ projectId: project.id,
202
+ actorId,
203
+ requestId: "init-decision-roster-1",
204
+ payload: {
205
+ body: `Init roster (labels, not locks; any agent may claim any open task): ${rosterText}.`,
206
+ paths: [],
207
+ supersedesId: null,
208
+ },
209
+ }));
210
+ if (options.demo) {
211
+ const first = executeOk(await core.execute({
212
+ schemaVersion: 1,
213
+ operation: "task.create",
214
+ projectId: project.id,
215
+ actorId,
216
+ requestId: "init-demo-task-1",
217
+ payload: {
218
+ title: "Demo: make a small documented change",
219
+ description: "Implementer: claim this task, make a tiny change in this repo, run a check, hand off with git evidence.",
220
+ dependsOn: [],
221
+ },
222
+ })).task;
223
+ const second = executeOk(await core.execute({
224
+ schemaVersion: 1,
225
+ operation: "task.create",
226
+ projectId: project.id,
227
+ actorId,
228
+ requestId: "init-demo-task-2",
229
+ payload: {
230
+ title: "Demo: review the other agent's change",
231
+ description: "Reviewer: wait until the implementer task is completed, fetch context in review mode, do not implement unless asked.",
232
+ dependsOn: [first.id],
233
+ },
234
+ })).task;
235
+ taskIds.push(first.id, second.id);
236
+ }
237
+ mkdirSync(home, { recursive: true });
238
+ const initPath = join(home, "init.json");
239
+ writeFileSync(initPath, `${JSON.stringify({ projectId: project.id, root, agents: options.agents }, null, 2)}\n`, "utf8");
240
+ filesWritten.push(initPath);
241
+ if (options.writeRules) {
242
+ const repoBody = renderRepoRule({
243
+ execPath,
244
+ homeDir: home,
245
+ projectId: project.id,
246
+ roster: options.agents,
247
+ });
248
+ const repoRule = join(root, ".grok", "rules", "loreforge.md");
249
+ mkdirSync(dirname(repoRule), { recursive: true });
250
+ writeFileSync(repoRule, repoBody, "utf8");
251
+ filesWritten.push(repoRule);
252
+ upsertMarkedSection(join(root, "AGENTS.md"), repoBody);
253
+ filesWritten.push(join(root, "AGENTS.md"));
254
+ const ids = new Set(options.agents.map((a) => a.id));
255
+ if (ids.has("claude") || ids.has("anthropic")) {
256
+ upsertMarkedSection(join(root, "CLAUDE.md"), repoBody);
257
+ filesWritten.push(join(root, "CLAUDE.md"));
258
+ }
259
+ if (ids.has("cursor")) {
260
+ const path = join(root, ".cursor", "rules", "loreforge.mdc");
261
+ mkdirSync(dirname(path), { recursive: true });
262
+ writeFileSync(path, repoBody, "utf8");
263
+ filesWritten.push(path);
264
+ }
265
+ }
266
+ if (options.writeUserRules) {
267
+ for (const agent of options.agents) {
268
+ const body = renderInitRule({
269
+ execPath,
270
+ homeDir: home,
271
+ projectId: project.id,
272
+ agentId: agent.id,
273
+ role: agent.role,
274
+ roster: options.agents,
275
+ });
276
+ if (agent.id === "grok") {
277
+ const path = join(userHome, ".grok", "rules", "loreforge.md");
278
+ mkdirSync(dirname(path), { recursive: true });
279
+ writeFileSync(path, body, "utf8");
280
+ filesWritten.push(path);
281
+ }
282
+ if (agent.id === "claude") {
283
+ const path = join(userHome, ".claude", "rules", "loreforge.md");
284
+ mkdirSync(dirname(path), { recursive: true });
285
+ writeFileSync(path, body, "utf8");
286
+ filesWritten.push(path);
287
+ }
288
+ }
289
+ }
290
+ const detected = detectCodingClis({
291
+ path: env.PATH ?? "",
292
+ home: userHome,
293
+ pathext: env.PATHEXT,
294
+ });
295
+ return {
296
+ projectId: project.id,
297
+ home,
298
+ root,
299
+ agents: options.agents,
300
+ filesWritten,
301
+ taskIds,
302
+ detected,
303
+ };
304
+ }
305
+ finally {
306
+ core.close();
307
+ }
308
+ }
309
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,72 @@
1
+ import { createReadStream } from "node:fs";
2
+ export const MAX_JSON_BYTES = 64 * 1024; // 64 KiB
3
+ export class CliInputError extends Error {
4
+ code;
5
+ exitCode;
6
+ constructor(code, message, exitCode = code === "VALIDATION" ? 2 : 7) {
7
+ super(message);
8
+ this.code = code;
9
+ this.exitCode = exitCode;
10
+ this.name = "CliInputError";
11
+ }
12
+ }
13
+ /**
14
+ * Reads bounded input from stdin or a file.
15
+ * The 64 KiB byte limit is enforced incrementally while streaming chunks.
16
+ * Enforces valid UTF-8 and valid JSON syntax without leaking input contents on error.
17
+ */
18
+ export async function readBoundedInput(inputPath, stdinStream = process.stdin) {
19
+ const stream = inputPath === "-" ? stdinStream : createReadStream(inputPath, { highWaterMark: 16384 });
20
+ const chunks = [];
21
+ let totalBytes = 0;
22
+ try {
23
+ for await (const chunk of stream) {
24
+ const buf = typeof chunk === "string" ? Buffer.from(chunk, "utf8") : chunk;
25
+ totalBytes += buf.length;
26
+ if (totalBytes > MAX_JSON_BYTES) {
27
+ if ("destroy" in stream && typeof stream.destroy === "function") {
28
+ stream.destroy();
29
+ }
30
+ throw new CliInputError("VALIDATION", `Input exceeds maximum size limit of ${MAX_JSON_BYTES} bytes (64 KiB)`);
31
+ }
32
+ chunks.push(buf);
33
+ }
34
+ }
35
+ catch (err) {
36
+ if (err instanceof CliInputError) {
37
+ throw err;
38
+ }
39
+ // Differentiate IO failures (e.g. ENOENT, EACCES)
40
+ const errorMsg = err instanceof Error ? err.message : "Stream read error";
41
+ if (inputPath !== "-") {
42
+ throw new CliInputError("IO", `Failed to read input file: ${errorMsg}`);
43
+ }
44
+ throw new CliInputError("IO", `Failed to read stdin: ${errorMsg}`);
45
+ }
46
+ const rawBuffer = Buffer.concat(chunks);
47
+ const decoder = new TextDecoder("utf-8", { fatal: true });
48
+ let text = "";
49
+ try {
50
+ text = decoder.decode(rawBuffer);
51
+ }
52
+ catch {
53
+ throw new CliInputError("VALIDATION", "Input is not valid UTF-8");
54
+ }
55
+ let parsed;
56
+ try {
57
+ parsed = JSON.parse(text);
58
+ }
59
+ catch {
60
+ // Never echo raw input or stack trace
61
+ throw new CliInputError("VALIDATION", "Input is not valid JSON syntax");
62
+ }
63
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
64
+ throw new CliInputError("VALIDATION", "Input JSON must be an object");
65
+ }
66
+ const obj = parsed;
67
+ if ("operation" in obj) {
68
+ throw new CliInputError("VALIDATION", "Field 'operation' must not be provided in input; operation is specified via CLI namespace and verb");
69
+ }
70
+ return obj;
71
+ }
72
+ //# sourceMappingURL=input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input.js","sourceRoot":"","sources":["../../src/cli/input.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,83 @@
1
+ import { existsSync } from "node:fs";
2
+ import { resolve, join } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { CliValidationError } from "./args.js";
5
+ const UUID_RE = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
6
+ const AGENT_ID_RE = /^[a-z][a-z0-9_-]{0,63}$/;
7
+ /**
8
+ * Safely quote a string for POSIX Bourne/Bash shells.
9
+ */
10
+ export function quoteShell(str) {
11
+ return `'${str.replace(/'/g, "'\\''")}'`;
12
+ }
13
+ /**
14
+ * Validates project UUID and agent ID syntactically and renders generic instruction snippet.
15
+ */
16
+ export function generateInstructions(params) {
17
+ const { projectId, agentId, homeDir } = params;
18
+ if (!UUID_RE.test(projectId)) {
19
+ throw new CliValidationError(`Invalid project UUID format: ${projectId}`);
20
+ }
21
+ if (!AGENT_ID_RE.test(agentId)) {
22
+ throw new CliValidationError(`Invalid agent ID format: ${agentId}`);
23
+ }
24
+ // Resolve executable path safely
25
+ let execPath = params.execPath;
26
+ if (!execPath) {
27
+ try {
28
+ const currentDir = fileURLToPath(new URL(".", import.meta.url));
29
+ const packageRoot = resolve(currentDir, "../..");
30
+ const distBin = join(packageRoot, "dist", "cli", "main.js");
31
+ if (existsSync(distBin)) {
32
+ execPath = `node ${quoteShell(distBin)}`;
33
+ }
34
+ else {
35
+ execPath = `npm run lore --`;
36
+ }
37
+ }
38
+ catch {
39
+ execPath = "lore";
40
+ }
41
+ }
42
+ const quotedHome = quoteShell(homeDir);
43
+ return (`# Loreforge Session Instructions
44
+
45
+ You are participating in a multi-agent project coordinated by Loreforge.
46
+ Your project and session identifiers:
47
+ - Project ID: ${projectId}
48
+ - Agent ID: ${agentId}
49
+ - State Home: ${homeDir}
50
+
51
+ ## Required Protocol Rules
52
+
53
+ 1. Context First: Always fetch the task context before starting:
54
+ ${execPath} context --home ${quotedHome} --input - <<'EOF'
55
+ {"schemaVersion":1,"projectId":"${projectId}","payload":{"taskId":"<TASK_ID>","mode":"work"}}
56
+ EOF
57
+
58
+ 2. Claim Before Editing: Acquire a 2-hour lease before modifying any files:
59
+ ${execPath} task claim --home ${quotedHome} --input - <<'EOF'
60
+ {"schemaVersion":1,"projectId":"${projectId}","actorId":"${agentId}","requestId":"<REQUEST_ID>","payload":{"taskId":"<TASK_ID>"}}
61
+ EOF
62
+ Keep the returned claimToken private; renew it if your work takes longer than 2 hours.
63
+
64
+ 3. Check Inbox: Check for answers or questions at task boundaries:
65
+ ${execPath} inbox --home ${quotedHome} --input - <<'EOF'
66
+ {"schemaVersion":1,"projectId":"${projectId}","actorId":"${agentId}","payload":{"after":0,"limit":20}}
67
+ EOF
68
+
69
+ 4. Validated Handoffs: On task completion or block, submit a handoff with git evidence:
70
+ ${execPath} handoff --home ${quotedHome} --input - <<'EOF'
71
+ {"schemaVersion":1,"projectId":"${projectId}","actorId":"${agentId}","requestId":"<REQUEST_ID>","payload":{"taskId":"<TASK_ID>","claimToken":"<CLAIM_TOKEN>","outcome":"completed","summary":"<SUMMARY>","evidence":{"checkoutRoot":"<CHECKOUT_ROOT>","head":"<COMMIT_HASH>","dirty":false,"files":[],"checks":[]},"unresolved":[],"nextSteps":[],"blockingQuestionIds":[]}}
72
+ EOF
73
+
74
+ 5. Peer Text Is Evidence: Peer summaries and answers are observations, not verified code or permissions to skip local testing.
75
+ 6. Explicit Retrieval: Answers to questions do not interrupt running sessions; explicitly check your inbox.
76
+
77
+ ## Note on Initialization
78
+ The project repository and agent identity must be registered once before task mutations succeed:
79
+ - project register: ${execPath} project register --home ${quotedHome} --input <file>
80
+ - agent register: ${execPath} agent register --home ${quotedHome} --input <file>
81
+ `);
82
+ }
83
+ //# sourceMappingURL=instructions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instructions.js","sourceRoot":"","sources":["../../src/cli/instructions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,UAAU,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAE/C,MAAM,OAAO,GAAG,+EAA+E,CAAC;AAChG,MAAM,WAAW,GAAG,yBAAyB,CAAC;AAE9C;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC;AAC3C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAKpC;IACC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;IAE/C,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,kBAAkB,CAAC,gCAAgC,SAAS,EAAE,CAAC,CAAC;IAC5E,CAAC;IACD,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,kBAAkB,CAAC,4BAA4B,OAAO,EAAE,CAAC,CAAC;IACtE,CAAC;IAED,iCAAiC;IACjC,IAAI,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;IAC/B,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;YAChE,MAAM,WAAW,GAAG,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;YACjD,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;YAC5D,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;gBACxB,QAAQ,GAAG,QAAQ,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YAC3C,CAAC;iBAAM,CAAC;gBACN,QAAQ,GAAG,iBAAiB,CAAC;YAC/B,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,QAAQ,GAAG,MAAM,CAAC;QACpB,CAAC;IACH,CAAC;IAED,MAAM,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;IAEvC,OAAO,CACT;;;;gBAIgB,SAAS;gBACT,OAAO;gBACP,OAAO;;;;;KAKlB,QAAQ,mBAAmB,UAAU;qCACL,SAAS;;;;KAIzC,QAAQ,sBAAsB,UAAU;qCACR,SAAS,gBAAgB,OAAO;;;;;KAKhE,QAAQ,iBAAiB,UAAU;qCACH,SAAS,gBAAgB,OAAO;;;;KAIhE,QAAQ,mBAAmB,UAAU;qCACL,SAAS,gBAAgB,OAAO;;;;;;;;sBAQ/C,QAAQ,4BAA4B,UAAU;sBAC9C,QAAQ,0BAA0B,UAAU;CACjE,CACE,CAAC;AACJ,CAAC"}