@useorgx/wizard 0.1.65 → 0.1.67

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
@@ -32,7 +32,7 @@ The wizard modifies local tool configuration only. Depending on the command, it
32
32
  - Every profile or preview writes both the full evidence report and a compact, machine-safe `work-graph-agent-brief-*.md` with provenance, the growth edge, and a ready prompt for the smallest verifiable repair.
33
33
  - `work-graph preview --from all` shows the same profile story locally without publishing.
34
34
  - `work-graph runtime-event --source codex|claude --summary "..."` lets an agent write public-safe runtime evidence that the next AQ profile can collect.
35
- - `hooks install [--targets codex,claude-code]` installs bounded local capture hooks. Terminal events write compact session summaries to a durable queue, then request a detached single-flight delivery worker. The hook does not read credentials or perform network I/O. Set `ORGX_SESSION_SUMMARY_AUTO_FLUSH=off` for local-only capture and manual delivery. The legacy transcript-derived execution-graph emit remains off unless `ORGX_EMIT_EXECUTION_GRAPH=1` is set.
35
+ - `hooks install [--targets codex,claude-code]` installs bounded local capture hooks. Terminal session events and adapter-supplied `RunEnd` events write compact summaries to a durable queue, then request a detached single-flight delivery worker. `RunEnd` represents one completed agent run inside a conversation that may continue. Receipt-ready captures remain queued until the server confirms that the automatic receipt was persisted; a session-only 2xx response is not enough. The hook does not read credentials or perform network I/O. Set `ORGX_SESSION_SUMMARY_AUTO_FLUSH=off` for local-only capture and manual delivery. The legacy transcript-derived execution-graph emit remains off unless `ORGX_EMIT_EXECUTION_GRAPH=1` is set.
36
36
  - `ORGX_SESSION_WORK_CONTEXT` can carry one explicit, bounded JSON annotation for intent, authority, cost, artifact and evidence references, plus exact Context Capsule, decision, constraint, expectation, applied-learning, and prior-receipt references. Capsule delivery requires both the capsule reference and delivery timestamp. The Wizard does not infer this context from prompts; invalid or oversized annotations are omitted, and unknown fields are removed before cloud delivery.
37
37
  - `hooks flush [--limit 100]` is the manual delivery and recovery path. It uses the same queue lease as automatic delivery and removes each valid file only after a successful server acknowledgement. Failed captures stay queued for retry; malformed captures move to the owner-only `session-summary-captures/quarantine/` directory and make a manual flush fail visibly without being deleted.
38
38
  - `hooks doctor` shows hook wiring, automatic-delivery configuration, active and quarantined capture counts, and the legacy spool count without changing local configuration.
package/dist/cli.js CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  // src/cli.ts
4
4
 
5
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="af54c3d7-9ef3-5d66-90dc-45a9ecb71d96")}catch(e){}}();
5
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="20c1b754-5691-5226-9f34-921cdff2d9f8")}catch(e){}}();
6
6
  import * as clack from "@clack/prompts";
7
7
  import { spawnSync as spawnSync5 } from "child_process";
8
8
  import { readFileSync as readFileSync10 } from "fs";
@@ -6354,7 +6354,7 @@ function initializeWizardSentry() {
6354
6354
  Sentry.init({
6355
6355
  dsn,
6356
6356
  environment: process.env.ORGX_SENTRY_ENVIRONMENT || "production",
6357
- release: "useorgx-wizard@0.1.65",
6357
+ release: "useorgx-wizard@0.1.67",
6358
6358
  tracesSampleRate: sampleRate(process.env.ORGX_SENTRY_TRACES_SAMPLE_RATE),
6359
6359
  enableLogs: true,
6360
6360
  sendDefaultPii: false,
@@ -13969,7 +13969,9 @@ function actionResult(event, sourceClient) {
13969
13969
  // Claude's PostToolUse contract fires only after success. Codex documents
13970
13970
  // PostToolUse for completed tools, including non-zero Bash exits, so its
13971
13971
  // outcome must remain explicitly unclassified without reading tool output.
13972
- return sourceClient === "claude-code" ? "succeeded" : "completed_unknown";
13972
+ return sourceClient === "claude-code" || sourceClient === "cursor" || sourceClient === "opencode"
13973
+ ? "succeeded"
13974
+ : "completed_unknown";
13973
13975
  }
13974
13976
 
13975
13977
  function pendingIndex(state, toolUseId) {
@@ -14135,7 +14137,7 @@ function buildExecutionObservation(state, captureKind) {
14135
14137
  return {
14136
14138
  schema_version: "orgx-session-execution-observation/v1",
14137
14139
  boundary: captureKind || "legacy_unspecified",
14138
- terminal_observed: captureKind === "session_end",
14140
+ terminal_observed: captureKind === "run_end" || captureKind === "session_end",
14139
14141
  actions: actions,
14140
14142
  actions_completed_observed: state.tool_calls,
14141
14143
  actions_omitted: omitted,
@@ -14443,7 +14445,15 @@ export async function main(options) {
14443
14445
  var explicitWorkContext = parseExplicitWorkContext(env.ORGX_SESSION_WORK_CONTEXT);
14444
14446
 
14445
14447
  var event = pickString(args.event, payload.hook_event_name, payload.hookEventName, "unknown");
14446
- var sessionId = pickString(payload.session_id, payload.sessionId, args.session_id);
14448
+ var sessionId = pickString(
14449
+ payload.session_id,
14450
+ payload.sessionId,
14451
+ payload.conversation_id,
14452
+ payload.conversationId,
14453
+ payload.thread_id,
14454
+ payload.threadId,
14455
+ args.session_id
14456
+ );
14447
14457
  if (!sessionId) return { ok: true, skipped: "missing_session_id" };
14448
14458
 
14449
14459
  var sourceClient = pickString(args.source_client, env.ORGX_SOURCE_CLIENT, "claude-code");
@@ -14451,7 +14461,7 @@ export async function main(options) {
14451
14461
  var stateDir = dir ? dir : pickString(args.state_dir, env.ORGX_SESSION_STATE_DIR);
14452
14462
  var path = statePath(sessionId, stateDir);
14453
14463
 
14454
- var terminal = event === "Stop" || event === "SessionEnd";
14464
+ var terminal = event === "Stop" || event === "RunEnd" || event === "SessionEnd";
14455
14465
 
14456
14466
  if (!terminal) {
14457
14467
  // Hot path: one small file read + write. Never a network call.
@@ -14487,13 +14497,17 @@ export async function main(options) {
14487
14497
  if (explicitWorkContext) finalState.work_context = explicitWorkContext;
14488
14498
  var initiativeId = pickString(env.ORGX_INITIATIVE_ID, args.initiative);
14489
14499
  var queueDir = pickString(args.queue_dir, env.ORGX_SESSION_SUMMARY_QUEUE_DIR) || defaultQueueDir();
14490
- var captureKind = event === "SessionEnd" ? "session_end" : "turn_boundary";
14500
+ var captureKind = event === "SessionEnd"
14501
+ ? "session_end"
14502
+ : event === "RunEnd"
14503
+ ? "run_end"
14504
+ : "turn_boundary";
14491
14505
  var summary = buildSummary(finalState, nowIso, captureKind);
14492
14506
  var queued = enqueueSummaryCapture(queueDir, summary, initiativeId, nowIso, captureKind);
14493
14507
  if (!queued) return { ok: true, skipped: "queue_write_failed", summary: summary };
14494
14508
  var deliveryTriggered = triggerQueueDelivery(args, env, queueDir, spawnImpl);
14495
14509
 
14496
- if (event === "SessionEnd") {
14510
+ if (event === "RunEnd" || event === "SessionEnd") {
14497
14511
  try {
14498
14512
  rmSync(path, { force: true });
14499
14513
  } catch (e) {
@@ -14506,7 +14520,7 @@ export async function main(options) {
14506
14520
  queued: true,
14507
14521
  queue_path: queued.path,
14508
14522
  delivery_triggered: deliveryTriggered,
14509
- final: event === "SessionEnd",
14523
+ final: event === "RunEnd" || event === "SessionEnd",
14510
14524
  summary: summary,
14511
14525
  };
14512
14526
  }
@@ -15397,6 +15411,7 @@ function normalizeSessionExecutionObservation(value) {
15397
15411
  const boundary = boundedString(value.boundary, 40);
15398
15412
  if (!boundary || ![
15399
15413
  "turn_boundary",
15414
+ "run_end",
15400
15415
  "session_end",
15401
15416
  "historical_backfill",
15402
15417
  "legacy_unspecified"
@@ -15676,6 +15691,24 @@ function quarantineMalformedCapture(path, queueDir) {
15676
15691
  function isRecord4(value) {
15677
15692
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
15678
15693
  }
15694
+ function expectsAutomaticReceipt(body) {
15695
+ const session = isRecord4(body.session) ? body.session : {};
15696
+ const metadata = isRecord4(session.metadata) ? session.metadata : {};
15697
+ const capture = isRecord4(metadata.capture) ? metadata.capture : {};
15698
+ const execution = isRecord4(metadata.execution) ? metadata.execution : {};
15699
+ const workContext = isRecord4(metadata.work_context) ? metadata.work_context : {};
15700
+ const actions = Array.isArray(execution.actions) ? execution.actions : [];
15701
+ const completed = execution.actions_completed_observed;
15702
+ return (capture.kind === "run_end" || capture.kind === "session_end") && execution.boundary === capture.kind && execution.terminal_observed === true && execution.action_capture_complete === true && typeof completed === "number" && completed > 0 && session.tool_calls === completed && execution.actions_omitted === 0 && execution.start_times_omitted === 0 && execution.pending_actions === 0 && actions.length === completed && actions.every((value) => {
15703
+ const action = isRecord4(value) ? value : {};
15704
+ return action.status !== "running" && typeof action.started_at === "string" && typeof action.completed_at === "string";
15705
+ }) && isRecord4(workContext.intent) && isRecord4(workContext.authority) && isRecord4(workContext.cost);
15706
+ }
15707
+ function confirmsAutomaticReceipt(response) {
15708
+ const body = isRecord4(response.body) ? response.body : {};
15709
+ const receipt = isRecord4(body.automatic_receipt) ? body.automatic_receipt : {};
15710
+ return receipt.ready === true && receipt.persisted === true && typeof receipt.receipt_id === "string" && receipt.receipt_id.length > 0;
15711
+ }
15679
15712
  function isSessionSummary(value) {
15680
15713
  if (!isRecord4(value)) return false;
15681
15714
  return typeof value.schema_version === "string" && typeof value.session_id === "string" && typeof value.source_client === "string";
@@ -15710,7 +15743,7 @@ function parseSessionSummaryCapture(raw) {
15710
15743
  // Captures created by wizard 0.1.56 before this field existed must remain
15711
15744
  // deliverable. Preserve the uncertainty instead of guessing that an old
15712
15745
  // snapshot represented a real SessionEnd.
15713
- capture_kind: value.capture_kind === "turn_boundary" || value.capture_kind === "session_end" ? value.capture_kind : "legacy_unspecified",
15746
+ capture_kind: value.capture_kind === "turn_boundary" || value.capture_kind === "run_end" || value.capture_kind === "session_end" ? value.capture_kind : "legacy_unspecified",
15714
15747
  queued_at: value.queued_at,
15715
15748
  session: value.session,
15716
15749
  ...typeof value.initiative_id === "string" ? { initiative_id: value.initiative_id } : {}
@@ -15786,7 +15819,9 @@ async function flushSessionSummaryCaptures(options) {
15786
15819
  retained: 0,
15787
15820
  malformed: 0,
15788
15821
  quarantined: 0,
15789
- fallbackAcknowledged: 0
15822
+ fallbackAcknowledged: 0,
15823
+ receiptExpected: 0,
15824
+ receiptAcknowledged: 0
15790
15825
  };
15791
15826
  for (const path of selected) {
15792
15827
  const capture = readSessionSummaryCapture(path);
@@ -15805,11 +15840,21 @@ async function flushSessionSummaryCaptures(options) {
15805
15840
  let response;
15806
15841
  let usedFallback = false;
15807
15842
  try {
15808
- response = await options.send(primaryUrl, deliveryBody(capture), headers);
15843
+ const body = deliveryBody(capture);
15844
+ const receiptExpected = expectsAutomaticReceipt(body);
15845
+ if (receiptExpected) result.receiptExpected += 1;
15846
+ response = await options.send(primaryUrl, body, headers);
15809
15847
  if (!response.ok && (response.status === 404 || response.status === 405)) {
15810
15848
  response = await options.send(fallbackUrl, buildWorkGraphFallback(capture), headers);
15811
15849
  usedFallback = true;
15812
15850
  }
15851
+ if (response.ok && receiptExpected && !confirmsAutomaticReceipt(response)) {
15852
+ result.retained += 1;
15853
+ result.firstError ??= `HTTP ${response.status} did not confirm automatic receipt persistence for ${capture.capture_id}`;
15854
+ if (options.stopOnFailure) break;
15855
+ continue;
15856
+ }
15857
+ if (response.ok && receiptExpected) result.receiptAcknowledged += 1;
15813
15858
  } catch {
15814
15859
  response = { ok: false, status: 0 };
15815
15860
  }
@@ -16711,6 +16756,13 @@ function printSessionSummaryFlush(result) {
16711
16756
  if (result.fallbackAcknowledged > 0) {
16712
16757
  console.log(` ${ICON.warn} ${pc3.bold("fallback ")} ${pc3.dim(`${result.fallbackAcknowledged} capture(s) delivered through the legacy Work Graph endpoint`)}`);
16713
16758
  }
16759
+ if (result.receiptExpected > 0) {
16760
+ const receiptStatus = `${result.receiptAcknowledged}/${result.receiptExpected} persisted`;
16761
+ const receiptIcon = result.receiptAcknowledged === result.receiptExpected ? ICON.ok : ICON.warn;
16762
+ console.log(
16763
+ ` ${receiptIcon} ${pc3.bold("receipts ")} ${pc3.dim(receiptStatus)}`
16764
+ );
16765
+ }
16714
16766
  if (result.firstError) console.log(` ${ICON.warn} ${pc3.dim(result.firstError)}`);
16715
16767
  }
16716
16768
  async function runSessionSummaryFlushCommand(options) {
@@ -16726,6 +16778,8 @@ async function runSessionSummaryFlushCommand(options) {
16726
16778
  malformed: 0,
16727
16779
  quarantined: 0,
16728
16780
  fallbackAcknowledged: 0,
16781
+ receiptExpected: 0,
16782
+ receiptAcknowledged: 0,
16729
16783
  skipped: "empty_queue"
16730
16784
  };
16731
16785
  } else {
@@ -16743,6 +16797,8 @@ async function runSessionSummaryFlushCommand(options) {
16743
16797
  malformed: 0,
16744
16798
  quarantined: 0,
16745
16799
  fallbackAcknowledged: 0,
16800
+ receiptExpected: 0,
16801
+ receiptAcknowledged: 0,
16746
16802
  skipped: "already_running"
16747
16803
  };
16748
16804
  } else {
@@ -16768,7 +16824,17 @@ async function runSessionSummaryFlushCommand(options) {
16768
16824
  },
16769
16825
  options.background ? { timeoutMs: 8e3, retries: 0 } : { timeoutMs: 12e3, retries: 1 }
16770
16826
  );
16771
- return { ok: response.ok, status: response.status };
16827
+ let responseBody;
16828
+ try {
16829
+ responseBody = await response.json();
16830
+ } catch {
16831
+ responseBody = void 0;
16832
+ }
16833
+ return {
16834
+ ok: response.ok,
16835
+ status: response.status,
16836
+ body: responseBody
16837
+ };
16772
16838
  } catch {
16773
16839
  return { ok: false, status: 0 };
16774
16840
  }
@@ -18563,7 +18629,7 @@ async function main() {
18563
18629
  initializeWizardSentry();
18564
18630
  const program = new Command();
18565
18631
  program.name("orgx-wizard").description("Add OrgX MCP configs, skills/rules, and companion plugins to your local AI tools.").showHelpAfterError();
18566
- const pkgVersion = true ? "0.1.65" : void 0;
18632
+ const pkgVersion = true ? "0.1.67" : void 0;
18567
18633
  program.version(pkgVersion ?? "unknown", "-V, --version");
18568
18634
  program.hook("preAction", (_thisCommand, actionCommand) => {
18569
18635
  if (Boolean(actionCommand.optsWithGlobals().json)) return;
@@ -19607,4 +19673,4 @@ main().catch(async (error) => {
19607
19673
  process.exitCode = 1;
19608
19674
  });
19609
19675
  //# sourceMappingURL=cli.js.map
19610
- //# debugId=af54c3d7-9ef3-5d66-90dc-45a9ecb71d96
19676
+ //# debugId=20c1b754-5691-5226-9f34-921cdff2d9f8