agent-conveyor 0.1.15 → 0.1.17

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 CHANGED
@@ -315,14 +315,18 @@ tmux attach -t codex-live-test
315
315
  Upsert the structured brief for a channel.
316
316
  - `campaign assign --name C --slot SLOT_ID --title TEXT --instructions TEXT [--status queued|active|blocked|done|cancelled] [--metadata-json JSON] [--json]` —
317
317
  Create a slot-scoped assignment.
318
- - `campaign asset --name C --slot SLOT_ID --asset-type image|video|hyperframes|copy|audio|other --title TEXT [--assignment ASSIGNMENT_ID] [--channel CH] [--status draft|needs_review|approved|rejected|published] [--prompt-summary TEXT] [--artifact-path PATH] [--metadata-json JSON] [--review-notes TEXT] [--json]` —
319
- Record a structured creative asset receipt.
318
+ - `campaign asset --name C --slot SLOT_ID --asset-type image|video|hyperframes|copy|audio|other --title TEXT [--assignment ASSIGNMENT_ID] [--channel CH] [--status draft|needs_review|approved|rejected|published] [--prompt-summary TEXT] [--artifact-path PATH] [--metadata-json JSON] [--review-notes TEXT] [--allow-additional-receipt] [--json]` —
319
+ Record a structured creative asset receipt. Assignment-scoped receipts are
320
+ one-per-assignment by default; use `--allow-additional-receipt` only for
321
+ intentional variants or revisions.
320
322
  - `campaign status --name C [--json]` —
321
323
  Show campaign metadata, worker slots, channel briefs, assignment counts, and
322
324
  asset receipt counts.
323
325
  - `campaign dashboard --name C [--json]` —
324
326
  Show a manager-oriented campaign aggregate: worker slot lifecycle states,
325
- blockers, approval counts, and the next recommended manager action.
327
+ blockers, approval counts, and the next recommended manager action. This is
328
+ also the supported way to inspect asset receipts and per-slot receipt counts;
329
+ there is no separate `campaign assets` subcommand.
326
330
 
327
331
  Creative Ops Campaign manager loop:
328
332
 
@@ -606,6 +610,9 @@ stay out of receipts.
606
610
  permissions, expected tools, epilogues, evidence gates, cleanup behavior,
607
611
  disallowed actions, locked setup summary template, and suggested
608
612
  `manager-config` command. Use this before cutting a manager loose.
613
+ `campaign-duplicate-guard-dogfood` is the recipe for visible creative
614
+ campaign dogfoods that prove accidental duplicate assignment receipts are
615
+ rejected unless a worker explicitly uses `--allow-additional-receipt`.
609
616
  - `worker-ack <task> --from-stdin|--json [--correlation-id ID]` /
610
617
  `manager-ack <task> --from-stdin|--json [--correlation-id ID]` — Persist or
611
618
  read the latest structured acknowledgement from the worker or manager. Acks
@@ -384,7 +384,11 @@ function commandHelpText(program, command) {
384
384
  ` ${program} finish-task my-task --reason "Accepted criteria satisfied" --require-criteria-audit --path /tmp/work/workerctl.db --json`,
385
385
  ],
386
386
  campaign: [
387
- `usage: ${program} campaign <create|add-slot|attach-slot|rotate-slot|archive-slot|brief|assign|asset|status|dashboard> --name <campaign> [options] ${path} [--json]`,
387
+ `usage: ${program} campaign <${campaignActionsUsage()}> --name <campaign> [options] ${path} [--json]`,
388
+ "",
389
+ `Supported subcommands: ${campaignActionsUsage()}`,
390
+ "",
391
+ "Use `dashboard` to list campaign assets and slot receipt counts; there is no separate `assets` subcommand.",
388
392
  "",
389
393
  "Examples:",
390
394
  ` ${program} campaign create --name launch --objective "Create launch assets" --metadata-json '{"owner":"ops"}' --json`,
@@ -395,6 +399,7 @@ function commandHelpText(program, command) {
395
399
  ` ${program} campaign brief --name launch --channel tiktok --brief-json '{"format":"9:16"}' --json`,
396
400
  ` ${program} campaign assign --name launch --slot campaign-slot-id --title "Draft hooks" --instructions "Create hooks" --status active --json`,
397
401
  ` ${program} campaign asset --name launch --slot campaign-slot-id --assignment campaign-assignment-id --asset-type copy --title "Hooks v1" --status needs_review --json`,
402
+ ` ${program} campaign asset --name launch --slot campaign-slot-id --assignment campaign-assignment-id --asset-type copy --title "Hooks v2" --allow-additional-receipt --json`,
398
403
  ` ${program} campaign status --name launch --json`,
399
404
  ` ${program} campaign dashboard --name launch --json`,
400
405
  ],
@@ -471,7 +476,8 @@ function commandHelpText(program, command) {
471
476
  };
472
477
  return linesByCommand[command] ?? [`usage: ${program} ${command} [-h] [options]`];
473
478
  }
474
- const CAMPAIGN_ACTIONS = new Set(["create", "add-slot", "attach-slot", "rotate-slot", "archive-slot", "brief", "assign", "asset", "status", "dashboard"]);
479
+ const CAMPAIGN_ACTION_NAMES = ["create", "add-slot", "attach-slot", "rotate-slot", "archive-slot", "brief", "assign", "asset", "status", "dashboard"];
480
+ const CAMPAIGN_ACTIONS = new Set(CAMPAIGN_ACTION_NAMES);
475
481
  const CAMPAIGN_STRING_FLAGS = {
476
482
  "--artifact-path": "artifactPath",
477
483
  "--asset-type": "assetType",
@@ -498,6 +504,7 @@ function parseRuntimeArgs(args, env) {
498
504
  includeFullTranscripts: false,
499
505
  includeTranscripts: false,
500
506
  all: false,
507
+ allowAdditionalReceipt: false,
501
508
  action: null,
502
509
  artifactPath: null,
503
510
  assetType: null,
@@ -767,6 +774,12 @@ function parseRuntimeArgs(args, env) {
767
774
  else if (arg === "--all") {
768
775
  flags.all = true;
769
776
  }
777
+ else if (arg === "--allow-additional-receipt") {
778
+ if (command !== "campaign") {
779
+ return { command, enabled, error: "Unsupported TypeScript runtime option: --allow-additional-receipt", explicit, flags, passthroughArgs, task };
780
+ }
781
+ flags.allowAdditionalReceipt = true;
782
+ }
770
783
  else if (arg === "--active") {
771
784
  flags.active = true;
772
785
  }
@@ -3014,7 +3027,7 @@ function parseRuntimeArgs(args, env) {
3014
3027
  }
3015
3028
  else if (command === "campaign" && flags.action === null) {
3016
3029
  if (!CAMPAIGN_ACTIONS.has(arg)) {
3017
- return { command, enabled, error: `Unsupported campaign action: ${arg}`, explicit, flags, task };
3030
+ return { command, enabled, error: unsupportedCampaignActionMessage(arg), explicit, flags, task };
3018
3031
  }
3019
3032
  flags.action = arg;
3020
3033
  }
@@ -6216,6 +6229,7 @@ function runCampaignCommand(parsed, options) {
6216
6229
  const status = campaignAssetStatusArg(parsed.flags.statusState);
6217
6230
  const metadata = jsonObjectArg(parsed.flags.metadataJson, "--metadata-json");
6218
6231
  const assetReceiptId = recordCampaignAssetReceiptSync(database, {
6232
+ allowAdditionalReceipt: parsed.flags.allowAdditionalReceipt,
6219
6233
  artifactPath: parsed.flags.artifactPath,
6220
6234
  assetType,
6221
6235
  assignment: parsed.flags.assignment,
@@ -6244,12 +6258,18 @@ function runCampaignCommand(parsed, options) {
6244
6258
  const dashboard = campaignDashboardSync(database, campaign);
6245
6259
  return campaignResult(parsed, dashboard, renderCampaignDashboardText(dashboard));
6246
6260
  }
6247
- return errorResult(`Unsupported campaign action: ${action}`);
6261
+ return errorResult(unsupportedCampaignActionMessage(action));
6248
6262
  }
6249
6263
  finally {
6250
6264
  database.close();
6251
6265
  }
6252
6266
  }
6267
+ function campaignActionsUsage() {
6268
+ return CAMPAIGN_ACTION_NAMES.join("|");
6269
+ }
6270
+ function unsupportedCampaignActionMessage(action) {
6271
+ return `Unsupported campaign action: ${action ?? "<missing>"}; expected one of: ${CAMPAIGN_ACTION_NAMES.join(", ")}. Use \`conveyor campaign dashboard --name <campaign> --json\` to list assets and receipt counts.`;
6272
+ }
6253
6273
  function campaignResult(parsed, payload, lines) {
6254
6274
  return parsed.flags.json ? jsonResult(payload) : textResult(lines);
6255
6275
  }
@@ -17203,6 +17223,45 @@ const MANAGER_RECIPES = {
17203
17223
  supportPatterns: ["Inbox / No-Tmux App Loop", "Recovery / Resume / Handoff"],
17204
17224
  tools: ["verification.run_tests", "context.fetch_prs"],
17205
17225
  },
17226
+ "campaign-duplicate-guard-dogfood": {
17227
+ acceptance: [
17228
+ "The campaign dashboard shows exactly one normal asset receipt for each active assignment before the duplicate probe.",
17229
+ "A worker visibly attempts an accidental duplicate `campaign asset` receipt without --allow-additional-receipt and records the expected non-zero failure.",
17230
+ "Manager independently verifies the post-probe dashboard still has the original asset_total, the probed slot still has one receipt, and blockers are empty.",
17231
+ ],
17232
+ cleanup: "off by default; archive or rotate only campaign-owned worker slots with exact expected thread ids",
17233
+ description: "Dogfood creative campaign workers while proving assignment-scoped duplicate receipts are blocked unless explicitly allowed.",
17234
+ disallowedActions: [
17235
+ "Do not use --allow-additional-receipt for the accidental duplicate probe.",
17236
+ "Do not treat the worker's duplicate-failure claim as proof until the manager verifies the dashboard.",
17237
+ "Do not publish, schedule, contact external services, inspect private content, edit product/content files, or commit during the dogfood.",
17238
+ "Do not archive or rotate a worker thread unless the campaign slot owns that exact thread id.",
17239
+ ],
17240
+ displayName: "Campaign Duplicate-Guard Dogfood",
17241
+ epilogues: [],
17242
+ evidenceGates: [
17243
+ "campaign_dashboard_pre_probe",
17244
+ "visible_worker_duplicate_failure",
17245
+ "duplicate_failure_exit_code",
17246
+ "post_probe_dashboard_no_extra_asset",
17247
+ "manager_duplicate_guard_decision",
17248
+ ],
17249
+ finalReportRequirements: [
17250
+ "Report the manager thread id, worker thread ids, assignment ids, original receipt ids, duplicate error text, pre/post dashboard counts, and residual cleanup status.",
17251
+ ],
17252
+ guidelines: [
17253
+ "Keep manager and worker sessions visibly chatty with CONVEYOR RECEIVED, WORK, and CONVEYOR SEND sections.",
17254
+ "Use `campaign dashboard --name <campaign> --json` as the supported receipt-listing surface.",
17255
+ "Ask exactly one worker to perform the missing-override duplicate probe, then require manager-side dashboard verification before closeout.",
17256
+ ],
17257
+ loopTemplate: null,
17258
+ mode: "strict",
17259
+ name: "campaign-duplicate-guard-dogfood",
17260
+ objective: "Supervise a visible campaign dogfood that proves duplicate assignment receipts fail closed without --allow-additional-receipt.",
17261
+ permissions: [],
17262
+ supportPatterns: ["Creative Ops Campaign", "Inbox / No-Tmux App Loop", "Recovery / Resume / Handoff"],
17263
+ tools: ["campaign.dashboard", "codex_app.send_message_to_thread"],
17264
+ },
17206
17265
  "nudge-whats-next": {
17207
17266
  acceptance: [
17208
17267
  "Accepted criteria are satisfied or explicitly deferred.",
@@ -17361,6 +17420,10 @@ const MANAGER_RECIPES = {
17361
17420
  },
17362
17421
  };
17363
17422
  const MANAGER_RECIPE_ALIASES = {
17423
+ "campaign duplicate guard": "campaign-duplicate-guard-dogfood",
17424
+ "campaign duplicate guard dogfood": "campaign-duplicate-guard-dogfood",
17425
+ "creative duplicate guard": "campaign-duplicate-guard-dogfood",
17426
+ "duplicate guard dogfood": "campaign-duplicate-guard-dogfood",
17364
17427
  "goalbuddy conveyor": "goalbuddy-conveyor",
17365
17428
  goalbuddy: "goalbuddy-conveyor",
17366
17429
  "nudge / what's next manager": "nudge-whats-next",