overlord-cli 0.2608181528.0 → 0.2608181615.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.
@@ -1 +1 @@
1
- 0.3.27
1
+ 0.3.28
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://antigravity.google/schemas/v1/plugin.json",
3
3
  "name": "overlord",
4
- "version": "0.3.27",
4
+ "version": "0.3.28",
5
5
  "description": "Chat-driven access to Overlord mission protocol workflows through skills and MCP.",
6
6
  "author": {
7
7
  "name": "Cooperativ",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "overlord",
3
- "version": "0.3.27",
3
+ "version": "0.3.28",
4
4
  "description": "Overlord mission protocol workflow for Claude Code — attach/update/ask/deliver, slash commands, and hook-driven activity capture.",
5
5
  "author": {
6
6
  "name": "Cooperativ",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "overlord",
3
- "version": "0.3.27",
3
+ "version": "0.3.28",
4
4
  "description": "Chat-driven access to Overlord mission protocol workflows with hook-driven activity capture.",
5
5
  "author": {
6
6
  "name": "Cooperativ",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "overlord",
3
- "version": "0.3.27",
3
+ "version": "0.3.28",
4
4
  "description": "Overlord mission protocol workflow for Cursor — attach/update/ask/deliver, slash commands, MCP bridge, and follow-up capture.",
5
5
  "author": {
6
6
  "name": "Cooperativ",
@@ -12,7 +12,7 @@ ovld protocol attachment-upload-file --session-key <sessionKey> --objective-id <
12
12
  ovld protocol attachment-download-url --session-key <sessionKey> --attachment-id <attachment-id>
13
13
  ```
14
14
 
15
- The `attach` and `load-context` responses already include an `attachments` array plus `previousObjectives` and `futureObjectives` arrays — use those for `<attachment-id>` and `<objective-id>` values. The objective currently being executed is not repeated in those arrays; it is the top-level `objective`. `previousObjectives` are the objectives already worked (before the current one) and `futureObjectives` are the ones queued after it. Run `attachment-list` mid-session if new files have been uploaded since attach. `--mission-id` is optional for attachment calls when `--objective-id` or `--attachment-id` lets the server derive the mission.
15
+ The `attach` and `load-context` responses already include an `attachments` array plus `previousObjectives` and `futureObjectives` arrays — use those for `<attachment-id>` and `<objective-id>` values. The objective currently being executed is not repeated in those arrays; it is the top-level `objective`. `previousObjectives` are the objectives already worked (before the current one) and `futureObjectives` are the ones queued after it. Run `attachment-list` mid-session if new files have been uploaded since attach. `--mission-id` is optional for attachment calls when `--objective-id` is a full display ID that lets the server derive the mission; an attachment ID alone does not carry mission scope.
16
16
 
17
17
  ## Creating artifacts during a turn
18
18
 
@@ -31,4 +31,3 @@ For large artifacts such as planning documents, architecture decisions, research
31
31
  - Prefer `add-artifact` mid-turn (or a delivery artifact) with a `note` or `decision` type, a concise summary, and the repository file path — not the full document content.
32
32
 
33
33
  This keeps the mission feed readable while preserving the full document in version control where it can be reviewed, diffed, and referenced later. If that summary artifact already exists on the mission, revise it with `update-artifact` rather than creating another copy.
34
-
@@ -164,7 +164,9 @@ const tools = [
164
164
  'Load structured mission context, objectives, history, artifacts, and shared context.',
165
165
  inputSchema: objectSchema(
166
166
  {
167
- missionId: stringProperty('Mission UUID or workspace display id. Optional when objectiveId is a display id such as coo:756.k7xm, which already names its mission.'),
167
+ missionId: stringProperty(
168
+ 'Mission UUID or workspace display id. Optional when objectiveId is a display id such as coo:756.k7xm, which already names its mission.'
169
+ ),
168
170
  objectiveId: stringProperty(
169
171
  'Objective UUID or display id such as coo:756.k7xm. Returns that objective as the current one instead of rediscovering the mission active objective.'
170
172
  ),
@@ -181,7 +183,9 @@ const tools = [
181
183
  description: 'Append one or more draft objectives to an existing mission.',
182
184
  inputSchema: objectSchema(
183
185
  {
184
- missionId: stringProperty('Mission UUID or workspace display id. Optional when objectiveId is a display id such as coo:756.k7xm, which already names its mission.'),
186
+ missionId: stringProperty(
187
+ 'Mission UUID or workspace display id. Optional when objectiveId is a display id such as coo:756.k7xm, which already names its mission.'
188
+ ),
185
189
  objectiveId: stringProperty(
186
190
  'Objective UUID or display id such as coo:756.k7xm. Used only to supply missionId when it is omitted.'
187
191
  ),
@@ -227,7 +231,9 @@ const tools = [
227
231
  'Attach an MCP-hosted agent session to a mission before update/ask/deliver. Pass objectiveId when the caller already knows which objective to execute.',
228
232
  inputSchema: objectSchema(
229
233
  {
230
- missionId: stringProperty('Mission UUID or workspace display id. Optional when objectiveId is a display id such as coo:756.k7xm, which already names its mission.'),
234
+ missionId: stringProperty(
235
+ 'Mission UUID or workspace display id. Optional when objectiveId is a display id such as coo:756.k7xm, which already names its mission.'
236
+ ),
231
237
  objectiveId: stringProperty(
232
238
  'Optional objective UUID or display id (e.g. coo:756.k7xm). Pins attach to that objective.'
233
239
  ),
@@ -246,7 +252,9 @@ const tools = [
246
252
  description: 'Post an update, alert, decision, or discussion summary for an attached session.',
247
253
  inputSchema: objectSchema(
248
254
  {
249
- missionId: stringProperty('Mission UUID or workspace display id. Optional when objectiveId is a display id such as coo:756.k7xm, which already names its mission.'),
255
+ missionId: stringProperty(
256
+ 'Mission UUID or workspace display id. Optional when objectiveId is a display id such as coo:756.k7xm, which already names its mission.'
257
+ ),
250
258
  objectiveId: stringProperty(
251
259
  'Objective UUID or display id such as coo:756.k7xm. Supplies missionId when it is omitted; the session key still determines which objective the event lands on.'
252
260
  ),
@@ -265,7 +273,9 @@ const tools = [
265
273
  'Deliver an attached session with explicit summary, optional change rationales, and optional human-action/tradeoff evidence.',
266
274
  inputSchema: objectSchema(
267
275
  {
268
- missionId: stringProperty('Mission UUID or workspace display id. Optional when objectiveId is a display id such as coo:756.k7xm, which already names its mission.'),
276
+ missionId: stringProperty(
277
+ 'Mission UUID or workspace display id. Optional when objectiveId is a display id such as coo:756.k7xm, which already names its mission.'
278
+ ),
269
279
  objectiveId: stringProperty(
270
280
  'Objective UUID or display id such as coo:756.k7xm. Supplies missionId when it is omitted; the session key still determines which objective is delivered.'
271
281
  ),
@@ -306,7 +316,9 @@ const tools = [
306
316
  'Create a mission artifact during a turn without delivering (plan, notes, decision, URL). Provide type, label, and at least one of contentText or externalUrl. Optional sessionKey stamps provenance. Revise later with overlord_update_artifact.',
307
317
  inputSchema: objectSchema(
308
318
  {
309
- missionId: stringProperty('Mission UUID or workspace display id. Optional when objectiveId is a display id such as coo:756.k7xm, which already names its mission.'),
319
+ missionId: stringProperty(
320
+ 'Mission UUID or workspace display id. Optional when objectiveId is a display id such as coo:756.k7xm, which already names its mission.'
321
+ ),
310
322
  objectiveId: stringProperty(
311
323
  'Objective UUID or display id such as coo:756.k7xm. Stamps objective provenance when no live sessionKey is available.'
312
324
  ),
@@ -328,7 +340,9 @@ const tools = [
328
340
  'Revise an existing mission artifact in place (label, Markdown content, and/or URL) using optimistic concurrency via expectedRevision.',
329
341
  inputSchema: objectSchema(
330
342
  {
331
- missionId: stringProperty('Mission UUID or workspace display id. Optional when objectiveId is a display id such as coo:756.k7xm, which already names its mission.'),
343
+ missionId: stringProperty(
344
+ 'Mission UUID or workspace display id. Optional when objectiveId is a display id such as coo:756.k7xm, which already names its mission.'
345
+ ),
332
346
  objectiveId: stringProperty(
333
347
  'Objective UUID or display id such as coo:756.k7xm. Used only to supply missionId when it is omitted.'
334
348
  ),
@@ -357,7 +371,8 @@ const tools = [
357
371
  title: stringProperty('Optional mission title.'),
358
372
  changeRationales: {
359
373
  type: 'array',
360
- description: 'One entry per meaningful file change (filePath, label, summary, why, impact).'
374
+ description:
375
+ 'One entry per meaningful file change (filePath, label, summary, why, impact).'
361
376
  },
362
377
  changedFiles: {
363
378
  type: 'array',
@@ -384,28 +399,22 @@ function requiredString(args, name) {
384
399
  return value;
385
400
  }
386
401
 
387
- /** Mission display id spelled inside an objective display id (`coo:756.k7xm`). */
388
- function missionFromObjectiveRef(ref) {
389
- const match =
390
- typeof ref === 'string' ? /^(.+:\d+)\.[0-9a-hjkmnp-tv-z]{4,5}$/i.exec(ref.trim()) : null;
391
- return match ? match[1] : null;
392
- }
393
-
394
402
  /**
395
- * Mission/objective addressing shared by every mission-scoped tool: an objective
396
- * display id already names its mission, so a caller holding only that identifier
397
- * can address the tool with it. Mirrors `missionScopeFlags` in mcp/server.ts.
403
+ * Forward mission/objective addressing to the CLI. The CLI owns the shared
404
+ * `@overlord/contract` parser and derives a mission from a display id before it
405
+ * performs local bookkeeping or calls the backend, so this standalone shim
406
+ * does not carry a second copy of the public-id regex.
398
407
  */
399
408
  function missionScopeFlags(args) {
400
409
  const objectiveId = optionalString(args, 'objectiveId');
401
- const missionId = optionalString(args, 'missionId') ?? missionFromObjectiveRef(objectiveId);
402
- if (!missionId) {
410
+ const missionId = optionalString(args, 'missionId');
411
+ if (!missionId && !objectiveId) {
403
412
  throw new Error(
404
413
  'Missing required argument: missionId (pass it, or an objective display id such as coo:756.k7xm as objectiveId)'
405
414
  );
406
415
  }
407
416
  return {
408
- 'mission-id': missionId,
417
+ ...(missionId ? { 'mission-id': missionId } : {}),
409
418
  ...(objectiveId ? { 'objective-id': objectiveId } : {})
410
419
  };
411
420
  }
@@ -478,8 +487,7 @@ function callOverlordTool(name, args) {
478
487
  if (name === 'overlord_add_objectives') {
479
488
  if (!Array.isArray(args.objectives)) throw new Error('objectives must be an array');
480
489
  return runProtocol('add-objectives', {
481
- // objectiveId here only names the mission; the new objectives are appended.
482
- 'mission-id': missionScopeFlags(args)['mission-id'],
490
+ ...missionScopeFlags(args),
483
491
  'objectives-json': args.objectives
484
492
  });
485
493
  }
@@ -491,7 +499,11 @@ function callOverlordTool(name, args) {
491
499
  }
492
500
  return runProtocol('update-objective', {
493
501
  'objective-id': requiredString(args, 'objectiveId'),
494
- ...(hasAutoAdvance ? (args.autoAdvance ? { 'auto-advance': true } : { 'no-auto-advance': true }) : {}),
502
+ ...(hasAutoAdvance
503
+ ? args.autoAdvance
504
+ ? { 'auto-advance': true }
505
+ : { 'no-auto-advance': true }
506
+ : {}),
495
507
  ...(hasInstructionText ? { 'instruction-text': requiredString(args, 'instructionText') } : {})
496
508
  });
497
509
  }
@@ -578,8 +590,7 @@ function callOverlordTool(name, args) {
578
590
  throw new Error('Provide at least one of label, contentText, or externalUrl');
579
591
  }
580
592
  return runProtocol('update-artifact', {
581
- // The artifact is addressed by its own id; objectiveId only scopes the mission.
582
- 'mission-id': missionScopeFlags(args)['mission-id'],
593
+ ...missionScopeFlags(args),
583
594
  'artifact-id': requiredString(args, 'artifactId'),
584
595
  'expected-revision': String(Math.trunc(args.expectedRevision)),
585
596
  ...(hasLabel ? { label: args.label } : {}),
@@ -633,7 +644,7 @@ process.stdin.on('data', async chunk => {
633
644
  result: {
634
645
  protocolVersion: PROTOCOL_VERSION,
635
646
  capabilities: { tools: { listChanged: false } },
636
- serverInfo: { name: 'overlord-__OVERLORD_ADAPTER_KEY__', version: '0.3.27' }
647
+ serverInfo: { name: 'overlord-__OVERLORD_ADAPTER_KEY__', version: '0.3.28' }
637
648
  }
638
649
  });
639
650
  continue;
package/dist/index.js CHANGED
@@ -20806,7 +20806,8 @@ function printProtocolHelp({ primaryCommand }) {
20806
20806
  Use this for mission lifecycle work from an agent runtime: create a standalone
20807
20807
  draft with \`${primaryCommand} protocol create\`, create-and-attach with
20808
20808
  \`${primaryCommand} protocol prompt\`, or attach to an existing mission with
20809
- \`${primaryCommand} protocol attach --mission-id <mission_id>\`.
20809
+ \`${primaryCommand} protocol attach --mission-id <mission_id>\` or
20810
+ \`${primaryCommand} protocol attach --objective-id <mission_id.objective_key>\`.
20810
20811
 
20811
20812
  Backend and auth:
20812
20813
  Configure the REST backend before protocol calls:
@@ -20831,7 +20832,8 @@ Project discovery:
20831
20832
  projects with \`${primaryCommand} create-project --name "<name>"\`.
20832
20833
 
20833
20834
  Agent workflow (required):
20834
- 1. Attach first with \`${primaryCommand} protocol attach --mission-id <id> [--objective-id <id>]\`.
20835
+ 1. Attach first with \`${primaryCommand} protocol attach --mission-id <id>\` or a full
20836
+ objective display id via \`--objective-id <id>\`.
20835
20837
  2. Post progress with \`${primaryCommand} protocol update\` or liveness with
20836
20838
  \`${primaryCommand} protocol heartbeat\`.
20837
20839
  3. Ask blocking questions with \`${primaryCommand} protocol ask\` and stop work.
@@ -22784,7 +22786,7 @@ var init_select_prompt = __esm({
22784
22786
 
22785
22787
  // src/session-key.ts
22786
22788
  import { createHash as createHash10 } from "node:crypto";
22787
- import { existsSync as existsSync28, mkdirSync as mkdirSync15, readFileSync as readFileSync23, rmSync as rmSync7, writeFileSync as writeFileSync14 } from "node:fs";
22789
+ import { existsSync as existsSync28, mkdirSync as mkdirSync15, readdirSync as readdirSync6, readFileSync as readFileSync23, rmSync as rmSync7, writeFileSync as writeFileSync14 } from "node:fs";
22788
22790
  import path32 from "node:path";
22789
22791
  function sessionKeyCachePath({
22790
22792
  missionId,
@@ -22811,10 +22813,7 @@ function readCachedSessionKey({
22811
22813
  objectiveId
22812
22814
  }) {
22813
22815
  if (objectiveId?.trim()) {
22814
- const keyed = readSessionKeyFile(
22815
- sessionKeyCachePath({ missionId, workingDirectory, objectiveId })
22816
- );
22817
- if (keyed) return keyed;
22816
+ return readSessionKeyFile(sessionKeyCachePath({ missionId, workingDirectory, objectiveId }));
22818
22817
  }
22819
22818
  return readSessionKeyFile(sessionKeyCachePath({ missionId, workingDirectory }));
22820
22819
  }
@@ -22852,12 +22851,25 @@ function writeCachedSessionKey({
22852
22851
  function clearCachedSessionKey({
22853
22852
  missionId,
22854
22853
  workingDirectory,
22855
- objectiveId
22854
+ objectiveId,
22855
+ sessionKey
22856
22856
  }) {
22857
22857
  try {
22858
- const files = [sessionKeyCachePath({ missionId, workingDirectory })];
22859
- if (objectiveId?.trim()) {
22860
- files.push(sessionKeyCachePath({ missionId, workingDirectory, objectiveId }));
22858
+ const files = /* @__PURE__ */ new Set();
22859
+ const trimmedSessionKey = sessionKey?.trim();
22860
+ if (trimmedSessionKey) {
22861
+ const cacheDir = path32.join(resolveGlobalDataDir(), "protocol-session-keys");
22862
+ if (existsSync28(cacheDir)) {
22863
+ for (const name of readdirSync6(cacheDir)) {
22864
+ const filePath = path32.join(cacheDir, name);
22865
+ if (readSessionKeyFile(filePath) === trimmedSessionKey) files.add(filePath);
22866
+ }
22867
+ }
22868
+ } else {
22869
+ files.add(sessionKeyCachePath({ missionId, workingDirectory }));
22870
+ if (objectiveId?.trim()) {
22871
+ files.add(sessionKeyCachePath({ missionId, workingDirectory, objectiveId }));
22872
+ }
22861
22873
  }
22862
22874
  for (const filePath of files) {
22863
22875
  if (existsSync28(filePath)) rmSync7(filePath);
@@ -23536,12 +23548,30 @@ async function runProtocolCommand({
23536
23548
  const attachedObjective = asRecord5(resultRecord.objective);
23537
23549
  const attachedObjectiveId = typeof attachedObjective.displayId === "string" && attachedObjective.displayId.trim() || typeof attachedObjective.id === "string" && attachedObjective.id.trim() || // `connect` returns a flat result rather than the full objective record.
23538
23550
  typeof resultRecord.objectiveDisplayId === "string" && resultRecord.objectiveDisplayId.trim() || typeof resultRecord.objectiveId === "string" && resultRecord.objectiveId.trim() || objectiveRef || null;
23539
- writeCachedSessionKey({
23540
- missionId,
23541
- workingDirectory,
23542
- sessionKey: resultRecord.sessionKey,
23543
- objectiveId: attachedObjectiveId
23544
- });
23551
+ const objectiveAliases = new Set(
23552
+ [
23553
+ attachedObjectiveId,
23554
+ typeof attachedObjective.id === "string" ? attachedObjective.id.trim() : null,
23555
+ typeof attachedObjective.displayId === "string" ? attachedObjective.displayId.trim() : null,
23556
+ objectiveRef ?? null
23557
+ ].filter((value) => Boolean(value))
23558
+ );
23559
+ if (objectiveAliases.size === 0) {
23560
+ writeCachedSessionKey({
23561
+ missionId,
23562
+ workingDirectory,
23563
+ sessionKey: resultRecord.sessionKey
23564
+ });
23565
+ } else {
23566
+ for (const objectiveAlias of objectiveAliases) {
23567
+ writeCachedSessionKey({
23568
+ missionId,
23569
+ workingDirectory,
23570
+ sessionKey: resultRecord.sessionKey,
23571
+ objectiveId: objectiveAlias
23572
+ });
23573
+ }
23574
+ }
23545
23575
  if (subcommand === "attach" || subcommand === "resume-follow-up") {
23546
23576
  writeActiveSession({
23547
23577
  workingDirectory,
@@ -23566,7 +23596,12 @@ async function runProtocolCommand({
23566
23596
  }
23567
23597
  }
23568
23598
  if (subcommand === "deliver" && missionId) {
23569
- clearCachedSessionKey({ missionId, workingDirectory });
23599
+ clearCachedSessionKey({
23600
+ missionId,
23601
+ workingDirectory,
23602
+ objectiveId: objectiveRef,
23603
+ sessionKey: typeof flags["--session-key"] === "string" ? flags["--session-key"] : null
23604
+ });
23570
23605
  removeActiveSession({ workingDirectory, missionId });
23571
23606
  clearActiveMissionPointer(workingDirectory);
23572
23607
  const connectorInstallsEditHook = existsSync29(path33.join(os6.homedir(), ".claude")) || existsSync29(
@@ -23975,7 +24010,15 @@ async function runManagementCommand({
23975
24010
  case "requests": {
23976
24011
  const sub = parsed.positional[0];
23977
24012
  if (!sub) {
23978
- const result2 = await runtime.backend.get("/api/agent-requests");
24013
+ const objectiveRef = flagValue(parsed.flags, "--objective-id");
24014
+ const missionId = flagValue(parsed.flags, "--mission-id") ?? missionDisplayIdFromObjectiveRef(objectiveRef);
24015
+ const params = new URLSearchParams();
24016
+ if (missionId) params.set("missionId", missionId);
24017
+ if (objectiveRef) params.set("objectiveId", objectiveRef);
24018
+ const query = params.size > 0 ? `?${params.toString()}` : "";
24019
+ const result2 = await runtime.backend.get(
24020
+ `/api/agent-requests${query}`
24021
+ );
23979
24022
  if (json) printJson(result2);
23980
24023
  else {
23981
24024
  for (const item of result2.requests) {
@@ -24026,8 +24069,11 @@ async function runManagementCommand({
24026
24069
  message: "Usage: ovld inputs list --mission-id <id> [--json] | ovld inputs send --channel-id <id> --body <text> [--json]"
24027
24070
  });
24028
24071
  }
24072
+ const objectiveRef = flagValue(parsed.flags, "--objective-id");
24073
+ const params = new URLSearchParams({ missionId });
24074
+ if (objectiveRef) params.set("objectiveId", objectiveRef);
24029
24075
  const result = await runtime.backend.get(
24030
- `/api/agent-session-inputs?missionId=${encodeURIComponent(missionId)}`
24076
+ `/api/agent-session-inputs?${params.toString()}`
24031
24077
  );
24032
24078
  if (json) printJson(result);
24033
24079
  else {
@@ -24692,7 +24738,7 @@ var COMMAND_FLAGS = {
24692
24738
  "--no-start"
24693
24739
  ],
24694
24740
  missions: ["--status", "--query", "--project-id", "--limit"],
24695
- requests: ["--revision", "--decision", "--text"],
24741
+ requests: ["--mission-id", "--objective-id", "--revision", "--decision", "--text"],
24696
24742
  inputs: ["--mission-id", "--objective-id", "--channel-id", "--body", "--kind"],
24697
24743
  mission: [],
24698
24744
  changes: ["--mission-id", "--objective-id"]
@@ -24812,8 +24858,11 @@ Missions:
24812
24858
  ${primaryCommand} attach <missionId> [agent] [--json]
24813
24859
  ${primaryCommand} missions list [--status <csv>] [--project-id <id>] [--json]
24814
24860
  ${primaryCommand} mission context|events|deliveries|artifacts|rationales <missionId> [--json]
24815
- ${primaryCommand} requests [--json] List open and recent agent decisions
24861
+ ${primaryCommand} requests [--mission-id <id>] [--objective-id <id>] [--json]
24862
+ List open and recent agent decisions
24816
24863
  ${primaryCommand} requests resolve <id> --revision <n> --decision allow|deny|ask [--text <text>]
24864
+ ${primaryCommand} inputs list [--mission-id <id>] [--objective-id <id>] [--json]
24865
+ List instructions for one mission or objective
24817
24866
 
24818
24867
  Launch and runner:
24819
24868
  ${primaryCommand} launch <agent> --mission-id <missionId> [--branch <name>] [--no-worktree] [--dry-run] [--json]
@@ -24832,8 +24881,8 @@ Agents:
24832
24881
  connect, load-context, update, heartbeat, ask, deliver.
24833
24882
 
24834
24883
  Protocol (JSON output by default):
24835
- ${primaryCommand} protocol attach --mission-id <id> [--objective-id <id>]
24836
- ${primaryCommand} protocol update --mission-id <id> --session-key <key> --summary "..."
24884
+ ${primaryCommand} protocol attach --mission-id <id> | --objective-id <display-id>
24885
+ ${primaryCommand} protocol update --objective-id <display-id> --session-key <key> --summary "..."
24837
24886
  ${primaryCommand} protocol heartbeat --mission-id <id> --session-key <key>
24838
24887
  ${primaryCommand} protocol ask --mission-id <id> --session-key <key> --question "..."
24839
24888
  ${primaryCommand} protocol deliver --mission-id <id> --session-key <key> --summary "..."