@gajae-code/coding-agent 0.12.6 → 0.12.8

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 (150) hide show
  1. package/CHANGELOG.md +22 -1
  2. package/dist/types/async/job-manager.d.ts +36 -1
  3. package/dist/types/commands/notify.d.ts +4 -0
  4. package/dist/types/config/file-lock.d.ts +3 -0
  5. package/dist/types/config/model-discovery-manager.d.ts +6 -1
  6. package/dist/types/config/model-registry.d.ts +2 -0
  7. package/dist/types/config/resolve-config-value.d.ts +2 -1
  8. package/dist/types/config/settings-schema.d.ts +17 -1
  9. package/dist/types/eval/backend.d.ts +2 -2
  10. package/dist/types/exec/bash-executor.d.ts +8 -10
  11. package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +0 -36
  12. package/dist/types/internal-urls/registry-helpers.d.ts +0 -18
  13. package/dist/types/main.d.ts +1 -0
  14. package/dist/types/modes/components/hook-selector.d.ts +20 -0
  15. package/dist/types/modes/components/notifications-settings-editor.d.ts +53 -4
  16. package/dist/types/modes/controllers/extension-ui-controller.d.ts +1 -1
  17. package/dist/types/modes/controllers/selector-controller.d.ts +4 -2
  18. package/dist/types/sdk/broker/broker.d.ts +5 -1
  19. package/dist/types/sdk/broker/lifecycle-ledger.d.ts +1 -0
  20. package/dist/types/sdk/bus/chat-daemon-control.d.ts +11 -3
  21. package/dist/types/sdk/bus/config.d.ts +75 -113
  22. package/dist/types/sdk/bus/discord-live-provider.d.ts +8 -2
  23. package/dist/types/sdk/bus/discord-provider.d.ts +19 -0
  24. package/dist/types/sdk/bus/index.d.ts +1 -1
  25. package/dist/types/sdk/bus/notification-orchestration.d.ts +127 -18
  26. package/dist/types/sdk/bus/notification-service.d.ts +31 -4
  27. package/dist/types/sdk/bus/session-control.d.ts +8 -3
  28. package/dist/types/sdk/bus/slack-live-provider.d.ts +9 -2
  29. package/dist/types/sdk/bus/slack-provider.d.ts +22 -0
  30. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +9 -4
  31. package/dist/types/sdk/client/discovery.d.ts +2 -1
  32. package/dist/types/sdk/host/host.d.ts +2 -23
  33. package/dist/types/sdk/host/query/handlers.d.ts +2 -0
  34. package/dist/types/sdk/host/reverse-leases.d.ts +4 -7
  35. package/dist/types/sdk/index.d.ts +1 -0
  36. package/dist/types/sdk/providers.d.ts +22 -0
  37. package/dist/types/sdk/session-directory.d.ts +1 -1
  38. package/dist/types/session/artifacts.d.ts +5 -8
  39. package/dist/types/session/client-bridge.d.ts +0 -14
  40. package/dist/types/session/internal/managed-session-scope.d.ts +17 -1
  41. package/dist/types/session/internal/managed-session-storage.d.ts +11 -4
  42. package/dist/types/session/internal/native-publish-outcome.d.ts +1 -0
  43. package/dist/types/session/internal/session-open-errors.d.ts +5 -0
  44. package/dist/types/session/messages.d.ts +1 -4
  45. package/dist/types/session/session-manager.d.ts +7 -6
  46. package/dist/types/session/session-storage.d.ts +2 -0
  47. package/dist/types/session/streaming-output.d.ts +0 -32
  48. package/dist/types/task/receipt.d.ts +1 -2
  49. package/dist/types/task/types.d.ts +43 -178
  50. package/dist/types/tools/bash.d.ts +1 -1
  51. package/dist/types/tools/fetch.d.ts +0 -3
  52. package/dist/types/tools/output-meta.d.ts +5 -37
  53. package/dist/types/tools/subagent.d.ts +15 -0
  54. package/dist/types/tools/todo-write.d.ts +3 -0
  55. package/dist/types/tools/tool-result.d.ts +0 -1
  56. package/package.json +10 -8
  57. package/scripts/build-sdk-package-smoke.ts +51 -0
  58. package/scripts/capture-notifications-settings-showcase.ts +1 -1
  59. package/src/async/job-manager.ts +430 -46
  60. package/src/cli/notify-cli.ts +204 -94
  61. package/src/commands/notify.ts +19 -8
  62. package/src/config/file-lock.ts +6 -0
  63. package/src/config/model-discovery-manager.ts +50 -8
  64. package/src/config/model-registry.ts +862 -75
  65. package/src/config/resolve-config-value.ts +10 -8
  66. package/src/config/settings-schema.ts +25 -15
  67. package/src/config/settings.ts +15 -15
  68. package/src/cursor.ts +13 -20
  69. package/src/defaults/gjc/skills/ultragoal/SKILL.md +2 -3
  70. package/src/eval/backend.ts +2 -2
  71. package/src/exec/bash-executor.ts +151 -425
  72. package/src/gjc-runtime/session-state-sidecar.ts +12 -2
  73. package/src/gjc-runtime/ultragoal-runtime.ts +3 -280
  74. package/src/gjc-runtime/workflow-manifest.generated.json +1 -40
  75. package/src/gjc-runtime/workflow-manifest.ts +0 -12
  76. package/src/internal-urls/agent-protocol.ts +38 -98
  77. package/src/internal-urls/artifact-protocol.ts +17 -28
  78. package/src/internal-urls/docs-index.generated.ts +7 -7
  79. package/src/internal-urls/registry-helpers.ts +0 -62
  80. package/src/main.ts +43 -7
  81. package/src/modes/DESIGN.md +11 -11
  82. package/src/modes/acp/acp-agent.ts +0 -24
  83. package/src/modes/acp/acp-client-bridge.ts +11 -154
  84. package/src/modes/components/hook-selector.ts +155 -44
  85. package/src/modes/components/model-selector.ts +242 -49
  86. package/src/modes/components/notifications-settings-editor.ts +631 -85
  87. package/src/modes/controllers/extension-ui-controller.ts +114 -15
  88. package/src/modes/controllers/selector-controller.ts +464 -50
  89. package/src/prompts/tools/bash.md +2 -2
  90. package/src/sdk/acp/adapter.ts +9 -200
  91. package/src/sdk/broker/broker.ts +54 -10
  92. package/src/sdk/broker/lifecycle-ledger.ts +34 -1
  93. package/src/sdk/broker/lifecycle.ts +47 -50
  94. package/src/sdk/bus/chat-daemon-cli.ts +12 -5
  95. package/src/sdk/bus/chat-daemon-control.ts +35 -8
  96. package/src/sdk/bus/chat-daemon-runtime.ts +16 -2
  97. package/src/sdk/bus/config.ts +534 -286
  98. package/src/sdk/bus/discord-live-provider.ts +57 -2
  99. package/src/sdk/bus/discord-provider.ts +21 -0
  100. package/src/sdk/bus/index.ts +105 -359
  101. package/src/sdk/bus/notification-orchestration.ts +371 -68
  102. package/src/sdk/bus/notification-service.ts +431 -130
  103. package/src/sdk/bus/session-control.ts +119 -44
  104. package/src/sdk/bus/slack-live-provider.ts +78 -2
  105. package/src/sdk/bus/slack-provider.ts +24 -0
  106. package/src/sdk/bus/telegram-daemon-cli.ts +9 -2
  107. package/src/sdk/bus/telegram-daemon-contract.ts +9 -4
  108. package/src/sdk/bus/telegram-daemon-control.ts +3 -3
  109. package/src/sdk/bus/telegram-daemon.ts +23 -15
  110. package/src/sdk/client/discovery.ts +10 -4
  111. package/src/sdk/host/host.ts +9 -187
  112. package/src/sdk/host/query/handlers.ts +20 -1
  113. package/src/sdk/host/reverse-leases.ts +42 -249
  114. package/src/sdk/index.ts +1 -0
  115. package/src/sdk/protocol/operation-inventory.generated.json +18 -0
  116. package/src/sdk/protocol/operation-registry.ts +5 -2
  117. package/src/sdk/providers.ts +51 -0
  118. package/src/sdk/session-directory.ts +1 -0
  119. package/src/sdk/session.ts +10 -7
  120. package/src/session/agent-session.ts +59 -202
  121. package/src/session/artifacts.ts +74 -211
  122. package/src/session/client-bridge.ts +0 -15
  123. package/src/session/internal/managed-session-scope.ts +981 -450
  124. package/src/session/internal/managed-session-storage.ts +362 -124
  125. package/src/session/internal/native-publish-outcome.ts +3 -1
  126. package/src/session/internal/session-open-errors.ts +11 -0
  127. package/src/session/messages.ts +7 -32
  128. package/src/session/session-manager.ts +48 -15
  129. package/src/session/session-storage.ts +72 -5
  130. package/src/session/streaming-output.ts +40 -198
  131. package/src/slash-commands/builtin-registry.ts +82 -4
  132. package/src/task/index.ts +237 -65
  133. package/src/task/receipt.ts +2 -4
  134. package/src/task/render.ts +0 -30
  135. package/src/task/types.ts +10 -34
  136. package/src/tools/ask.ts +1 -1
  137. package/src/tools/bash.ts +239 -818
  138. package/src/tools/eval.ts +4 -99
  139. package/src/tools/fetch.ts +15 -77
  140. package/src/tools/find.ts +3 -7
  141. package/src/tools/output-meta.ts +114 -696
  142. package/src/tools/search.ts +4 -9
  143. package/src/tools/subagent.ts +97 -75
  144. package/src/tools/telegram-send.ts +4 -2
  145. package/src/tools/todo-write.ts +47 -0
  146. package/src/tools/tool-result.ts +0 -1
  147. package/dist/types/gjc-runtime/ultragoal-review-source.d.ts +0 -83
  148. package/dist/types/utils/artifact-id.d.ts +0 -2
  149. package/src/gjc-runtime/ultragoal-review-source.ts +0 -378
  150. package/src/utils/artifact-id.ts +0 -6
@@ -5,7 +5,7 @@ import * as path from "node:path";
5
5
  import type { AssistantMessage } from "@gajae-code/ai";
6
6
  import { normalizePathForComparison, postmortem } from "@gajae-code/utils";
7
7
  import { withFileLock } from "../config/file-lock";
8
- import { sessionRuntimeDir } from "./session-layout";
8
+ import { sessionRoot, sessionRuntimeDir } from "./session-layout";
9
9
  import {
10
10
  isValidOwnerIntent,
11
11
  lifecyclePaths,
@@ -1022,6 +1022,7 @@ export async function persistCoordinatorRuntimeStateFromPostmortem(
1022
1022
  const stateFile = runtimeStateFileForContext(context);
1023
1023
  if (!stateFile) return;
1024
1024
  const identity = normalizedIdentity(context);
1025
+ const ownerSessionRoot = sessionRoot(context.cwd, identity.sessionId);
1025
1026
  const ownerTerminalVerdict = context.ownerTerminal
1026
1027
  ? await observeOwnerTerminalPostmortem(reason, context.ownerTerminal, identity.sessionId)
1027
1028
  : null;
@@ -1091,7 +1092,16 @@ export async function persistCoordinatorRuntimeStateFromPostmortem(
1091
1092
  await writeStateFileSync(stateFile, payload);
1092
1093
  }),
1093
1094
  ),
1094
- );
1095
+ ).catch(error => {
1096
+ if ((error as NodeJS.ErrnoException).code === "ENOENT") {
1097
+ try {
1098
+ fsSync.lstatSync(ownerSessionRoot);
1099
+ } catch (rootError) {
1100
+ if ((rootError as NodeJS.ErrnoException).code === "ENOENT") return;
1101
+ }
1102
+ }
1103
+ throw error;
1104
+ });
1095
1105
  }
1096
1106
 
1097
1107
  export function registerCoordinatorRuntimeStateFinalizer(context: RuntimeStateContext): () => void {
@@ -77,17 +77,6 @@ export {
77
77
  validateRecoveryAdmission,
78
78
  validateRecoveryPath,
79
79
  } from "./ultragoal-owner-loss-recovery";
80
-
81
- import {
82
- captureReviewSourceSnapshot,
83
- createReviewSourceCohort,
84
- createReviewSourceDispatch,
85
- normalizeReviewSourceCohorts,
86
- type ReviewDeliveryDisposition,
87
- type ReviewSourceCohort,
88
- type ReviewSourceLane,
89
- } from "./ultragoal-review-source";
90
-
91
80
  export type UltragoalGjcGoalMode = "aggregate" | "per-story";
92
81
  export type UltragoalGoalStatus =
93
82
  | "pending"
@@ -138,8 +127,6 @@ export interface UltragoalPlan {
138
127
  goals: UltragoalGoal[];
139
128
  /** Authoritative repository identity for multi-repo fail-closed spawn (#2901). */
140
129
  repositoryBinding?: RepositoryBinding;
141
- reviewCohorts?: ReviewSourceCohort[];
142
-
143
130
  createdAt: string;
144
131
  updatedAt: string;
145
132
  [key: string]: unknown;
@@ -997,8 +984,6 @@ function normalizePlan(raw: unknown): UltragoalPlan {
997
984
  if (record.repositoryBinding !== undefined) {
998
985
  repositoryBinding = parseRepositoryBinding(record.repositoryBinding);
999
986
  }
1000
- const reviewCohorts = normalizeReviewSourceCohorts(record.reviewCohorts);
1001
-
1002
987
  return {
1003
988
  version: 1,
1004
989
  brief,
@@ -1009,7 +994,6 @@ function normalizePlan(raw: unknown): UltragoalPlan {
1009
994
  createdAt,
1010
995
  updatedAt,
1011
996
  ...(repositoryBinding ? { repositoryBinding } : {}),
1012
- reviewCohorts,
1013
997
  ...(typeof record.state_revision === "number" && Number.isFinite(record.state_revision)
1014
998
  ? { state_revision: record.state_revision }
1015
999
  : {}),
@@ -2530,12 +2514,7 @@ const COHORT_LANE_KEYS = ["cleaner", "architect", "qa"] as const;
2530
2514
  * generations are delta-only. Cohort state rides the existing `iteration` gate key so
2531
2515
  * no new top-level quality-gate key is introduced.
2532
2516
  */
2533
- async function validateReviewCohort(
2534
- cwd: string,
2535
- gate: JsonObject,
2536
- iteration: JsonObject,
2537
- plan?: UltragoalPlan,
2538
- ): Promise<void> {
2517
+ function validateReviewCohort(gate: JsonObject, iteration: JsonObject): void {
2539
2518
  const cohort = qualityGateObject(iteration.reviewCohort);
2540
2519
  if (!cohort) throw new Error("qualityGate iteration.reviewCohort is required at the review boundary");
2541
2520
  const generation = cohort.reviewGeneration;
@@ -2543,40 +2522,6 @@ async function validateReviewCohort(
2543
2522
  throw new Error("iteration.reviewCohort.reviewGeneration must be an integer >= 1");
2544
2523
  const sourceHash = nonEmptyString(cohort.sourceHash);
2545
2524
  if (!sourceHash) throw new Error("iteration.reviewCohort.sourceHash is required");
2546
- const cohortId = nonEmptyString(cohort.cohortId);
2547
- const lanesForAuthority = qualityGateObject(cohort.lanes);
2548
- const deliveryBearing = COHORT_LANE_KEYS.some(lane =>
2549
- nonEmptyString(qualityGateObject(lanesForAuthority?.[lane])?.deliveryId),
2550
- );
2551
- const authoritativeReview = Boolean(cohortId || deliveryBearing || plan?.reviewCohorts?.length);
2552
- if (authoritativeReview && !cohortId) {
2553
- throw new Error(
2554
- "iteration.reviewCohort.cohortId is required; reviewer-declared source hashes are not gate authority",
2555
- );
2556
- }
2557
- const authoritative = cohortId ? plan?.reviewCohorts?.find(record => record.cohortId === cohortId) : undefined;
2558
- if (cohortId && !authoritative) {
2559
- throw new Error("iteration.reviewCohort.cohortId must resolve to a runtime-owned persisted review cohort");
2560
- }
2561
- if (authoritative?.status !== undefined && authoritative.status !== "active") {
2562
- throw new Error(
2563
- "iteration.reviewCohort references a superseded review cohort; rerun reviews on the active source snapshot",
2564
- );
2565
- }
2566
- if (authoritative && (authoritative.generation !== generation || authoritative.snapshotId !== sourceHash)) {
2567
- throw new Error(
2568
- "iteration.reviewCohort generation/sourceHash must match the runtime-owned persisted review cohort",
2569
- );
2570
- }
2571
- if (authoritative && plan?.repositoryBinding) {
2572
- const current = await captureReviewSourceSnapshot(cwd, plan.repositoryBinding);
2573
- if (current.snapshotId !== authoritative.snapshotId) {
2574
- throw new Error(
2575
- "iteration.reviewCohort source advanced after review delivery; rerun the cohort on the current source snapshot",
2576
- );
2577
- }
2578
- }
2579
-
2580
2525
  if (cohort.joined !== true)
2581
2526
  throw new Error("iteration.reviewCohort.joined must be true: all lane findings must join before checkpoint");
2582
2527
  const lanes = qualityGateObject(cohort.lanes);
@@ -2589,22 +2534,6 @@ async function validateReviewCohort(
2589
2534
  throw new Error(`iteration.reviewCohort.lanes.${lane} must be one lane per generation, not a list`);
2590
2535
  const record = qualityGateObject(lanes[lane]);
2591
2536
  if (!record) throw new Error(`iteration.reviewCohort.lanes.${lane} is required`);
2592
- if (authoritative) {
2593
- const deliveryId = nonEmptyString(record.deliveryId);
2594
- if (!deliveryId) throw new Error(`iteration.reviewCohort.lanes.${lane}.deliveryId is required`);
2595
- const delivery = authoritative.deliveries.find(item => item.deliveryId === deliveryId && item.lane === lane);
2596
- if (!delivery) {
2597
- throw new Error(
2598
- `iteration.reviewCohort.lanes.${lane}.deliveryId must resolve to its runtime-owned lane delivery`,
2599
- );
2600
- }
2601
- if (delivery.disposition !== "current" || delivery.snapshotId !== sourceHash) {
2602
- throw new Error(
2603
- `iteration.reviewCohort.lanes.${lane} is ${delivery.disposition}; stale or invalid review delivery cannot satisfy the current gate. Rerun the ${lane} lane on cohort ${cohortId}`,
2604
- );
2605
- }
2606
- }
2607
-
2608
2537
  const laneHash = nonEmptyString(record.sourceHash);
2609
2538
  if (!laneHash) throw new Error(`iteration.reviewCohort.lanes.${lane}.sourceHash is required`);
2610
2539
  if (laneHash !== sourceHash)
@@ -2642,19 +2571,6 @@ async function validateReviewCohort(
2642
2571
  // per-lane or per-generation vote.
2643
2572
  const critic = qualityGateObject(gate.criticReview);
2644
2573
  if (critic) {
2645
- if (authoritative) {
2646
- const criticDeliveryId = nonEmptyString(critic.deliveryId);
2647
- if (!criticDeliveryId) throw new Error("criticReview.deliveryId is required for the terminal review gate");
2648
- const criticDelivery = authoritative.deliveries.find(
2649
- item => item.deliveryId === criticDeliveryId && item.lane === "critic",
2650
- );
2651
- if (criticDelivery?.disposition !== "current" || criticDelivery.snapshotId !== sourceHash) {
2652
- throw new Error(
2653
- "criticReview.deliveryId must resolve to a current terminal critic delivery on the joined cohort",
2654
- );
2655
- }
2656
- }
2657
-
2658
2574
  const criticHash = nonEmptyString(critic.sourceHash);
2659
2575
  if (criticHash && criticHash !== sourceHash)
2660
2576
  throw new Error(
@@ -2852,9 +2768,7 @@ async function validateCompletionQualityGate(
2852
2768
  found.check("iteration.blockers", "non_empty_blockers", () =>
2853
2769
  requireEmptyBlockers(iteration.blockers, "iteration.blockers"),
2854
2770
  );
2855
- await found.checkAsync("iteration.reviewCohort", "review_cohort_invalid", () =>
2856
- validateReviewCohort(cwd, gate, iteration, options.plan),
2857
- );
2771
+ found.check("iteration.reviewCohort", "review_cohort_invalid", () => validateReviewCohort(gate, iteration));
2858
2772
  if (batchMode && options.goal && options.plan && options.ledger) {
2859
2773
  found.check("validationBatchClose", "batch_close_invalid", () =>
2860
2774
  validateBatchCloseQualityGate(gate, options.plan!, batchMode, options.ledger!, options.changeSet),
@@ -4003,150 +3917,9 @@ async function annotateUltragoalLedger(input: {
4003
3917
  rationale: input.rationale,
4004
3918
  });
4005
3919
  await appendLedger(input.cwd, { event: "steering_accepted", kind, evidence, rationale });
4006
-
4007
3920
  return { plan: input.plan };
4008
3921
  }
4009
3922
 
4010
- async function mutateReviewCohorts<T>(cwd: string, mutate: (plan: UltragoalPlan) => T): Promise<T> {
4011
- for (let attempt = 0; attempt < 5; attempt++) {
4012
- const plan = await readUltragoalPlan(cwd);
4013
- if (!plan) throw new Error("No ultragoal plan found");
4014
- const result = mutate(plan);
4015
- plan.updatedAt = new Date().toISOString();
4016
- try {
4017
- await writePlan(cwd, plan);
4018
- return result;
4019
- } catch (error) {
4020
- if (!(error instanceof Error) || !error.message.includes("revision")) throw error;
4021
- }
4022
- }
4023
- throw new Error("review cohort state changed concurrently; rerun the operation");
4024
- }
4025
-
4026
- export async function validateUltragoalReviewDispatch(input: {
4027
- cwd: string;
4028
- dispatchId: string;
4029
- cohortId: string;
4030
- taskId: string;
4031
- lane: ReviewSourceLane;
4032
- snapshotId: string;
4033
- generation: number;
4034
- repositoryBindingDigest: string;
4035
- stateRevision: number;
4036
- rerunCommand: string;
4037
- taskSourceTaskId: string;
4038
- createdAt: string;
4039
- }): Promise<void> {
4040
- const plan = await readUltragoalPlan(input.cwd);
4041
- const cohort = plan?.reviewCohorts?.find(item => item.cohortId === input.cohortId && item.status === "active");
4042
- const dispatch = cohort?.dispatches.find(item => item.dispatchId === input.dispatchId);
4043
- if (
4044
- !dispatch ||
4045
- dispatch.taskId !== input.taskId ||
4046
- dispatch.lane !== input.lane ||
4047
- dispatch.snapshotId !== input.snapshotId ||
4048
- dispatch.generation !== input.generation ||
4049
- dispatch.repositoryBindingDigest !== input.repositoryBindingDigest ||
4050
- dispatch.stateRevision !== input.stateRevision ||
4051
- dispatch.rerunCommand !== input.rerunCommand ||
4052
- dispatch.taskId !== input.taskSourceTaskId ||
4053
- dispatch.createdAt !== input.createdAt
4054
- ) {
4055
- throw new Error("reviewSource must resolve to an active runtime-owned dispatch before task launch");
4056
- }
4057
- }
4058
-
4059
- export async function freezeUltragoalReviewCohort(input: {
4060
- cwd: string;
4061
- workflow?: "ultragoal" | "ralplan";
4062
- }): Promise<ReviewSourceCohort> {
4063
- const plan = await readUltragoalPlan(input.cwd);
4064
- if (!plan?.repositoryBinding) throw new Error("review cohort freeze requires an authoritative repository binding");
4065
- const captured = await captureReviewSourceSnapshot(input.cwd, plan.repositoryBinding);
4066
- const prior = plan.reviewCohorts?.find(cohort => cohort.status === "active");
4067
- if (
4068
- prior?.snapshotId === captured.snapshotId &&
4069
- prior.repositoryBindingDigest === captured.repositoryBindingDigest
4070
- ) {
4071
- return prior;
4072
- }
4073
- const cohort = createReviewSourceCohort({
4074
- workflow: input.workflow ?? "ultragoal",
4075
- generation: (prior?.generation ?? 0) + 1,
4076
- snapshotId: captured.snapshotId,
4077
- repositoryBindingDigest: captured.repositoryBindingDigest,
4078
- stateRevision: persistedStateRevision(plan),
4079
- });
4080
- if (prior) {
4081
- prior.status = "superseded";
4082
- prior.supersededBy = cohort.cohortId;
4083
- }
4084
- plan.reviewCohorts = [...(plan.reviewCohorts ?? []), cohort];
4085
- plan.updatedAt = new Date().toISOString();
4086
- await writePlan(input.cwd, plan);
4087
- return cohort;
4088
- }
4089
-
4090
- export async function dispatchUltragoalReviewLane(input: {
4091
- cwd: string;
4092
- cohortId: string;
4093
- taskId: string;
4094
- lane: ReviewSourceLane;
4095
- rerunCommand: string;
4096
- }): Promise<ReturnType<typeof createReviewSourceDispatch>> {
4097
- return mutateReviewCohorts(input.cwd, plan => {
4098
- const cohort = plan.reviewCohorts?.find(item => item.cohortId === input.cohortId);
4099
- if (!cohort) throw new Error(`Unknown review cohort ${input.cohortId}`);
4100
- const dispatch = createReviewSourceDispatch({
4101
- cohort,
4102
- taskId: input.taskId,
4103
- lane: input.lane,
4104
- rerunCommand: input.rerunCommand,
4105
- });
4106
- cohort.dispatches.push(dispatch);
4107
- return dispatch;
4108
- });
4109
- }
4110
-
4111
- export async function classifyUltragoalReviewDelivery(input: {
4112
- cwd: string;
4113
- cohortId: string;
4114
- dispatchId: string;
4115
- observedDisposition: ReviewDeliveryDisposition;
4116
- }): Promise<{ disposition: ReviewDeliveryDisposition; deliveryId: string }> {
4117
- return mutateReviewCohorts(input.cwd, plan => {
4118
- const cohort = plan.reviewCohorts?.find(item => item.cohortId === input.cohortId);
4119
- const active = plan.reviewCohorts?.find(item => item.status === "active");
4120
- if (!cohort) throw new Error(`Unknown review cohort ${input.cohortId}`);
4121
- const dispatch = cohort.dispatches.find(item => item.dispatchId === input.dispatchId);
4122
- if (!dispatch) throw new Error(`Unknown review dispatch ${input.dispatchId}`);
4123
- const disposition =
4124
- input.observedDisposition === "invalid_provenance"
4125
- ? "invalid_provenance"
4126
- : active?.cohortId === cohort.cohortId && cohort.status === "active"
4127
- ? input.observedDisposition
4128
- : "stale_review_delivery";
4129
- const existing = cohort.deliveries.find(item => item.dispatchId === dispatch.dispatchId);
4130
- if (existing) {
4131
- if (existing.disposition !== disposition) throw new Error("conflicting_review_delivery");
4132
- return { disposition, deliveryId: existing.deliveryId };
4133
- }
4134
- const deliveryId = crypto.randomUUID();
4135
- cohort.deliveries.push({
4136
- deliveryId,
4137
- cohortId: cohort.cohortId,
4138
- dispatchId: dispatch.dispatchId,
4139
- taskId: dispatch.taskId,
4140
- lane: dispatch.lane,
4141
- snapshotId: dispatch.snapshotId,
4142
- disposition,
4143
- receivedAt: new Date().toISOString(),
4144
- rerunCommand: dispatch.rerunCommand,
4145
- });
4146
- return { disposition, deliveryId };
4147
- });
4148
- }
4149
-
4150
3923
  async function markBlockedUltragoalSuperseded(input: {
4151
3924
  cwd: string;
4152
3925
  plan: UltragoalPlan;
@@ -4948,21 +4721,6 @@ function renderUltragoalHelp(args: readonly string[]): string | null {
4948
4721
  ].join("\n");
4949
4722
  }
4950
4723
 
4951
- if (subject === "review-source") {
4952
- return [
4953
- "Run native GJC Ultragoal workflow commands",
4954
- "",
4955
- "USAGE",
4956
- " $ gjc ultragoal review-source freeze [--json]",
4957
- " $ gjc ultragoal review-source dispatch --cohort-id <id> --task-id <id> --lane <cleaner|architect|qa|critic> --rerun-command <command> [--json]",
4958
- "",
4959
- "DESCRIPTION",
4960
- " Freeze derives and persists a runtime-owned source snapshot before review dispatch.",
4961
- " Dispatch returns the leader-issued reviewSource object required by source-aware task lanes.",
4962
- "",
4963
- ].join("\n");
4964
- }
4965
-
4966
4724
  if (subject === "quality-gate") {
4967
4725
  return [
4968
4726
  "Run native GJC Ultragoal workflow commands",
@@ -5004,11 +4762,9 @@ function renderUltragoalHelp(args: readonly string[]): string | null {
5004
4762
  " record-critic-gate-override",
5005
4763
  " quality-gate init",
5006
4764
  " quality-gate validate",
5007
- " review-source freeze",
5008
- " review-source dispatch",
5009
4765
 
5010
4766
  "",
5011
- "Run `gjc ultragoal checkpoint --help`, `gjc ultragoal review --help`, `gjc ultragoal review-source --help`, `gjc ultragoal classify-blocker --help`, `gjc ultragoal record-critic-verdict --help`, `gjc ultragoal record-critic-gate-override --help`, or `gjc ultragoal quality-gate --help` for command-specific requirements.",
4767
+ "Run `gjc ultragoal checkpoint --help`, `gjc ultragoal review --help`, `gjc ultragoal classify-blocker --help`, `gjc ultragoal record-critic-verdict --help`, or `gjc ultragoal record-critic-gate-override --help`, or `gjc ultragoal quality-gate --help` for command-specific requirements.",
5012
4768
  "",
5013
4769
  ].join("\n");
5014
4770
  }
@@ -5435,39 +5191,6 @@ async function dispatchUltragoalCommand(args: string[], cwd: string): Promise<Ul
5435
5191
  .join("\n")}\n`,
5436
5192
  };
5437
5193
  }
5438
- case "review-source": {
5439
- const positional = args.filter(arg => !arg.startsWith("-"));
5440
- const subcommand = positional[1];
5441
- if (subcommand === "freeze") {
5442
- const cohort = await freezeUltragoalReviewCohort({ cwd });
5443
- return { status: 0, stdout: `${JSON.stringify(cohort, null, 2)}\n` };
5444
- }
5445
- if (subcommand === "dispatch") {
5446
- const cohortId = flagValue(args, "--cohort-id") ?? "";
5447
- const taskId = flagValue(args, "--task-id") ?? "";
5448
- const lane = flagValue(args, "--lane") as ReviewSourceLane | undefined;
5449
- const rerunCommand = flagValue(args, "--rerun-command") ?? "";
5450
- if (
5451
- !cohortId ||
5452
- !taskId ||
5453
- !lane ||
5454
- !["cleaner", "architect", "qa", "critic"].includes(lane) ||
5455
- !rerunCommand
5456
- ) {
5457
- return {
5458
- status: 1,
5459
- stderr:
5460
- "review-source dispatch requires --cohort-id, --task-id, --lane cleaner|architect|qa|critic, and --rerun-command\n",
5461
- };
5462
- }
5463
- const dispatch = await dispatchUltragoalReviewLane({ cwd, cohortId, taskId, lane, rerunCommand });
5464
- return { status: 0, stdout: `${JSON.stringify(dispatch, null, 2)}\n` };
5465
- }
5466
- return {
5467
- status: 1,
5468
- stderr: `Unknown gjc ultragoal review-source subcommand: ${subcommand ?? "(missing)"}\n`,
5469
- };
5470
- }
5471
5194
  case "review": {
5472
5195
  const result = await runUltragoalReview(cwd, args);
5473
5196
  return {
@@ -1745,40 +1745,6 @@
1745
1745
  "name": "goal-id",
1746
1746
  "type": "string"
1747
1747
  },
1748
- {
1749
- "appliesToVerbs": [
1750
- "review-source"
1751
- ],
1752
- "name": "cohort-id",
1753
- "type": "string"
1754
- },
1755
- {
1756
- "appliesToVerbs": [
1757
- "review-source"
1758
- ],
1759
- "name": "task-id",
1760
- "type": "string"
1761
- },
1762
- {
1763
- "appliesToVerbs": [
1764
- "review-source"
1765
- ],
1766
- "enumValues": [
1767
- "cleaner",
1768
- "architect",
1769
- "qa",
1770
- "critic"
1771
- ],
1772
- "name": "lane",
1773
- "type": "enum"
1774
- },
1775
- {
1776
- "appliesToVerbs": [
1777
- "review-source"
1778
- ],
1779
- "name": "rerun-command",
1780
- "type": "string"
1781
- },
1782
1748
  {
1783
1749
  "appliesToVerbs": [
1784
1750
  "steer"
@@ -1907,8 +1873,7 @@
1907
1873
  "steer",
1908
1874
  "classify-blocker",
1909
1875
  "record-critic-verdict",
1910
- "record-critic-gate-override",
1911
- "review-source"
1876
+ "record-critic-gate-override"
1912
1877
  ],
1913
1878
  "name": "json",
1914
1879
  "type": "boolean"
@@ -2005,10 +1970,6 @@
2005
1970
  "name": "quality-gate",
2006
1971
  "surface": "command-positional"
2007
1972
  },
2008
- {
2009
- "name": "review-source",
2010
- "surface": "command-positional"
2011
- },
2012
1973
  {
2013
1974
  "name": "graph",
2014
1975
  "planned": true,
@@ -306,7 +306,6 @@ export const WORKFLOW_MANIFEST: Record<CanonicalGjcWorkflowSkill, SkillManifest>
306
306
  "record-critic-verdict",
307
307
  "record-critic-gate-override",
308
308
  "quality-gate",
309
- "review-source",
310
309
  ]),
311
310
  ...plannedVerbs(PLANNED_ADMIN_VERBS),
312
311
  ],
@@ -363,16 +362,6 @@ export const WORKFLOW_MANIFEST: Record<CanonicalGjcWorkflowSkill, SkillManifest>
363
362
  { name: "classification-event-id", type: "string", appliesToVerbs: ["record-critic-verdict"] },
364
363
  { name: "quality-gate-json", type: "string", appliesToVerbs: ["checkpoint", "quality-gate"] },
365
364
  { name: "goal-id", type: "string", appliesToVerbs: ["quality-gate"] },
366
- { name: "cohort-id", type: "string", appliesToVerbs: ["review-source"] },
367
- { name: "task-id", type: "string", appliesToVerbs: ["review-source"] },
368
- {
369
- name: "lane",
370
- type: "enum",
371
- enumValues: ["cleaner", "architect", "qa", "critic"],
372
- appliesToVerbs: ["review-source"],
373
- },
374
- { name: "rerun-command", type: "string", appliesToVerbs: ["review-source"] },
375
-
376
365
  { name: "goal-id", type: "string", appliesToVerbs: ["steer"] },
377
366
  { name: "goal-id", type: "string", appliesToVerbs: ["classify-blocker"] },
378
367
  {
@@ -424,7 +413,6 @@ export const WORKFLOW_MANIFEST: Record<CanonicalGjcWorkflowSkill, SkillManifest>
424
413
  "classify-blocker",
425
414
  "record-critic-verdict",
426
415
  "record-critic-gate-override",
427
- "review-source",
428
416
  ],
429
417
  },
430
418
  { name: "directive-json", type: "string", appliesToVerbs: ["steer"], planned: true },