@gajae-code/coding-agent 0.4.5 → 0.5.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.
- package/CHANGELOG.md +62 -0
- package/dist/types/async/job-manager.d.ts +26 -0
- package/dist/types/cli/args.d.ts +1 -0
- package/dist/types/cli/list-models.d.ts +6 -0
- package/dist/types/commands/gc.d.ts +26 -0
- package/dist/types/commands/harness.d.ts +3 -0
- package/dist/types/config/file-lock-gc.d.ts +5 -0
- package/dist/types/config/file-lock.d.ts +7 -0
- package/dist/types/config/model-profile-activation.d.ts +11 -2
- package/dist/types/config/model-profiles.d.ts +7 -0
- package/dist/types/config/model-registry.d.ts +3 -0
- package/dist/types/config/model-resolver.d.ts +2 -0
- package/dist/types/config/models-config-schema.d.ts +30 -0
- package/dist/types/config/settings-schema.d.ts +4 -3
- package/dist/types/coordinator/contract.d.ts +1 -1
- package/dist/types/defaults/gjc/extensions/grok-build/index.d.ts +1 -0
- package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/index.d.ts +1 -0
- package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/models/catalog.d.ts +25 -0
- package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/payload/sanitize.d.ts +27 -0
- package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/provider/billing.d.ts +8 -0
- package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/provider/register.d.ts +5 -0
- package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/provider/stream.d.ts +10 -0
- package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/provider/usage.d.ts +2 -0
- package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/shared/base-url.d.ts +2 -0
- package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/shared/errors.d.ts +38 -0
- package/dist/types/defaults/gjc-grok-cli.d.ts +5 -0
- package/dist/types/extensibility/extensions/index.d.ts +1 -0
- package/dist/types/extensibility/extensions/prefix-command-bridge.d.ts +35 -0
- package/dist/types/gjc-runtime/deep-interview-recorder.d.ts +103 -0
- package/dist/types/gjc-runtime/deep-interview-runtime.d.ts +2 -0
- package/dist/types/gjc-runtime/deep-interview-state.d.ts +112 -0
- package/dist/types/gjc-runtime/gc-render.d.ts +6 -0
- package/dist/types/gjc-runtime/gc-runtime.d.ts +134 -0
- package/dist/types/gjc-runtime/ledger-event-renderer.d.ts +68 -0
- package/dist/types/gjc-runtime/team-gc.d.ts +7 -0
- package/dist/types/gjc-runtime/team-runtime.d.ts +5 -1
- package/dist/types/gjc-runtime/tmux-common.d.ts +14 -0
- package/dist/types/gjc-runtime/tmux-gc.d.ts +7 -0
- package/dist/types/gjc-runtime/tmux-sessions.d.ts +13 -0
- package/dist/types/harness-control-plane/gc-adapter.d.ts +3 -0
- package/dist/types/harness-control-plane/owner.d.ts +8 -1
- package/dist/types/harness-control-plane/receipt-spool.d.ts +19 -0
- package/dist/types/harness-control-plane/state-machine.d.ts +6 -1
- package/dist/types/harness-control-plane/storage.d.ts +20 -0
- package/dist/types/harness-control-plane/types.d.ts +4 -0
- package/dist/types/hindsight/mental-models.d.ts +5 -5
- package/dist/types/modes/components/hook-selector.d.ts +7 -1
- package/dist/types/modes/components/model-selector.d.ts +1 -12
- package/dist/types/modes/controllers/command-controller.d.ts +1 -0
- package/dist/types/modes/rpc/rpc-client.d.ts +2 -2
- package/dist/types/modes/rpc/rpc-mode.d.ts +16 -1
- package/dist/types/modes/rpc/rpc-types.d.ts +4 -1
- package/dist/types/modes/shared/agent-wire/deep-interview-gate.d.ts +13 -0
- package/dist/types/modes/shared/agent-wire/session-registry.d.ts +25 -0
- package/dist/types/modes/shared/agent-wire/unattended-action-policy.d.ts +2 -0
- package/dist/types/sdk.d.ts +5 -0
- package/dist/types/session/agent-session.d.ts +3 -1
- package/dist/types/session/blob-store.d.ts +59 -4
- package/dist/types/session/session-manager.d.ts +24 -6
- package/dist/types/session/streaming-output.d.ts +3 -2
- package/dist/types/session/tool-choice-queue.d.ts +6 -0
- package/dist/types/skill-state/workflow-hud.d.ts +14 -0
- package/dist/types/task/receipt.d.ts +1 -0
- package/dist/types/task/types.d.ts +7 -0
- package/dist/types/thinking-metadata.d.ts +16 -0
- package/dist/types/thinking.d.ts +3 -12
- package/dist/types/tools/ask.d.ts +15 -1
- package/dist/types/tools/index.d.ts +2 -0
- package/dist/types/tools/resolve.d.ts +0 -10
- package/dist/types/tools/subagent.d.ts +6 -0
- package/dist/types/utils/tool-choice.d.ts +14 -1
- package/package.json +7 -7
- package/src/async/job-manager.ts +52 -0
- package/src/cli/args.ts +3 -0
- package/src/cli/auth-broker-cli.ts +1 -0
- package/src/cli/list-models.ts +13 -1
- package/src/cli.ts +9 -4
- package/src/commands/gc.ts +22 -0
- package/src/commands/harness.ts +43 -5
- package/src/commands/launch.ts +2 -2
- package/src/commands/session.ts +3 -1
- package/src/config/file-lock-gc.ts +181 -0
- package/src/config/file-lock.ts +14 -0
- package/src/config/model-profile-activation.ts +15 -3
- package/src/config/model-profiles.ts +264 -56
- package/src/config/model-resolver.ts +9 -6
- package/src/config/models-config-schema.ts +1 -0
- package/src/config/settings-schema.ts +6 -3
- package/src/coordinator/contract.ts +1 -0
- package/src/coordinator-mcp/server.ts +513 -26
- package/src/cursor.ts +16 -2
- package/src/defaults/gjc/agent.models.grok-cli.yml +36 -0
- package/src/defaults/gjc/extensions/grok-build/index.ts +1 -0
- package/src/defaults/gjc/extensions/grok-build/package.json +7 -0
- package/src/defaults/gjc/extensions/grok-cli-vendor/biome.json +39 -0
- package/src/defaults/gjc/extensions/grok-cli-vendor/package.json +8 -0
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/index.ts +1 -0
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/models/catalog.ts +155 -0
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/payload/sanitize.ts +361 -0
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/provider/billing.ts +57 -0
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/provider/register.ts +99 -0
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/provider/stream.ts +50 -0
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/provider/usage.ts +56 -0
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/shared/base-url.ts +36 -0
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/shared/errors.ts +44 -0
- package/src/defaults/gjc/skills/deep-interview/SKILL.md +131 -113
- package/src/defaults/gjc/skills/deep-interview/lateral-review-panel.md +49 -0
- package/src/defaults/gjc/skills/team/SKILL.md +3 -2
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +8 -2
- package/src/defaults/gjc-defaults.ts +7 -0
- package/src/defaults/gjc-grok-cli.ts +22 -0
- package/src/export/html/index.ts +13 -9
- package/src/extensibility/extensions/index.ts +1 -0
- package/src/extensibility/extensions/prefix-command-bridge.ts +128 -0
- package/src/gjc-runtime/deep-interview-recorder.ts +417 -0
- package/src/gjc-runtime/deep-interview-runtime.ts +18 -26
- package/src/gjc-runtime/deep-interview-state.ts +324 -0
- package/src/gjc-runtime/gc-render.ts +70 -0
- package/src/gjc-runtime/gc-runtime.ts +403 -0
- package/src/gjc-runtime/ledger-event-renderer.ts +164 -0
- package/src/gjc-runtime/ralplan-runtime.ts +58 -7
- package/src/gjc-runtime/state-renderer.ts +12 -3
- package/src/gjc-runtime/state-runtime.ts +46 -29
- package/src/gjc-runtime/team-gc.ts +49 -0
- package/src/gjc-runtime/team-runtime.ts +211 -8
- package/src/gjc-runtime/tmux-common.ts +29 -0
- package/src/gjc-runtime/tmux-gc.ts +176 -0
- package/src/gjc-runtime/tmux-sessions.ts +68 -12
- package/src/gjc-runtime/ultragoal-runtime.ts +517 -41
- package/src/gjc-runtime/workflow-manifest.generated.json +27 -1
- package/src/gjc-runtime/workflow-manifest.ts +16 -1
- package/src/harness-control-plane/gc-adapter.ts +184 -0
- package/src/harness-control-plane/owner.ts +89 -27
- package/src/harness-control-plane/receipt-spool.ts +128 -0
- package/src/harness-control-plane/state-machine.ts +27 -6
- package/src/harness-control-plane/storage.ts +93 -0
- package/src/harness-control-plane/types.ts +4 -0
- package/src/hindsight/mental-models.ts +17 -16
- package/src/internal-urls/docs-index.generated.ts +14 -8
- package/src/main.ts +7 -2
- package/src/modes/components/assistant-message.ts +26 -14
- package/src/modes/components/diff.ts +97 -0
- package/src/modes/components/hook-selector.ts +19 -0
- package/src/modes/components/model-selector.ts +370 -181
- package/src/modes/components/status-line/segments.ts +1 -1
- package/src/modes/components/tool-execution.ts +30 -13
- package/src/modes/controllers/command-controller.ts +25 -6
- package/src/modes/controllers/extension-ui-controller.ts +3 -0
- package/src/modes/controllers/selector-controller.ts +34 -42
- package/src/modes/rpc/rpc-client.ts +3 -2
- package/src/modes/rpc/rpc-mode.ts +187 -39
- package/src/modes/rpc/rpc-types.ts +5 -2
- package/src/modes/shared/agent-wire/command-dispatch.ts +279 -257
- package/src/modes/shared/agent-wire/command-validation.ts +11 -0
- package/src/modes/shared/agent-wire/deep-interview-gate.ts +30 -1
- package/src/modes/shared/agent-wire/session-registry.ts +109 -0
- package/src/modes/shared/agent-wire/unattended-action-policy.ts +24 -0
- package/src/modes/shared/agent-wire/unattended-run-controller.ts +23 -3
- package/src/modes/shared/agent-wire/unattended-session.ts +16 -1
- package/src/sdk.ts +46 -5
- package/src/secrets/obfuscator.ts +102 -27
- package/src/session/agent-session.ts +179 -25
- package/src/session/blob-store.ts +148 -6
- package/src/session/session-manager.ts +311 -60
- package/src/session/streaming-output.ts +185 -122
- package/src/session/tool-choice-queue.ts +23 -0
- package/src/setup/hermes/templates/operator-instructions.v1.md +7 -1
- package/src/skill-state/workflow-hud.ts +106 -10
- package/src/slash-commands/builtin-registry.ts +3 -2
- package/src/task/executor.ts +78 -6
- package/src/task/receipt.ts +5 -0
- package/src/task/render.ts +21 -1
- package/src/task/types.ts +8 -0
- package/src/thinking-metadata.ts +51 -0
- package/src/thinking.ts +26 -46
- package/src/tools/ask.ts +56 -1
- package/src/tools/bash.ts +1 -1
- package/src/tools/index.ts +2 -0
- package/src/tools/job.ts +3 -2
- package/src/tools/monitor.ts +36 -1
- package/src/tools/resolve.ts +93 -18
- package/src/tools/subagent-render.ts +9 -0
- package/src/tools/subagent.ts +26 -2
- package/src/utils/edit-mode.ts +1 -1
- package/src/utils/tool-choice.ts +45 -16
|
@@ -4,6 +4,7 @@ import type { WorkflowHudSummary } from "../skill-state/active-state";
|
|
|
4
4
|
import { buildUltragoalHudSummary as buildWorkflowUltragoalHudSummary } from "../skill-state/workflow-hud";
|
|
5
5
|
import { renderCliWriteReceipt } from "./cli-write-receipt";
|
|
6
6
|
import { DEFAULT_ULTRAGOAL_OBJECTIVE } from "./goal-mode-request";
|
|
7
|
+
import { latestUltragoalLedgerEventFromText } from "./ledger-event-renderer";
|
|
7
8
|
import { renderUltragoalStatusMarkdown } from "./state-renderer";
|
|
8
9
|
import { reconcileWorkflowSkillState } from "./state-runtime";
|
|
9
10
|
import { appendJsonl, writeArtifact, writeJsonAtomic } from "./state-writer";
|
|
@@ -116,6 +117,27 @@ const GJC_GOAL_SNAPSHOT_MAX_AGE_MILLISECONDS = 10 * 60 * 1000;
|
|
|
116
117
|
const GJC_GOAL_SNAPSHOT_MAX_FUTURE_SKEW_MILLISECONDS = 60 * 1000;
|
|
117
118
|
|
|
118
119
|
const SCHEDULABLE_STATUSES = new Set<UltragoalGoalStatus>(["pending", "active", "failed"]);
|
|
120
|
+
const NATIVE_STEERING_KINDS = [
|
|
121
|
+
"add_subgoal",
|
|
122
|
+
"split_subgoal",
|
|
123
|
+
"reorder_pending",
|
|
124
|
+
"revise_pending_wording",
|
|
125
|
+
"annotate_ledger",
|
|
126
|
+
"mark_blocked_superseded",
|
|
127
|
+
] as const;
|
|
128
|
+
type UltragoalSteeringKind = (typeof NATIVE_STEERING_KINDS)[number];
|
|
129
|
+
const NATIVE_STEERING_KIND_SET = new Set<string>(NATIVE_STEERING_KINDS);
|
|
130
|
+
|
|
131
|
+
interface ReplacementSpec {
|
|
132
|
+
title: string;
|
|
133
|
+
objective: string;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
interface SteeringCommandResult {
|
|
137
|
+
kind: UltragoalSteeringKind;
|
|
138
|
+
message: string;
|
|
139
|
+
receipt: JsonObject;
|
|
140
|
+
}
|
|
119
141
|
|
|
120
142
|
function stableStructuredValue(value: unknown): unknown {
|
|
121
143
|
if (Array.isArray(value)) return value.map(item => stableStructuredValue(item));
|
|
@@ -1263,44 +1285,372 @@ export async function checkpointAndContinueUltragoalGoal(input: {
|
|
|
1263
1285
|
};
|
|
1264
1286
|
}
|
|
1265
1287
|
|
|
1266
|
-
|
|
1288
|
+
function nextUltragoalGoalId(plan: UltragoalPlan, offset = 1): string {
|
|
1289
|
+
return `G${String(plan.goals.length + offset).padStart(3, "0")}`;
|
|
1290
|
+
}
|
|
1291
|
+
|
|
1292
|
+
function requireSteeringText(value: string, label: string, kind: UltragoalSteeringKind): string {
|
|
1293
|
+
const trimmed = value.trim();
|
|
1294
|
+
if (!trimmed) throw new Error(`steer --${label} is required for ${kind}`);
|
|
1295
|
+
return trimmed;
|
|
1296
|
+
}
|
|
1297
|
+
|
|
1298
|
+
function requireSteeringEvidence(input: { kind: UltragoalSteeringKind; evidence: string; rationale: string }): {
|
|
1299
|
+
evidence: string;
|
|
1300
|
+
rationale: string;
|
|
1301
|
+
} {
|
|
1302
|
+
return {
|
|
1303
|
+
evidence: requireSteeringText(input.evidence, "evidence", input.kind),
|
|
1304
|
+
rationale: requireSteeringText(input.rationale, "rationale", input.kind),
|
|
1305
|
+
};
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1308
|
+
function findGoalOrThrow(plan: UltragoalPlan, goalId: string, kind: UltragoalSteeringKind): UltragoalGoal {
|
|
1309
|
+
const id = goalId.trim();
|
|
1310
|
+
if (!id) throw new Error(`steer --goal-id is required for ${kind}`);
|
|
1311
|
+
const goal = plan.goals.find(item => item.id === id);
|
|
1312
|
+
if (!goal) throw new Error(`No ultragoal goal found for ${id}.`);
|
|
1313
|
+
return goal;
|
|
1314
|
+
}
|
|
1315
|
+
|
|
1316
|
+
function requireGoalStatus(
|
|
1317
|
+
goal: UltragoalGoal,
|
|
1318
|
+
allowed: readonly UltragoalGoalStatus[],
|
|
1319
|
+
kind: UltragoalSteeringKind,
|
|
1320
|
+
): void {
|
|
1321
|
+
if (!allowed.includes(goal.status)) {
|
|
1322
|
+
throw new Error(`steer ${kind} requires goal ${goal.id} status ${allowed.join(" or ")}; found ${goal.status}`);
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1326
|
+
function parseJsonFlag(value: string, label: string, kind: UltragoalSteeringKind): unknown {
|
|
1327
|
+
const trimmed = requireSteeringText(value, label, kind);
|
|
1328
|
+
try {
|
|
1329
|
+
return JSON.parse(trimmed) as unknown;
|
|
1330
|
+
} catch (error) {
|
|
1331
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1332
|
+
throw new Error(`steer --${label} must be valid JSON for ${kind}: ${message}`);
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
|
|
1336
|
+
function parseReplacementSpecs(value: string, kind: UltragoalSteeringKind): ReplacementSpec[] {
|
|
1337
|
+
const raw = parseJsonFlag(value, "replacements-json", kind);
|
|
1338
|
+
if (!Array.isArray(raw) || raw.length < 2) {
|
|
1339
|
+
throw new Error("steer --replacements-json must be an array with at least two replacements");
|
|
1340
|
+
}
|
|
1341
|
+
const seen = new Set<string>();
|
|
1342
|
+
return raw.map((item, index) => {
|
|
1343
|
+
if (typeof item !== "object" || item === null || Array.isArray(item)) {
|
|
1344
|
+
throw new Error(`steer --replacements-json[${index}] must be an object`);
|
|
1345
|
+
}
|
|
1346
|
+
const record = item as Record<string, unknown>;
|
|
1347
|
+
const title = typeof record.title === "string" ? record.title.trim() : "";
|
|
1348
|
+
const objective = typeof record.objective === "string" ? record.objective.trim() : "";
|
|
1349
|
+
if (!title || !objective) {
|
|
1350
|
+
throw new Error(`steer --replacements-json[${index}] requires non-empty title and objective`);
|
|
1351
|
+
}
|
|
1352
|
+
const key = `${title}\u0000${objective}`;
|
|
1353
|
+
if (seen.has(key)) throw new Error(`steer --replacements-json[${index}] duplicates an earlier replacement`);
|
|
1354
|
+
seen.add(key);
|
|
1355
|
+
return { title, objective };
|
|
1356
|
+
});
|
|
1357
|
+
}
|
|
1358
|
+
|
|
1359
|
+
function parsePendingOrder(value: string, kind: UltragoalSteeringKind): string[] {
|
|
1360
|
+
const raw = parseJsonFlag(value, "order-json", kind);
|
|
1361
|
+
if (!Array.isArray(raw) || raw.length === 0) {
|
|
1362
|
+
throw new Error("steer --order-json must be a non-empty array of goal ids");
|
|
1363
|
+
}
|
|
1364
|
+
const seen = new Set<string>();
|
|
1365
|
+
return raw.map((item, index) => {
|
|
1366
|
+
if (typeof item !== "string" || item.trim().length === 0) {
|
|
1367
|
+
throw new Error(`steer --order-json[${index}] must be a non-empty goal id string`);
|
|
1368
|
+
}
|
|
1369
|
+
const id = item.trim();
|
|
1370
|
+
if (seen.has(id)) throw new Error(`steer --order-json contains duplicate goal id ${id}`);
|
|
1371
|
+
seen.add(id);
|
|
1372
|
+
return id;
|
|
1373
|
+
});
|
|
1374
|
+
}
|
|
1375
|
+
|
|
1376
|
+
async function appendSteeringRejected(input: {
|
|
1377
|
+
cwd: string;
|
|
1378
|
+
kind: UltragoalSteeringKind;
|
|
1379
|
+
reason: string;
|
|
1380
|
+
goalId?: string;
|
|
1381
|
+
evidence?: string;
|
|
1382
|
+
rationale?: string;
|
|
1383
|
+
payload?: JsonObject;
|
|
1384
|
+
}): Promise<void> {
|
|
1385
|
+
await appendLedger(input.cwd, {
|
|
1386
|
+
event: "steering_rejected",
|
|
1387
|
+
kind: input.kind,
|
|
1388
|
+
goalId: input.goalId?.trim() || undefined,
|
|
1389
|
+
reason: input.reason,
|
|
1390
|
+
evidence: input.evidence?.trim() || undefined,
|
|
1391
|
+
rationale: input.rationale?.trim() || undefined,
|
|
1392
|
+
payload: input.payload,
|
|
1393
|
+
});
|
|
1394
|
+
}
|
|
1395
|
+
|
|
1396
|
+
function steeringPayloadSummary(args: readonly string[]): JsonObject {
|
|
1397
|
+
return {
|
|
1398
|
+
goalId: flagValue(args, "--goal-id"),
|
|
1399
|
+
title: flagValue(args, "--title"),
|
|
1400
|
+
objective: flagValue(args, "--objective"),
|
|
1401
|
+
replacementsJson: flagValue(args, "--replacements-json"),
|
|
1402
|
+
orderJson: flagValue(args, "--order-json"),
|
|
1403
|
+
};
|
|
1404
|
+
}
|
|
1405
|
+
|
|
1406
|
+
function parseNativeSteeringKind(value: string | undefined): UltragoalSteeringKind {
|
|
1407
|
+
if (typeof value === "string" && NATIVE_STEERING_KIND_SET.has(value)) return value as UltragoalSteeringKind;
|
|
1408
|
+
throw new Error(`native steering currently supports --kind ${NATIVE_STEERING_KINDS.join(", ")}`);
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1411
|
+
async function addUltragoalSubgoalToPlan(input: {
|
|
1267
1412
|
cwd: string;
|
|
1413
|
+
plan: UltragoalPlan;
|
|
1268
1414
|
title: string;
|
|
1269
1415
|
objective: string;
|
|
1270
1416
|
evidence: string;
|
|
1271
1417
|
rationale: string;
|
|
1272
|
-
}): Promise<UltragoalPlan> {
|
|
1273
|
-
const
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
if (!value.trim()) throw new Error(`steer --${label} is required for add_subgoal`);
|
|
1282
|
-
}
|
|
1418
|
+
}): Promise<{ plan: UltragoalPlan; goalId: string }> {
|
|
1419
|
+
const kind = "add_subgoal";
|
|
1420
|
+
const title = requireSteeringText(input.title, "title", kind);
|
|
1421
|
+
const objective = requireSteeringText(input.objective, "objective", kind);
|
|
1422
|
+
const { evidence, rationale } = requireSteeringEvidence({
|
|
1423
|
+
kind,
|
|
1424
|
+
evidence: input.evidence,
|
|
1425
|
+
rationale: input.rationale,
|
|
1426
|
+
});
|
|
1283
1427
|
const now = new Date().toISOString();
|
|
1284
|
-
const nextId =
|
|
1285
|
-
plan.goals.push({
|
|
1428
|
+
const nextId = nextUltragoalGoalId(input.plan);
|
|
1429
|
+
input.plan.goals.push({
|
|
1286
1430
|
id: nextId,
|
|
1287
|
-
title
|
|
1288
|
-
objective
|
|
1431
|
+
title,
|
|
1432
|
+
objective,
|
|
1289
1433
|
status: "pending",
|
|
1290
1434
|
createdAt: now,
|
|
1291
1435
|
updatedAt: now,
|
|
1292
|
-
steering: { kind
|
|
1436
|
+
steering: { kind, evidence, rationale },
|
|
1293
1437
|
});
|
|
1294
|
-
plan.updatedAt = now;
|
|
1295
|
-
await writePlan(input.cwd, plan);
|
|
1438
|
+
input.plan.updatedAt = now;
|
|
1439
|
+
await writePlan(input.cwd, input.plan);
|
|
1296
1440
|
await appendLedger(input.cwd, {
|
|
1297
1441
|
event: "steering_accepted",
|
|
1298
|
-
kind
|
|
1442
|
+
kind,
|
|
1299
1443
|
goalId: nextId,
|
|
1300
|
-
evidence
|
|
1301
|
-
rationale
|
|
1444
|
+
evidence,
|
|
1445
|
+
rationale,
|
|
1302
1446
|
});
|
|
1303
|
-
return plan;
|
|
1447
|
+
return { plan: input.plan, goalId: nextId };
|
|
1448
|
+
}
|
|
1449
|
+
|
|
1450
|
+
export async function addUltragoalSubgoal(input: {
|
|
1451
|
+
cwd: string;
|
|
1452
|
+
title: string;
|
|
1453
|
+
objective: string;
|
|
1454
|
+
evidence: string;
|
|
1455
|
+
rationale: string;
|
|
1456
|
+
}): Promise<UltragoalPlan> {
|
|
1457
|
+
const plan = await readUltragoalPlan(input.cwd);
|
|
1458
|
+
if (!plan) throw new Error("No ultragoal plan found. Run `gjc ultragoal create-goals --brief ...` first.");
|
|
1459
|
+
return (await addUltragoalSubgoalToPlan({ ...input, plan })).plan;
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1462
|
+
async function splitUltragoalSubgoal(input: {
|
|
1463
|
+
cwd: string;
|
|
1464
|
+
plan: UltragoalPlan;
|
|
1465
|
+
goalId: string;
|
|
1466
|
+
replacementsJson: string;
|
|
1467
|
+
evidence: string;
|
|
1468
|
+
rationale: string;
|
|
1469
|
+
}): Promise<{ plan: UltragoalPlan; goalId: string; replacementGoalIds: string[] }> {
|
|
1470
|
+
const kind = "split_subgoal";
|
|
1471
|
+
const { evidence, rationale } = requireSteeringEvidence({
|
|
1472
|
+
kind,
|
|
1473
|
+
evidence: input.evidence,
|
|
1474
|
+
rationale: input.rationale,
|
|
1475
|
+
});
|
|
1476
|
+
const target = findGoalOrThrow(input.plan, input.goalId, kind);
|
|
1477
|
+
requireGoalStatus(target, ["pending"], kind);
|
|
1478
|
+
const replacements = parseReplacementSpecs(input.replacementsJson, kind);
|
|
1479
|
+
const now = new Date().toISOString();
|
|
1480
|
+
const replacementGoalIds = replacements.map((_, index) => nextUltragoalGoalId(input.plan, index + 1));
|
|
1481
|
+
target.status = "superseded";
|
|
1482
|
+
target.evidence = evidence;
|
|
1483
|
+
target.updatedAt = now;
|
|
1484
|
+
target.steering = { kind, evidence, rationale, replacementGoalIds };
|
|
1485
|
+
const replacementGoals = replacements.map(
|
|
1486
|
+
(replacement, index): UltragoalGoal => ({
|
|
1487
|
+
id: replacementGoalIds[index]!,
|
|
1488
|
+
title: replacement.title,
|
|
1489
|
+
objective: replacement.objective,
|
|
1490
|
+
status: "pending",
|
|
1491
|
+
createdAt: now,
|
|
1492
|
+
updatedAt: now,
|
|
1493
|
+
steering: { kind: "split_replacement", sourceGoalId: target.id, evidence, rationale },
|
|
1494
|
+
}),
|
|
1495
|
+
);
|
|
1496
|
+
const targetIndex = input.plan.goals.findIndex(goal => goal.id === target.id);
|
|
1497
|
+
input.plan.goals.splice(targetIndex + 1, 0, ...replacementGoals);
|
|
1498
|
+
input.plan.updatedAt = now;
|
|
1499
|
+
await writePlan(input.cwd, input.plan);
|
|
1500
|
+
await appendLedger(input.cwd, {
|
|
1501
|
+
event: "steering_accepted",
|
|
1502
|
+
kind,
|
|
1503
|
+
goalId: target.id,
|
|
1504
|
+
replacementGoalIds,
|
|
1505
|
+
evidence,
|
|
1506
|
+
rationale,
|
|
1507
|
+
});
|
|
1508
|
+
return { plan: input.plan, goalId: target.id, replacementGoalIds };
|
|
1509
|
+
}
|
|
1510
|
+
|
|
1511
|
+
async function reorderPendingUltragoalGoals(input: {
|
|
1512
|
+
cwd: string;
|
|
1513
|
+
plan: UltragoalPlan;
|
|
1514
|
+
orderJson: string;
|
|
1515
|
+
evidence: string;
|
|
1516
|
+
rationale: string;
|
|
1517
|
+
}): Promise<{ plan: UltragoalPlan; pendingGoalIds: string[] }> {
|
|
1518
|
+
const kind = "reorder_pending";
|
|
1519
|
+
const { evidence, rationale } = requireSteeringEvidence({
|
|
1520
|
+
kind,
|
|
1521
|
+
evidence: input.evidence,
|
|
1522
|
+
rationale: input.rationale,
|
|
1523
|
+
});
|
|
1524
|
+
const pendingGoalIds = input.plan.goals.filter(goal => goal.status === "pending").map(goal => goal.id);
|
|
1525
|
+
const requestedOrder = parsePendingOrder(input.orderJson, kind);
|
|
1526
|
+
const pendingSet = new Set(pendingGoalIds);
|
|
1527
|
+
for (const id of requestedOrder) {
|
|
1528
|
+
const goal = input.plan.goals.find(item => item.id === id);
|
|
1529
|
+
if (!goal) throw new Error(`steer --order-json references unknown goal id ${id}`);
|
|
1530
|
+
if (goal.status !== "pending") throw new Error(`steer --order-json references non-pending goal id ${id}`);
|
|
1531
|
+
}
|
|
1532
|
+
const missing = pendingGoalIds.filter(id => !requestedOrder.includes(id));
|
|
1533
|
+
if (missing.length > 0) throw new Error(`steer --order-json missing pending goal id(s): ${missing.join(", ")}`);
|
|
1534
|
+
if (requestedOrder.length !== pendingSet.size)
|
|
1535
|
+
throw new Error("steer --order-json must include every pending goal exactly once");
|
|
1536
|
+
const pendingById = new Map(input.plan.goals.map(goal => [goal.id, goal]));
|
|
1537
|
+
const remaining = [...requestedOrder];
|
|
1538
|
+
input.plan.goals = input.plan.goals.map(goal =>
|
|
1539
|
+
goal.status === "pending" ? pendingById.get(remaining.shift()!)! : goal,
|
|
1540
|
+
);
|
|
1541
|
+
input.plan.updatedAt = new Date().toISOString();
|
|
1542
|
+
await writePlan(input.cwd, input.plan);
|
|
1543
|
+
await appendLedger(input.cwd, {
|
|
1544
|
+
event: "steering_accepted",
|
|
1545
|
+
kind,
|
|
1546
|
+
previousPendingGoalIds: pendingGoalIds,
|
|
1547
|
+
pendingGoalIds: requestedOrder,
|
|
1548
|
+
evidence,
|
|
1549
|
+
rationale,
|
|
1550
|
+
});
|
|
1551
|
+
return { plan: input.plan, pendingGoalIds: requestedOrder };
|
|
1552
|
+
}
|
|
1553
|
+
|
|
1554
|
+
async function revisePendingUltragoalWording(input: {
|
|
1555
|
+
cwd: string;
|
|
1556
|
+
plan: UltragoalPlan;
|
|
1557
|
+
goalId: string;
|
|
1558
|
+
title?: string;
|
|
1559
|
+
objective?: string;
|
|
1560
|
+
evidence: string;
|
|
1561
|
+
rationale: string;
|
|
1562
|
+
}): Promise<{ plan: UltragoalPlan; goalId: string; changedFields: string[] }> {
|
|
1563
|
+
const kind = "revise_pending_wording";
|
|
1564
|
+
const { evidence, rationale } = requireSteeringEvidence({
|
|
1565
|
+
kind,
|
|
1566
|
+
evidence: input.evidence,
|
|
1567
|
+
rationale: input.rationale,
|
|
1568
|
+
});
|
|
1569
|
+
const goal = findGoalOrThrow(input.plan, input.goalId, kind);
|
|
1570
|
+
requireGoalStatus(goal, ["pending"], kind);
|
|
1571
|
+
const title = input.title === undefined ? undefined : input.title.trim();
|
|
1572
|
+
const objective = input.objective === undefined ? undefined : input.objective.trim();
|
|
1573
|
+
if (input.title !== undefined && !title)
|
|
1574
|
+
throw new Error("steer --title must be non-empty for revise_pending_wording");
|
|
1575
|
+
if (input.objective !== undefined && !objective)
|
|
1576
|
+
throw new Error("steer --objective must be non-empty for revise_pending_wording");
|
|
1577
|
+
if (!title && !objective) throw new Error("revise_pending_wording requires --title and/or --objective");
|
|
1578
|
+
const changedFields: string[] = [];
|
|
1579
|
+
if (title !== undefined) {
|
|
1580
|
+
goal.title = title;
|
|
1581
|
+
changedFields.push("title");
|
|
1582
|
+
}
|
|
1583
|
+
if (objective !== undefined) {
|
|
1584
|
+
goal.objective = objective;
|
|
1585
|
+
changedFields.push("objective");
|
|
1586
|
+
}
|
|
1587
|
+
const now = new Date().toISOString();
|
|
1588
|
+
goal.updatedAt = now;
|
|
1589
|
+
goal.steering = { kind, evidence, rationale, changedFields };
|
|
1590
|
+
input.plan.updatedAt = now;
|
|
1591
|
+
await writePlan(input.cwd, input.plan);
|
|
1592
|
+
await appendLedger(input.cwd, {
|
|
1593
|
+
event: "steering_accepted",
|
|
1594
|
+
kind,
|
|
1595
|
+
goalId: goal.id,
|
|
1596
|
+
changedFields,
|
|
1597
|
+
evidence,
|
|
1598
|
+
rationale,
|
|
1599
|
+
});
|
|
1600
|
+
return { plan: input.plan, goalId: goal.id, changedFields };
|
|
1601
|
+
}
|
|
1602
|
+
|
|
1603
|
+
async function annotateUltragoalLedger(input: {
|
|
1604
|
+
cwd: string;
|
|
1605
|
+
plan: UltragoalPlan;
|
|
1606
|
+
evidence: string;
|
|
1607
|
+
rationale: string;
|
|
1608
|
+
}): Promise<{ plan: UltragoalPlan }> {
|
|
1609
|
+
const kind = "annotate_ledger";
|
|
1610
|
+
const { evidence, rationale } = requireSteeringEvidence({
|
|
1611
|
+
kind,
|
|
1612
|
+
evidence: input.evidence,
|
|
1613
|
+
rationale: input.rationale,
|
|
1614
|
+
});
|
|
1615
|
+
await appendLedger(input.cwd, { event: "steering_accepted", kind, evidence, rationale });
|
|
1616
|
+
return { plan: input.plan };
|
|
1617
|
+
}
|
|
1618
|
+
|
|
1619
|
+
async function markBlockedUltragoalSuperseded(input: {
|
|
1620
|
+
cwd: string;
|
|
1621
|
+
plan: UltragoalPlan;
|
|
1622
|
+
goalId: string;
|
|
1623
|
+
evidence: string;
|
|
1624
|
+
rationale: string;
|
|
1625
|
+
}): Promise<{ plan: UltragoalPlan; goalId: string }> {
|
|
1626
|
+
const kind = "mark_blocked_superseded";
|
|
1627
|
+
const { evidence, rationale } = requireSteeringEvidence({
|
|
1628
|
+
kind,
|
|
1629
|
+
evidence: input.evidence,
|
|
1630
|
+
rationale: input.rationale,
|
|
1631
|
+
});
|
|
1632
|
+
const goal = findGoalOrThrow(input.plan, input.goalId, kind);
|
|
1633
|
+
requireGoalStatus(goal, ["blocked", "review_blocked"], kind);
|
|
1634
|
+
const remainingRequiredGoals = requiredUltragoalGoals(input.plan).filter(item => item.id !== goal.id);
|
|
1635
|
+
if (remainingRequiredGoals.length === 0) {
|
|
1636
|
+
throw new Error(`steer ${kind} cannot supersede ${goal.id} because it is the only remaining required goal`);
|
|
1637
|
+
}
|
|
1638
|
+
const now = new Date().toISOString();
|
|
1639
|
+
goal.status = "superseded";
|
|
1640
|
+
goal.evidence = evidence;
|
|
1641
|
+
goal.updatedAt = now;
|
|
1642
|
+
goal.steering = { kind, evidence, rationale, noReplacementRequired: true };
|
|
1643
|
+
input.plan.updatedAt = now;
|
|
1644
|
+
await writePlan(input.cwd, input.plan);
|
|
1645
|
+
await appendLedger(input.cwd, {
|
|
1646
|
+
event: "steering_accepted",
|
|
1647
|
+
kind,
|
|
1648
|
+
goalId: goal.id,
|
|
1649
|
+
noReplacementRequired: true,
|
|
1650
|
+
evidence,
|
|
1651
|
+
rationale,
|
|
1652
|
+
});
|
|
1653
|
+
return { plan: input.plan, goalId: goal.id };
|
|
1304
1654
|
}
|
|
1305
1655
|
|
|
1306
1656
|
export async function recordUltragoalReviewBlockers(input: {
|
|
@@ -1365,6 +1715,8 @@ const FLAGS_WITH_VALUES = new Set([
|
|
|
1365
1715
|
"--title",
|
|
1366
1716
|
"--objective",
|
|
1367
1717
|
"--rationale",
|
|
1718
|
+
"--replacements-json",
|
|
1719
|
+
"--order-json",
|
|
1368
1720
|
]);
|
|
1369
1721
|
|
|
1370
1722
|
function isHelpArg(arg: string): boolean {
|
|
@@ -1523,6 +1875,135 @@ function renderCheckpointContinuation(
|
|
|
1523
1875
|
return lines.join("\n");
|
|
1524
1876
|
}
|
|
1525
1877
|
|
|
1878
|
+
async function executeUltragoalSteeringCommand(args: readonly string[], cwd: string): Promise<SteeringCommandResult> {
|
|
1879
|
+
const kind = parseNativeSteeringKind(flagValue(args, "--kind"));
|
|
1880
|
+
const plan = await readUltragoalPlan(cwd);
|
|
1881
|
+
if (!plan) throw new Error("No ultragoal plan found. Run `gjc ultragoal create-goals --brief ...` first.");
|
|
1882
|
+
const evidence = flagValue(args, "--evidence") ?? "";
|
|
1883
|
+
const rationale = flagValue(args, "--rationale") ?? "";
|
|
1884
|
+
try {
|
|
1885
|
+
switch (kind) {
|
|
1886
|
+
case "add_subgoal": {
|
|
1887
|
+
const result = await addUltragoalSubgoalToPlan({
|
|
1888
|
+
cwd,
|
|
1889
|
+
plan,
|
|
1890
|
+
title: flagValue(args, "--title") ?? "",
|
|
1891
|
+
objective: flagValue(args, "--objective") ?? "",
|
|
1892
|
+
evidence,
|
|
1893
|
+
rationale,
|
|
1894
|
+
});
|
|
1895
|
+
return {
|
|
1896
|
+
kind,
|
|
1897
|
+
message: "Accepted add_subgoal steering.\n",
|
|
1898
|
+
receipt: { ok: true, kind, goal_id: result.goalId, goals_path: getUltragoalPaths(cwd).goalsPath },
|
|
1899
|
+
};
|
|
1900
|
+
}
|
|
1901
|
+
case "split_subgoal": {
|
|
1902
|
+
const result = await splitUltragoalSubgoal({
|
|
1903
|
+
cwd,
|
|
1904
|
+
plan,
|
|
1905
|
+
goalId: flagValue(args, "--goal-id") ?? "",
|
|
1906
|
+
replacementsJson: flagValue(args, "--replacements-json") ?? "",
|
|
1907
|
+
evidence,
|
|
1908
|
+
rationale,
|
|
1909
|
+
});
|
|
1910
|
+
return {
|
|
1911
|
+
kind,
|
|
1912
|
+
message: "Accepted split_subgoal steering.\n",
|
|
1913
|
+
receipt: {
|
|
1914
|
+
ok: true,
|
|
1915
|
+
kind,
|
|
1916
|
+
goal_id: result.goalId,
|
|
1917
|
+
replacement_goal_ids: result.replacementGoalIds,
|
|
1918
|
+
goals_path: getUltragoalPaths(cwd).goalsPath,
|
|
1919
|
+
},
|
|
1920
|
+
};
|
|
1921
|
+
}
|
|
1922
|
+
case "reorder_pending": {
|
|
1923
|
+
const result = await reorderPendingUltragoalGoals({
|
|
1924
|
+
cwd,
|
|
1925
|
+
plan,
|
|
1926
|
+
orderJson: flagValue(args, "--order-json") ?? "",
|
|
1927
|
+
evidence,
|
|
1928
|
+
rationale,
|
|
1929
|
+
});
|
|
1930
|
+
return {
|
|
1931
|
+
kind,
|
|
1932
|
+
message: "Accepted reorder_pending steering.\n",
|
|
1933
|
+
receipt: {
|
|
1934
|
+
ok: true,
|
|
1935
|
+
kind,
|
|
1936
|
+
pending_goal_ids: result.pendingGoalIds,
|
|
1937
|
+
goals_path: getUltragoalPaths(cwd).goalsPath,
|
|
1938
|
+
},
|
|
1939
|
+
};
|
|
1940
|
+
}
|
|
1941
|
+
case "revise_pending_wording": {
|
|
1942
|
+
const result = await revisePendingUltragoalWording({
|
|
1943
|
+
cwd,
|
|
1944
|
+
plan,
|
|
1945
|
+
goalId: flagValue(args, "--goal-id") ?? "",
|
|
1946
|
+
title: flagValue(args, "--title"),
|
|
1947
|
+
objective: flagValue(args, "--objective"),
|
|
1948
|
+
evidence,
|
|
1949
|
+
rationale,
|
|
1950
|
+
});
|
|
1951
|
+
return {
|
|
1952
|
+
kind,
|
|
1953
|
+
message: "Accepted revise_pending_wording steering.\n",
|
|
1954
|
+
receipt: {
|
|
1955
|
+
ok: true,
|
|
1956
|
+
kind,
|
|
1957
|
+
goal_id: result.goalId,
|
|
1958
|
+
changed_fields: result.changedFields,
|
|
1959
|
+
goals_path: getUltragoalPaths(cwd).goalsPath,
|
|
1960
|
+
},
|
|
1961
|
+
};
|
|
1962
|
+
}
|
|
1963
|
+
case "annotate_ledger": {
|
|
1964
|
+
await annotateUltragoalLedger({ cwd, plan, evidence, rationale });
|
|
1965
|
+
return {
|
|
1966
|
+
kind,
|
|
1967
|
+
message: "Accepted annotate_ledger steering.\n",
|
|
1968
|
+
receipt: { ok: true, kind, ledger_path: getUltragoalPaths(cwd).ledgerPath },
|
|
1969
|
+
};
|
|
1970
|
+
}
|
|
1971
|
+
case "mark_blocked_superseded": {
|
|
1972
|
+
const result = await markBlockedUltragoalSuperseded({
|
|
1973
|
+
cwd,
|
|
1974
|
+
plan,
|
|
1975
|
+
goalId: flagValue(args, "--goal-id") ?? "",
|
|
1976
|
+
evidence,
|
|
1977
|
+
rationale,
|
|
1978
|
+
});
|
|
1979
|
+
return {
|
|
1980
|
+
kind,
|
|
1981
|
+
message: "Accepted mark_blocked_superseded steering.\n",
|
|
1982
|
+
receipt: {
|
|
1983
|
+
ok: true,
|
|
1984
|
+
kind,
|
|
1985
|
+
goal_id: result.goalId,
|
|
1986
|
+
no_replacement_required: true,
|
|
1987
|
+
goals_path: getUltragoalPaths(cwd).goalsPath,
|
|
1988
|
+
},
|
|
1989
|
+
};
|
|
1990
|
+
}
|
|
1991
|
+
}
|
|
1992
|
+
} catch (error) {
|
|
1993
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
1994
|
+
await appendSteeringRejected({
|
|
1995
|
+
cwd,
|
|
1996
|
+
kind,
|
|
1997
|
+
reason,
|
|
1998
|
+
goalId: flagValue(args, "--goal-id"),
|
|
1999
|
+
evidence,
|
|
2000
|
+
rationale,
|
|
2001
|
+
payload: steeringPayloadSummary(args),
|
|
2002
|
+
});
|
|
2003
|
+
throw error;
|
|
2004
|
+
}
|
|
2005
|
+
}
|
|
2006
|
+
|
|
1526
2007
|
async function dispatchUltragoalCommand(args: string[], cwd: string): Promise<UltragoalCommandResult> {
|
|
1527
2008
|
const help = renderUltragoalHelp(args);
|
|
1528
2009
|
if (help) return { status: 0, stdout: help };
|
|
@@ -1577,26 +2058,10 @@ async function dispatchUltragoalCommand(args: string[], cwd: string): Promise<Ul
|
|
|
1577
2058
|
};
|
|
1578
2059
|
}
|
|
1579
2060
|
case "steer": {
|
|
1580
|
-
const
|
|
1581
|
-
if (kind !== "add_subgoal") throw new Error("native steering currently supports --kind add_subgoal");
|
|
1582
|
-
const plan = await addUltragoalSubgoal({
|
|
1583
|
-
cwd,
|
|
1584
|
-
title: flagValue(args, "--title") ?? "",
|
|
1585
|
-
objective: flagValue(args, "--objective") ?? "",
|
|
1586
|
-
evidence: flagValue(args, "--evidence") ?? "",
|
|
1587
|
-
rationale: flagValue(args, "--rationale") ?? "",
|
|
1588
|
-
});
|
|
1589
|
-
const goal = plan.goals.at(-1);
|
|
2061
|
+
const result = await executeUltragoalSteeringCommand(args, cwd);
|
|
1590
2062
|
return {
|
|
1591
2063
|
status: 0,
|
|
1592
|
-
stdout: json
|
|
1593
|
-
? renderCliWriteReceipt({
|
|
1594
|
-
ok: true,
|
|
1595
|
-
kind,
|
|
1596
|
-
goal_id: goal?.id,
|
|
1597
|
-
goals_path: getUltragoalPaths(cwd).goalsPath,
|
|
1598
|
-
})
|
|
1599
|
-
: "Accepted add_subgoal steering.\n",
|
|
2064
|
+
stdout: json ? renderCliWriteReceipt(result.receipt) : result.message,
|
|
1600
2065
|
};
|
|
1601
2066
|
}
|
|
1602
2067
|
case "record-review-blockers": {
|
|
@@ -1663,6 +2128,17 @@ async function reconcileUltragoalState(cwd: string): Promise<void> {
|
|
|
1663
2128
|
goals_path: summary.paths.goalsPath,
|
|
1664
2129
|
};
|
|
1665
2130
|
if (summary.gjcObjective) payload.gjc_objective = summary.gjcObjective;
|
|
2131
|
+
const ledgerText = await Bun.file(summary.paths.ledgerPath)
|
|
2132
|
+
.text()
|
|
2133
|
+
.catch(() => "");
|
|
2134
|
+
const latestLedger = latestUltragoalLedgerEventFromText(ledgerText);
|
|
2135
|
+
if (latestLedger) {
|
|
2136
|
+
payload.latestLedgerEvent = {
|
|
2137
|
+
event: latestLedger.event,
|
|
2138
|
+
...(latestLedger.goalId ? { goalId: latestLedger.goalId } : {}),
|
|
2139
|
+
...(latestLedger.timestamp ? { timestamp: latestLedger.timestamp } : {}),
|
|
2140
|
+
};
|
|
2141
|
+
}
|
|
1666
2142
|
await reconcileWorkflowSkillState({ cwd, mode: "ultragoal", sessionId, active, phase: status, payload });
|
|
1667
2143
|
} catch (error) {
|
|
1668
2144
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -1464,12 +1464,24 @@
|
|
|
1464
1464
|
"name": "quality-gate-json",
|
|
1465
1465
|
"type": "string"
|
|
1466
1466
|
},
|
|
1467
|
+
{
|
|
1468
|
+
"appliesToVerbs": [
|
|
1469
|
+
"steer"
|
|
1470
|
+
],
|
|
1471
|
+
"name": "goal-id",
|
|
1472
|
+
"type": "string"
|
|
1473
|
+
},
|
|
1467
1474
|
{
|
|
1468
1475
|
"appliesToVerbs": [
|
|
1469
1476
|
"steer"
|
|
1470
1477
|
],
|
|
1471
1478
|
"enumValues": [
|
|
1472
|
-
"add_subgoal"
|
|
1479
|
+
"add_subgoal",
|
|
1480
|
+
"split_subgoal",
|
|
1481
|
+
"reorder_pending",
|
|
1482
|
+
"revise_pending_wording",
|
|
1483
|
+
"annotate_ledger",
|
|
1484
|
+
"mark_blocked_superseded"
|
|
1473
1485
|
],
|
|
1474
1486
|
"name": "kind",
|
|
1475
1487
|
"type": "enum"
|
|
@@ -1497,6 +1509,20 @@
|
|
|
1497
1509
|
"name": "rationale",
|
|
1498
1510
|
"type": "string"
|
|
1499
1511
|
},
|
|
1512
|
+
{
|
|
1513
|
+
"appliesToVerbs": [
|
|
1514
|
+
"steer"
|
|
1515
|
+
],
|
|
1516
|
+
"name": "replacements-json",
|
|
1517
|
+
"type": "string"
|
|
1518
|
+
},
|
|
1519
|
+
{
|
|
1520
|
+
"appliesToVerbs": [
|
|
1521
|
+
"steer"
|
|
1522
|
+
],
|
|
1523
|
+
"name": "order-json",
|
|
1524
|
+
"type": "string"
|
|
1525
|
+
},
|
|
1500
1526
|
{
|
|
1501
1527
|
"appliesToVerbs": [
|
|
1502
1528
|
"status",
|
|
@@ -267,10 +267,25 @@ export const WORKFLOW_MANIFEST: Record<CanonicalGjcWorkflowSkill, SkillManifest>
|
|
|
267
267
|
},
|
|
268
268
|
{ name: "gjc-goal-json", type: "string", appliesToVerbs: ["checkpoint", "record-review-blockers"] },
|
|
269
269
|
{ name: "quality-gate-json", type: "string", appliesToVerbs: ["checkpoint"] },
|
|
270
|
-
{ name: "
|
|
270
|
+
{ name: "goal-id", type: "string", appliesToVerbs: ["steer"] },
|
|
271
|
+
{
|
|
272
|
+
name: "kind",
|
|
273
|
+
type: "enum",
|
|
274
|
+
enumValues: [
|
|
275
|
+
"add_subgoal",
|
|
276
|
+
"split_subgoal",
|
|
277
|
+
"reorder_pending",
|
|
278
|
+
"revise_pending_wording",
|
|
279
|
+
"annotate_ledger",
|
|
280
|
+
"mark_blocked_superseded",
|
|
281
|
+
],
|
|
282
|
+
appliesToVerbs: ["steer"],
|
|
283
|
+
},
|
|
271
284
|
{ name: "title", type: "string", appliesToVerbs: ["record-review-blockers", "steer"] },
|
|
272
285
|
{ name: "objective", type: "string", appliesToVerbs: ["record-review-blockers", "steer"] },
|
|
273
286
|
{ name: "rationale", type: "string", appliesToVerbs: ["steer"] },
|
|
287
|
+
{ name: "replacements-json", type: "string", appliesToVerbs: ["steer"] },
|
|
288
|
+
{ name: "order-json", type: "string", appliesToVerbs: ["steer"] },
|
|
274
289
|
{
|
|
275
290
|
name: "json",
|
|
276
291
|
type: "boolean",
|