@gajae-code/coding-agent 0.3.0 → 0.3.2
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 +32 -0
- package/README.md +1 -1
- package/dist/types/async/job-manager.d.ts +7 -0
- package/dist/types/cli/args.d.ts +3 -1
- package/dist/types/commands/deep-interview.d.ts +3 -0
- package/dist/types/commands/launch.d.ts +6 -0
- package/dist/types/config/keybindings.d.ts +5 -0
- package/dist/types/config/model-profile-activation.d.ts +30 -0
- package/dist/types/config/model-profiles.d.ts +19 -0
- package/dist/types/config/model-registry.d.ts +8 -0
- package/dist/types/config/model-resolver.d.ts +1 -1
- package/dist/types/config/models-config-schema.d.ts +47 -0
- package/dist/types/config/settings-schema.d.ts +14 -4
- package/dist/types/debug/crash-diagnostics.d.ts +45 -0
- package/dist/types/debug/runtime-gauges.d.ts +6 -0
- package/dist/types/deep-interview/render-middleware.d.ts +1 -0
- package/dist/types/eval/py/executor.d.ts +2 -0
- package/dist/types/eval/py/kernel.d.ts +2 -0
- package/dist/types/exec/bash-executor.d.ts +10 -0
- package/dist/types/gjc-runtime/cli-write-receipt.d.ts +24 -0
- package/dist/types/gjc-runtime/deep-interview-runtime.d.ts +1 -0
- package/dist/types/gjc-runtime/state-migrations.d.ts +9 -0
- package/dist/types/gjc-runtime/state-schema.d.ts +317 -0
- package/dist/types/gjc-runtime/state-writer.d.ts +10 -0
- package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +2 -1
- package/dist/types/gjc-runtime/workflow-command-ref.d.ts +43 -0
- package/dist/types/harness-control-plane/control-endpoint.d.ts +3 -2
- package/dist/types/hooks/skill-state.d.ts +21 -0
- package/dist/types/internal-urls/agent-protocol.d.ts +2 -2
- package/dist/types/internal-urls/artifact-protocol.d.ts +2 -2
- package/dist/types/internal-urls/registry-helpers.d.ts +8 -7
- package/dist/types/internal-urls/types.d.ts +4 -0
- package/dist/types/lsp/index.d.ts +10 -10
- package/dist/types/main.d.ts +10 -1
- package/dist/types/modes/bridge/auth.d.ts +12 -0
- package/dist/types/modes/bridge/bridge-client-bridge.d.ts +9 -0
- package/dist/types/modes/bridge/bridge-mode.d.ts +44 -0
- package/dist/types/modes/bridge/bridge-ui-context.d.ts +88 -0
- package/dist/types/modes/bridge/event-stream.d.ts +8 -0
- package/dist/types/modes/components/custom-editor.d.ts +6 -0
- package/dist/types/modes/components/custom-provider-wizard.d.ts +10 -0
- package/dist/types/modes/components/jobs-overlay-model.d.ts +31 -0
- package/dist/types/modes/components/jobs-overlay.d.ts +30 -0
- package/dist/types/modes/components/model-selector.d.ts +6 -1
- package/dist/types/modes/components/provider-onboarding-selector.d.ts +1 -1
- package/dist/types/modes/components/status-line/types.d.ts +2 -0
- package/dist/types/modes/components/status-line.d.ts +2 -0
- package/dist/types/modes/controllers/input-controller.d.ts +1 -0
- package/dist/types/modes/controllers/selector-controller.d.ts +9 -0
- package/dist/types/modes/index.d.ts +1 -0
- package/dist/types/modes/interactive-mode.d.ts +1 -0
- package/dist/types/modes/jobs-observer.d.ts +57 -0
- package/dist/types/modes/rpc/host-tools.d.ts +1 -16
- package/dist/types/modes/rpc/host-uris.d.ts +1 -38
- package/dist/types/modes/shared/agent-wire/command-dispatch.d.ts +20 -0
- package/dist/types/modes/shared/agent-wire/command-validation.d.ts +2 -0
- package/dist/types/modes/shared/agent-wire/event-envelope.d.ts +24 -0
- package/dist/types/modes/shared/agent-wire/handshake.d.ts +46 -0
- package/dist/types/modes/shared/agent-wire/host-tool-bridge.d.ts +16 -0
- package/dist/types/modes/shared/agent-wire/host-uri-bridge.d.ts +17 -0
- package/dist/types/modes/shared/agent-wire/protocol.d.ts +44 -0
- package/dist/types/modes/shared/agent-wire/responses.d.ts +4 -0
- package/dist/types/modes/shared/agent-wire/scopes.d.ts +18 -0
- package/dist/types/modes/shared/agent-wire/ui-request-broker.d.ts +42 -0
- package/dist/types/modes/shared/agent-wire/ui-result.d.ts +27 -0
- package/dist/types/modes/types.d.ts +2 -0
- package/dist/types/sdk.d.ts +3 -1
- package/dist/types/session/agent-session.d.ts +11 -1
- package/dist/types/skill-state/workflow-state-contract.d.ts +1 -2
- package/dist/types/skill-state/workflow-state-version.d.ts +3 -0
- package/dist/types/task/executor.d.ts +1 -0
- package/dist/types/task/id.d.ts +7 -0
- package/dist/types/task/index.d.ts +5 -0
- package/dist/types/task/receipt.d.ts +85 -0
- package/dist/types/task/spawn-gate.d.ts +38 -0
- package/dist/types/task/types.d.ts +143 -11
- package/dist/types/tools/cron.d.ts +6 -0
- package/dist/types/tools/hindsight-recall.d.ts +0 -2
- package/dist/types/tools/hindsight-reflect.d.ts +0 -2
- package/dist/types/tools/hindsight-retain.d.ts +0 -2
- package/dist/types/tools/index.d.ts +6 -4
- package/dist/types/tools/path-utils.d.ts +1 -0
- package/dist/types/tools/subagent.d.ts +15 -0
- package/package.json +7 -7
- package/scripts/build-binary.ts +7 -0
- package/src/async/job-manager.ts +36 -0
- package/src/cli/args.ts +19 -2
- package/src/commands/deep-interview.ts +1 -0
- package/src/commands/harness.ts +289 -19
- package/src/commands/launch.ts +10 -2
- package/src/commands/state.ts +2 -1
- package/src/commands/team.ts +22 -4
- package/src/config/keybindings.ts +6 -0
- package/src/config/model-profile-activation.ts +157 -0
- package/src/config/model-profiles.ts +155 -0
- package/src/config/model-registry.ts +19 -0
- package/src/config/model-resolver.ts +3 -2
- package/src/config/models-config-schema.ts +36 -0
- package/src/config/settings-schema.ts +16 -3
- package/src/dap/client.ts +17 -3
- package/src/debug/crash-diagnostics.ts +223 -0
- package/src/debug/runtime-gauges.ts +20 -0
- package/src/deep-interview/render-middleware.ts +6 -0
- package/src/defaults/gjc/skills/deep-interview/SKILL.md +1 -1
- package/src/defaults/gjc/skills/ralplan/SKILL.md +31 -2
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +39 -3
- package/src/defaults/gjc/skills/ultragoal/ai-slop-cleaner.md +61 -0
- package/src/defaults/gjc-defaults.ts +7 -0
- package/src/eval/py/executor.ts +21 -1
- package/src/eval/py/kernel.ts +15 -0
- package/src/exec/bash-executor.ts +41 -0
- package/src/gjc-runtime/cli-write-receipt.ts +31 -0
- package/src/gjc-runtime/deep-interview-runtime.ts +69 -32
- package/src/gjc-runtime/ralplan-runtime.ts +213 -36
- package/src/gjc-runtime/state-migrations.ts +54 -7
- package/src/gjc-runtime/state-runtime.ts +461 -64
- package/src/gjc-runtime/state-schema.ts +192 -0
- package/src/gjc-runtime/state-writer.ts +32 -1
- package/src/gjc-runtime/team-runtime.ts +177 -105
- package/src/gjc-runtime/ultragoal-runtime.ts +231 -38
- package/src/gjc-runtime/workflow-command-ref.ts +239 -0
- package/src/gjc-runtime/workflow-manifest.generated.json +108 -4
- package/src/gjc-runtime/workflow-manifest.ts +3 -1
- package/src/harness-control-plane/control-endpoint.ts +19 -8
- package/src/harness-control-plane/owner.ts +57 -10
- package/src/harness-control-plane/state-machine.ts +2 -1
- package/src/hooks/skill-state.ts +176 -26
- package/src/internal-urls/agent-protocol.ts +68 -21
- package/src/internal-urls/artifact-protocol.ts +12 -17
- package/src/internal-urls/docs-index.generated.ts +8 -10
- package/src/internal-urls/registry-helpers.ts +19 -16
- package/src/internal-urls/types.ts +4 -0
- package/src/lsp/client.ts +18 -2
- package/src/main.ts +88 -6
- package/src/modes/bridge/auth.ts +41 -0
- package/src/modes/bridge/bridge-client-bridge.ts +47 -0
- package/src/modes/bridge/bridge-mode.ts +520 -0
- package/src/modes/bridge/bridge-ui-context.ts +200 -0
- package/src/modes/bridge/event-stream.ts +70 -0
- package/src/modes/components/custom-editor.ts +101 -0
- package/src/modes/components/custom-provider-wizard.ts +318 -0
- package/src/modes/components/hook-selector.ts +61 -18
- package/src/modes/components/jobs-overlay-model.ts +109 -0
- package/src/modes/components/jobs-overlay.ts +172 -0
- package/src/modes/components/model-selector.ts +108 -18
- package/src/modes/components/provider-onboarding-selector.ts +6 -1
- package/src/modes/components/status-line/presets.ts +7 -5
- package/src/modes/components/status-line/segments.ts +25 -0
- package/src/modes/components/status-line/types.ts +2 -0
- package/src/modes/components/status-line.ts +9 -1
- package/src/modes/controllers/extension-ui-controller.ts +39 -3
- package/src/modes/controllers/input-controller.ts +97 -9
- package/src/modes/controllers/selector-controller.ts +86 -1
- package/src/modes/index.ts +1 -0
- package/src/modes/interactive-mode.ts +27 -0
- package/src/modes/jobs-observer.ts +204 -0
- package/src/modes/rpc/host-tools.ts +1 -186
- package/src/modes/rpc/host-uris.ts +1 -235
- package/src/modes/rpc/rpc-client.ts +25 -10
- package/src/modes/rpc/rpc-mode.ts +12 -381
- package/src/modes/shared/agent-wire/command-dispatch.ts +341 -0
- package/src/modes/shared/agent-wire/command-validation.ts +131 -0
- package/src/modes/shared/agent-wire/event-envelope.ts +108 -0
- package/src/modes/shared/agent-wire/handshake.ts +117 -0
- package/src/modes/shared/agent-wire/host-tool-bridge.ts +194 -0
- package/src/modes/shared/agent-wire/host-uri-bridge.ts +236 -0
- package/src/modes/shared/agent-wire/protocol.ts +96 -0
- package/src/modes/shared/agent-wire/responses.ts +17 -0
- package/src/modes/shared/agent-wire/scopes.ts +89 -0
- package/src/modes/shared/agent-wire/ui-request-broker.ts +150 -0
- package/src/modes/shared/agent-wire/ui-result.ts +48 -0
- package/src/modes/types.ts +2 -0
- package/src/prompts/memories/consolidation.md +1 -1
- package/src/prompts/memories/read-path.md +6 -7
- package/src/prompts/memories/unavailable.md +2 -2
- package/src/prompts/tools/bash.md +1 -1
- package/src/prompts/tools/irc.md +1 -1
- package/src/prompts/tools/read.md +2 -2
- package/src/prompts/tools/recall.md +1 -0
- package/src/prompts/tools/reflect.md +1 -0
- package/src/prompts/tools/retain.md +1 -0
- package/src/prompts/tools/subagent.md +12 -7
- package/src/prompts/tools/task-summary.md +3 -9
- package/src/prompts/tools/task.md +5 -1
- package/src/sdk.ts +5 -1
- package/src/session/agent-session.ts +214 -38
- package/src/skill-state/deep-interview-mutation-guard.ts +23 -4
- package/src/skill-state/workflow-state-contract.ts +7 -4
- package/src/skill-state/workflow-state-version.ts +3 -0
- package/src/slash-commands/builtin-registry.ts +9 -1
- package/src/task/executor.ts +31 -5
- package/src/task/id.ts +33 -0
- package/src/task/index.ts +259 -67
- package/src/task/output-manager.ts +5 -4
- package/src/task/receipt.ts +297 -0
- package/src/task/render.ts +48 -131
- package/src/task/spawn-gate.ts +132 -0
- package/src/task/types.ts +48 -7
- package/src/tools/ask.ts +73 -33
- package/src/tools/ast-edit.ts +1 -0
- package/src/tools/ast-grep.ts +1 -0
- package/src/tools/bash.ts +1 -1
- package/src/tools/cron.ts +48 -0
- package/src/tools/find.ts +4 -1
- package/src/tools/hindsight-recall.ts +0 -2
- package/src/tools/hindsight-reflect.ts +0 -2
- package/src/tools/hindsight-retain.ts +0 -2
- package/src/tools/index.ts +6 -18
- package/src/tools/path-utils.ts +3 -2
- package/src/tools/read.ts +4 -3
- package/src/tools/search.ts +1 -0
- package/src/tools/skill.ts +6 -1
- package/src/tools/subagent.ts +237 -84
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
import * as crypto from "node:crypto";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
-
import type
|
|
3
|
+
import { syncSkillActiveState, type WorkflowHudSummary } from "../skill-state/active-state";
|
|
4
4
|
import { buildUltragoalHudSummary as buildWorkflowUltragoalHudSummary } from "../skill-state/workflow-hud";
|
|
5
|
+
import { WORKFLOW_STATE_VERSION, workflowStateStoragePath } from "../skill-state/workflow-state-contract";
|
|
6
|
+
import { renderCliWriteReceipt } from "./cli-write-receipt";
|
|
5
7
|
import { DEFAULT_ULTRAGOAL_OBJECTIVE } from "./goal-mode-request";
|
|
6
8
|
import { renderUltragoalStatusMarkdown } from "./state-renderer";
|
|
7
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
appendJsonl,
|
|
11
|
+
readExistingStateForMutation,
|
|
12
|
+
writeArtifact,
|
|
13
|
+
writeJsonAtomic,
|
|
14
|
+
writeWorkflowEnvelopeAtomic,
|
|
15
|
+
} from "./state-writer";
|
|
8
16
|
|
|
9
17
|
export type UltragoalGjcGoalMode = "aggregate" | "per-story";
|
|
10
18
|
export type UltragoalGoalStatus =
|
|
@@ -473,14 +481,145 @@ export function buildUltragoalHudSummary(
|
|
|
473
481
|
updatedAt: new Date().toISOString(),
|
|
474
482
|
});
|
|
475
483
|
}
|
|
484
|
+
function currentSessionId(): string | undefined {
|
|
485
|
+
const sessionId = process.env.GJC_SESSION_ID?.trim();
|
|
486
|
+
return sessionId || undefined;
|
|
487
|
+
}
|
|
476
488
|
|
|
477
|
-
function
|
|
478
|
-
|
|
489
|
+
function ultragoalModeStateFromSummary(
|
|
490
|
+
summary: UltragoalStatusSummary,
|
|
491
|
+
latestLedger: UltragoalLedgerEvent | undefined,
|
|
492
|
+
existing: Record<string, unknown> | undefined,
|
|
493
|
+
sessionId: string | undefined,
|
|
494
|
+
): Record<string, unknown> {
|
|
495
|
+
const updatedAt = new Date().toISOString();
|
|
496
|
+
return {
|
|
497
|
+
...(existing ?? {}),
|
|
498
|
+
skill: "ultragoal",
|
|
499
|
+
version: WORKFLOW_STATE_VERSION,
|
|
500
|
+
active: summary.exists && summary.status !== "complete",
|
|
501
|
+
current_phase: summary.status,
|
|
502
|
+
status: summary.status,
|
|
503
|
+
active_goal_id: summary.currentGoal?.id,
|
|
504
|
+
counts: summary.counts,
|
|
505
|
+
brief_path: summary.paths.briefPath,
|
|
506
|
+
ledger_path: summary.paths.ledgerPath,
|
|
507
|
+
goals_path: summary.paths.goalsPath,
|
|
508
|
+
latest_ledger_event: latestLedger?.event,
|
|
509
|
+
latest_ledger_event_id: latestLedger?.eventId,
|
|
510
|
+
updated_at: updatedAt,
|
|
511
|
+
...(sessionId ? { session_id: sessionId } : {}),
|
|
512
|
+
};
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
export async function syncUltragoalWorkflowState(cwd: string): Promise<void> {
|
|
516
|
+
const summary = await getUltragoalStatus(cwd);
|
|
517
|
+
const ledger = await readUltragoalLedger(cwd);
|
|
518
|
+
const latestLedger = ledger.at(-1);
|
|
519
|
+
const sessionId = currentSessionId();
|
|
520
|
+
const modeStateActive = summary.exists && summary.status !== "complete";
|
|
521
|
+
const syncModeState = async (targetSessionId: string | undefined): Promise<void> => {
|
|
522
|
+
const statePath = workflowStateStoragePath(cwd, "ultragoal", targetSessionId);
|
|
523
|
+
const existing = await readExistingStateForMutation(statePath);
|
|
524
|
+
if (existing.kind === "corrupt" && modeStateActive)
|
|
525
|
+
throw new Error(`Cannot sync corrupt ultragoal mode-state: ${existing.error}`);
|
|
526
|
+
const existingValue = existing.kind === "valid" ? existing.value : undefined;
|
|
527
|
+
await writeWorkflowEnvelopeAtomic(
|
|
528
|
+
statePath,
|
|
529
|
+
ultragoalModeStateFromSummary(summary, latestLedger, existingValue, targetSessionId),
|
|
530
|
+
{
|
|
531
|
+
cwd,
|
|
532
|
+
receipt: {
|
|
533
|
+
cwd,
|
|
534
|
+
skill: "ultragoal",
|
|
535
|
+
owner: "gjc-runtime",
|
|
536
|
+
command: "gjc ultragoal sync",
|
|
537
|
+
sessionId: targetSessionId,
|
|
538
|
+
},
|
|
539
|
+
audit: {
|
|
540
|
+
category: "state",
|
|
541
|
+
verb: "sync",
|
|
542
|
+
owner: "gjc-runtime",
|
|
543
|
+
skill: "ultragoal",
|
|
544
|
+
fromPhase: typeof existingValue?.current_phase === "string" ? existingValue.current_phase : undefined,
|
|
545
|
+
toPhase: summary.status,
|
|
546
|
+
},
|
|
547
|
+
},
|
|
548
|
+
);
|
|
549
|
+
};
|
|
550
|
+
await syncModeState(undefined);
|
|
551
|
+
if (sessionId) await syncModeState(sessionId);
|
|
552
|
+
await syncSkillActiveState({
|
|
553
|
+
cwd,
|
|
554
|
+
skill: "ultragoal",
|
|
555
|
+
active: summary.exists && summary.status !== "complete",
|
|
556
|
+
phase: summary.status,
|
|
557
|
+
sessionId: currentSessionId(),
|
|
558
|
+
hud: buildUltragoalHudSummary(summary, latestLedger),
|
|
559
|
+
source: "gjc-ultragoal",
|
|
560
|
+
});
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
async function syncUltragoalWorkflowStateBestEffort(cwd: string): Promise<void> {
|
|
564
|
+
try {
|
|
565
|
+
await syncUltragoalWorkflowState(cwd);
|
|
566
|
+
} catch {
|
|
567
|
+
// HUD and mode-state sync are best-effort and must not change command semantics.
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
function clampTitle(title: string): string {
|
|
572
|
+
return title.length > 80 ? `${title.slice(0, 77)}...` : title;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
function firstNonEmptyLine(text: string): string | undefined {
|
|
576
|
+
return text
|
|
479
577
|
.split(/\r?\n/)
|
|
480
578
|
.map(line => line.trim())
|
|
481
579
|
.find(line => line.length > 0);
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
function titleFromBrief(brief: string): string {
|
|
583
|
+
const firstLine = firstNonEmptyLine(brief);
|
|
482
584
|
if (!firstLine) return "Complete ultragoal brief";
|
|
483
|
-
return firstLine
|
|
585
|
+
return clampTitle(firstLine);
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
// A reserved, column-0 (unindented) `@goal` line opens a story. The character
|
|
589
|
+
// right after `@goal` must be `:`, an ASCII space or tab, or end-of-line, so
|
|
590
|
+
// `@goalish`, `@goals:`, `@goal-foo`, `@goal.foo`, `@goal/foo`, a non-breaking
|
|
591
|
+
// space, and indented or mid-line `@goal:` are all ordinary objective text and
|
|
592
|
+
// never delimiters.
|
|
593
|
+
const GOAL_DELIMITER = /^@goal(?::|[ \t]+|$)[ \t]*(.*)$/;
|
|
594
|
+
|
|
595
|
+
interface ParsedGoal {
|
|
596
|
+
title: string;
|
|
597
|
+
objective: string;
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
function parseGoalsFromBrief(brief: string): ParsedGoal[] {
|
|
601
|
+
const sections: { title: string; body: string[] }[] = [];
|
|
602
|
+
let current: { title: string; body: string[] } | undefined;
|
|
603
|
+
for (const line of brief.split(/\r?\n/)) {
|
|
604
|
+
const match = GOAL_DELIMITER.exec(line);
|
|
605
|
+
if (match) {
|
|
606
|
+
current = { title: match[1].trim(), body: [] };
|
|
607
|
+
sections.push(current);
|
|
608
|
+
continue;
|
|
609
|
+
}
|
|
610
|
+
current?.body.push(line);
|
|
611
|
+
}
|
|
612
|
+
if (sections.length === 0) {
|
|
613
|
+
return [{ title: titleFromBrief(brief), objective: brief.trim() }];
|
|
614
|
+
}
|
|
615
|
+
return sections.map((section, index) => {
|
|
616
|
+
const body = section.body.join("\n").trim();
|
|
617
|
+
const title = section.title || firstNonEmptyLine(body) || "";
|
|
618
|
+
if (!title && !body) {
|
|
619
|
+
throw new Error(`ultragoal @goal block ${index + 1} has no title or objective`);
|
|
620
|
+
}
|
|
621
|
+
return { title: clampTitle(title), objective: body || title };
|
|
622
|
+
});
|
|
484
623
|
}
|
|
485
624
|
|
|
486
625
|
export async function createUltragoalPlan(input: {
|
|
@@ -491,21 +630,23 @@ export async function createUltragoalPlan(input: {
|
|
|
491
630
|
const brief = input.brief.trim();
|
|
492
631
|
if (!brief) throw new Error("ultragoal brief is required");
|
|
493
632
|
const now = new Date().toISOString();
|
|
633
|
+
// Parse the untrimmed brief so the raw-line delimiter contract holds: a
|
|
634
|
+
// leading-indented `@goal` on the first line must stay objective text rather
|
|
635
|
+
// than being promoted to column 0 by trimming.
|
|
636
|
+
const goals: UltragoalGoal[] = parseGoalsFromBrief(input.brief).map((goal, index) => ({
|
|
637
|
+
id: `G${String(index + 1).padStart(3, "0")}`,
|
|
638
|
+
title: goal.title,
|
|
639
|
+
objective: goal.objective,
|
|
640
|
+
status: "pending",
|
|
641
|
+
createdAt: now,
|
|
642
|
+
updatedAt: now,
|
|
643
|
+
}));
|
|
494
644
|
const plan: UltragoalPlan = {
|
|
495
645
|
version: 1,
|
|
496
646
|
brief,
|
|
497
647
|
gjcGoalMode: input.gjcGoalMode ?? "aggregate",
|
|
498
648
|
gjcObjective: DEFAULT_ULTRAGOAL_OBJECTIVE,
|
|
499
|
-
goals
|
|
500
|
-
{
|
|
501
|
-
id: "G001",
|
|
502
|
-
title: titleFromBrief(brief),
|
|
503
|
-
objective: brief,
|
|
504
|
-
status: "pending",
|
|
505
|
-
createdAt: now,
|
|
506
|
-
updatedAt: now,
|
|
507
|
-
},
|
|
508
|
-
],
|
|
649
|
+
goals,
|
|
509
650
|
createdAt: now,
|
|
510
651
|
updatedAt: now,
|
|
511
652
|
};
|
|
@@ -1235,16 +1376,26 @@ function renderStatus(summary: UltragoalStatusSummary, json: boolean): string {
|
|
|
1235
1376
|
function renderCompleteHandoff(
|
|
1236
1377
|
result: { plan: UltragoalPlan; goal?: UltragoalGoal; allComplete: boolean },
|
|
1237
1378
|
json: boolean,
|
|
1379
|
+
cwd: string,
|
|
1238
1380
|
): string {
|
|
1239
|
-
if (json)
|
|
1240
|
-
|
|
1241
|
-
|
|
1381
|
+
if (json) {
|
|
1382
|
+
return renderCliWriteReceipt({
|
|
1383
|
+
ok: true,
|
|
1384
|
+
all_complete: result.allComplete,
|
|
1385
|
+
next_action: result.allComplete ? "none" : "execute-goal",
|
|
1386
|
+
goal_id: result.goal?.id,
|
|
1387
|
+
goal_status: result.goal?.status,
|
|
1388
|
+
gjc_objective: result.plan.gjcObjective,
|
|
1389
|
+
goals_path: getUltragoalPaths(cwd).goalsPath,
|
|
1390
|
+
});
|
|
1391
|
+
}
|
|
1392
|
+
if (result.allComplete) return "ultragoal complete all=true\n";
|
|
1393
|
+
if (!result.goal) return "ultragoal next-action=none\n";
|
|
1242
1394
|
return [
|
|
1243
|
-
`
|
|
1244
|
-
`
|
|
1245
|
-
`
|
|
1246
|
-
|
|
1247
|
-
'Before checkpointing complete, obtain a passing architectReview (architecture/product/code CLEAR + APPROVE) and executorQa (e2e/red-team passed with contractCoverage, surfaceEvidence, adversarialCases, and artifactRefs matrix evidence), then checkpoint with --quality-gate-json and a fresh active goal snapshot; record blockers instead of completing on any finding, plan/code mismatch, shallow evidence, or missing artifact link; call goal({"op":"complete"}) only after the final aggregate receipt exists.',
|
|
1395
|
+
`ultragoal next-action=execute-goal goal-id=${result.goal.id}`,
|
|
1396
|
+
`objective=${result.goal.objective}`,
|
|
1397
|
+
`gjc-objective=${result.plan.gjcObjective}`,
|
|
1398
|
+
"checkpoint requires=architectReview:CLEAR+APPROVE,executorQa:passed",
|
|
1248
1399
|
"",
|
|
1249
1400
|
].join("\n");
|
|
1250
1401
|
}
|
|
@@ -1253,29 +1404,40 @@ export async function runNativeUltragoalCommand(args: string[], cwd = process.cw
|
|
|
1253
1404
|
try {
|
|
1254
1405
|
const command = commandName(args);
|
|
1255
1406
|
const json = hasFlag(args, "--json");
|
|
1407
|
+
let result: UltragoalCommandResult;
|
|
1256
1408
|
switch (command) {
|
|
1257
1409
|
case "status":
|
|
1258
|
-
|
|
1410
|
+
await syncUltragoalWorkflowStateBestEffort(cwd);
|
|
1411
|
+
result = { status: 0, stdout: renderStatus(await getUltragoalStatus(cwd), json) };
|
|
1412
|
+
break;
|
|
1259
1413
|
case "create":
|
|
1260
1414
|
case "create-goals": {
|
|
1261
1415
|
const mode = flagValue(args, "--gjc-goal-mode") === "per-story" ? "per-story" : "aggregate";
|
|
1262
1416
|
const plan = await createUltragoalPlan({ cwd, brief: await readBrief(cwd, args), gjcGoalMode: mode });
|
|
1263
|
-
|
|
1417
|
+
await syncUltragoalWorkflowStateBestEffort(cwd);
|
|
1418
|
+
result = {
|
|
1264
1419
|
status: 0,
|
|
1265
1420
|
createdPlan: true,
|
|
1266
1421
|
stdout: json
|
|
1267
|
-
?
|
|
1268
|
-
|
|
1422
|
+
? renderCliWriteReceipt({
|
|
1423
|
+
ok: true,
|
|
1424
|
+
goals_count: plan.goals.length,
|
|
1425
|
+
goal_ids: plan.goals.map(goal => goal.id),
|
|
1426
|
+
goals_path: getUltragoalPaths(cwd).goalsPath,
|
|
1427
|
+
})
|
|
1428
|
+
: `Created ultragoal plan with ${plan.goals.length} goal${plan.goals.length === 1 ? "" : "s"} at ${getUltragoalPaths(cwd).goalsPath}.\n`,
|
|
1269
1429
|
};
|
|
1430
|
+
break;
|
|
1270
1431
|
}
|
|
1271
|
-
case "complete-goals":
|
|
1272
|
-
|
|
1432
|
+
case "complete-goals": {
|
|
1433
|
+
const handoff = await startNextUltragoalGoal({ cwd, retryFailed: hasFlag(args, "--retry-failed") });
|
|
1434
|
+
await syncUltragoalWorkflowStateBestEffort(cwd);
|
|
1435
|
+
result = {
|
|
1273
1436
|
status: 0,
|
|
1274
|
-
stdout: renderCompleteHandoff(
|
|
1275
|
-
await startNextUltragoalGoal({ cwd, retryFailed: hasFlag(args, "--retry-failed") }),
|
|
1276
|
-
json,
|
|
1277
|
-
),
|
|
1437
|
+
stdout: renderCompleteHandoff(handoff, json, cwd),
|
|
1278
1438
|
};
|
|
1439
|
+
break;
|
|
1440
|
+
}
|
|
1279
1441
|
case "checkpoint": {
|
|
1280
1442
|
const goalId = flagValue(args, "--goal-id") ?? "";
|
|
1281
1443
|
const status = parseGoalStatus(flagValue(args, "--status"));
|
|
@@ -1288,10 +1450,22 @@ export async function runNativeUltragoalCommand(args: string[], cwd = process.cw
|
|
|
1288
1450
|
gjcGoalJson: flagValue(args, "--gjc-goal-json"),
|
|
1289
1451
|
qualityGateJson: flagValue(args, "--quality-gate-json"),
|
|
1290
1452
|
});
|
|
1291
|
-
|
|
1453
|
+
await syncUltragoalWorkflowStateBestEffort(cwd);
|
|
1454
|
+
const goal = plan.goals.find(item => item.id === goalId);
|
|
1455
|
+
result = {
|
|
1292
1456
|
status: 0,
|
|
1293
|
-
stdout: json
|
|
1457
|
+
stdout: json
|
|
1458
|
+
? renderCliWriteReceipt({
|
|
1459
|
+
ok: true,
|
|
1460
|
+
goal_id: goalId,
|
|
1461
|
+
status,
|
|
1462
|
+
goals_path: getUltragoalPaths(cwd).goalsPath,
|
|
1463
|
+
completion_receipt_kind: goal?.completionVerification?.receiptKind,
|
|
1464
|
+
quality_gate_hash: goal?.completionVerification?.qualityGateHash,
|
|
1465
|
+
})
|
|
1466
|
+
: `ultragoal checkpoint goal-id=${goalId} status=${status}\n`,
|
|
1294
1467
|
};
|
|
1468
|
+
break;
|
|
1295
1469
|
}
|
|
1296
1470
|
case "steer": {
|
|
1297
1471
|
const kind = flagValue(args, "--kind");
|
|
@@ -1303,10 +1477,20 @@ export async function runNativeUltragoalCommand(args: string[], cwd = process.cw
|
|
|
1303
1477
|
evidence: flagValue(args, "--evidence") ?? "",
|
|
1304
1478
|
rationale: flagValue(args, "--rationale") ?? "",
|
|
1305
1479
|
});
|
|
1306
|
-
|
|
1480
|
+
await syncUltragoalWorkflowStateBestEffort(cwd);
|
|
1481
|
+
const goal = plan.goals.at(-1);
|
|
1482
|
+
result = {
|
|
1307
1483
|
status: 0,
|
|
1308
|
-
stdout: json
|
|
1484
|
+
stdout: json
|
|
1485
|
+
? renderCliWriteReceipt({
|
|
1486
|
+
ok: true,
|
|
1487
|
+
kind,
|
|
1488
|
+
goal_id: goal?.id,
|
|
1489
|
+
goals_path: getUltragoalPaths(cwd).goalsPath,
|
|
1490
|
+
})
|
|
1491
|
+
: "Accepted add_subgoal steering.\n",
|
|
1309
1492
|
};
|
|
1493
|
+
break;
|
|
1310
1494
|
}
|
|
1311
1495
|
case "record-review-blockers": {
|
|
1312
1496
|
const plan = await recordUltragoalReviewBlockers({
|
|
@@ -1317,11 +1501,20 @@ export async function runNativeUltragoalCommand(args: string[], cwd = process.cw
|
|
|
1317
1501
|
evidence: flagValue(args, "--evidence") ?? "",
|
|
1318
1502
|
gjcGoalJson: flagValue(args, "--gjc-goal-json"),
|
|
1319
1503
|
});
|
|
1320
|
-
|
|
1504
|
+
await syncUltragoalWorkflowStateBestEffort(cwd);
|
|
1505
|
+
const goal = plan.goals.at(-1);
|
|
1506
|
+
result = {
|
|
1507
|
+
status: 0,
|
|
1508
|
+
stdout: json
|
|
1509
|
+
? renderCliWriteReceipt({ ok: true, goal_id: goal?.id, goals_path: getUltragoalPaths(cwd).goalsPath })
|
|
1510
|
+
: "Recorded review blockers.\n",
|
|
1511
|
+
};
|
|
1512
|
+
break;
|
|
1321
1513
|
}
|
|
1322
1514
|
default:
|
|
1323
1515
|
return { status: 1, stderr: `Unknown gjc ultragoal command: ${command}\n` };
|
|
1324
1516
|
}
|
|
1517
|
+
return result;
|
|
1325
1518
|
} catch (error) {
|
|
1326
1519
|
return { status: 1, stderr: `${error instanceof Error ? error.message : String(error)}\n` };
|
|
1327
1520
|
}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import type { CanonicalGjcWorkflowSkill } from "../skill-state/active-state";
|
|
2
|
+
import { CANONICAL_GJC_WORKFLOW_SKILLS } from "../skill-state/active-state";
|
|
3
|
+
|
|
4
|
+
export type CommandRefVisibility = "public" | "hidden" | "planned";
|
|
5
|
+
export type CommandRefIncludeWhen = "implemented-only" | "planned";
|
|
6
|
+
|
|
7
|
+
export interface CommandRefCommand {
|
|
8
|
+
tokens: string[];
|
|
9
|
+
rendered: string;
|
|
10
|
+
visibility: CommandRefVisibility;
|
|
11
|
+
includeWhen: CommandRefIncludeWhen;
|
|
12
|
+
note?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface CommandRefExample {
|
|
16
|
+
label?: string;
|
|
17
|
+
bytes: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface CommandRefBridge {
|
|
21
|
+
from: string;
|
|
22
|
+
to: string;
|
|
23
|
+
rendered: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface CommandRefBlock {
|
|
27
|
+
skill: CanonicalGjcWorkflowSkill;
|
|
28
|
+
blockId: string;
|
|
29
|
+
sourcePath: string;
|
|
30
|
+
renderOrder: number;
|
|
31
|
+
markers: {
|
|
32
|
+
start: string;
|
|
33
|
+
end: string;
|
|
34
|
+
};
|
|
35
|
+
commands: CommandRefCommand[];
|
|
36
|
+
examples: CommandRefExample[];
|
|
37
|
+
aliasesAndBridges: CommandRefBridge[];
|
|
38
|
+
notes: string[];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface RenderedCommandRefBlock {
|
|
42
|
+
skill: CanonicalGjcWorkflowSkill;
|
|
43
|
+
blockId: string;
|
|
44
|
+
markers: CommandRefBlock["markers"];
|
|
45
|
+
bytes: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const skillPath = (skill: CanonicalGjcWorkflowSkill): string =>
|
|
49
|
+
`packages/coding-agent/src/defaults/gjc/skills/${skill}/SKILL.md`;
|
|
50
|
+
|
|
51
|
+
const stateWrite = (skill: CanonicalGjcWorkflowSkill): CommandRefCommand => ({
|
|
52
|
+
tokens: ["gjc", "state", skill, "write", "--input", `'{"current_phase":"handoff"}'`, "--json"],
|
|
53
|
+
rendered: `gjc state ${skill} write --input '{"current_phase":"handoff"}' --json`,
|
|
54
|
+
visibility: "public",
|
|
55
|
+
includeWhen: "implemented-only",
|
|
56
|
+
note: "Marks the workflow ready for the skill-tool chain guard.",
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const stateHandoff = (
|
|
60
|
+
skill: CanonicalGjcWorkflowSkill,
|
|
61
|
+
targets: readonly CanonicalGjcWorkflowSkill[],
|
|
62
|
+
): CommandRefCommand => ({
|
|
63
|
+
tokens: ["gjc", "state", skill, "handoff", "--to", `<${targets.join("|")}>`, "--json"],
|
|
64
|
+
rendered: `gjc state ${skill} handoff --to <${targets.join("|")}> --json`,
|
|
65
|
+
visibility: "public",
|
|
66
|
+
includeWhen: "implemented-only",
|
|
67
|
+
note: "Bridge command run in-process by the skill tool after slash-skill dispatch.",
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
export const WORKFLOW_COMMAND_REF_BLOCKS: readonly CommandRefBlock[] = [
|
|
71
|
+
{
|
|
72
|
+
skill: "deep-interview",
|
|
73
|
+
blockId: "state",
|
|
74
|
+
sourcePath: skillPath("deep-interview"),
|
|
75
|
+
renderOrder: 10,
|
|
76
|
+
markers: {
|
|
77
|
+
start: "<!-- gjc:cmdref:start state -->",
|
|
78
|
+
end: "<!-- gjc:cmdref:end state -->",
|
|
79
|
+
},
|
|
80
|
+
commands: [
|
|
81
|
+
stateWrite("deep-interview"),
|
|
82
|
+
{
|
|
83
|
+
tokens: [
|
|
84
|
+
"gjc",
|
|
85
|
+
"deep-interview",
|
|
86
|
+
"--write",
|
|
87
|
+
"--stage",
|
|
88
|
+
"final",
|
|
89
|
+
"--slug",
|
|
90
|
+
"{slug}",
|
|
91
|
+
"--spec",
|
|
92
|
+
"<markdown-or-path>",
|
|
93
|
+
"--deliberate",
|
|
94
|
+
"--json",
|
|
95
|
+
],
|
|
96
|
+
rendered:
|
|
97
|
+
"gjc deep-interview --write --stage final --slug {slug} --spec <markdown-or-path> --deliberate --json",
|
|
98
|
+
visibility: "public",
|
|
99
|
+
includeWhen: "implemented-only",
|
|
100
|
+
note: "Sanctioned deliberate deep-interview to ralplan bridge.",
|
|
101
|
+
},
|
|
102
|
+
],
|
|
103
|
+
examples: [
|
|
104
|
+
{
|
|
105
|
+
label: "handoff state write",
|
|
106
|
+
bytes: '```\ngjc state deep-interview write --input \'{"current_phase":"handoff"}\' --json\n```',
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
label: "deliberate bridge",
|
|
110
|
+
bytes: "```\ngjc \\\ndeep-interview --write --stage final --slug {slug} --spec <markdown-or-path> --deliberate --json\n```",
|
|
111
|
+
},
|
|
112
|
+
],
|
|
113
|
+
aliasesAndBridges: [
|
|
114
|
+
{
|
|
115
|
+
from: "deep-interview",
|
|
116
|
+
to: "ralplan",
|
|
117
|
+
rendered:
|
|
118
|
+
"gjc deep-interview --write --stage final --slug {slug} --spec <markdown-or-path> --deliberate --json",
|
|
119
|
+
},
|
|
120
|
+
],
|
|
121
|
+
notes: [
|
|
122
|
+
"Before invoking `/skill:ralplan`, `/skill:team`, or `/skill:ultragoal`, persist the final spec and mark deep-interview ready for handoff.",
|
|
123
|
+
],
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
skill: "ralplan",
|
|
127
|
+
blockId: "state",
|
|
128
|
+
sourcePath: skillPath("ralplan"),
|
|
129
|
+
renderOrder: 10,
|
|
130
|
+
markers: { start: "<!-- gjc:cmdref:start state -->", end: "<!-- gjc:cmdref:end state -->" },
|
|
131
|
+
commands: [stateWrite("ralplan"), stateHandoff("ralplan", ["team", "ultragoal"])],
|
|
132
|
+
examples: [
|
|
133
|
+
{
|
|
134
|
+
label: "handoff state write",
|
|
135
|
+
bytes: '```\ngjc state ralplan write --input \'{"current_phase":"handoff"}\' --json\n```',
|
|
136
|
+
},
|
|
137
|
+
],
|
|
138
|
+
aliasesAndBridges: [
|
|
139
|
+
{ from: "ralplan", to: "team|ultragoal", rendered: "gjc state ralplan handoff --to <team|ultragoal> --json" },
|
|
140
|
+
],
|
|
141
|
+
notes: [
|
|
142
|
+
"Before invoking `/skill:team` or `/skill:ultragoal`, mark ralplan ready for handoff so the skill tool's chain guard permits the transition.",
|
|
143
|
+
],
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
skill: "ultragoal",
|
|
147
|
+
blockId: "state",
|
|
148
|
+
sourcePath: skillPath("ultragoal"),
|
|
149
|
+
renderOrder: 10,
|
|
150
|
+
markers: { start: "<!-- gjc:cmdref:start state -->", end: "<!-- gjc:cmdref:end state -->" },
|
|
151
|
+
commands: [stateWrite("ultragoal"), stateHandoff("ultragoal", ["ralplan", "deep-interview"])],
|
|
152
|
+
examples: [
|
|
153
|
+
{
|
|
154
|
+
label: "handoff state write",
|
|
155
|
+
bytes: '```\ngjc state ultragoal write --input \'{"current_phase":"handoff"}\' --json\n```',
|
|
156
|
+
},
|
|
157
|
+
],
|
|
158
|
+
aliasesAndBridges: [
|
|
159
|
+
{
|
|
160
|
+
from: "ultragoal",
|
|
161
|
+
to: "ralplan|deep-interview",
|
|
162
|
+
rendered: "gjc state ultragoal handoff --to <ralplan|deep-interview> --json",
|
|
163
|
+
},
|
|
164
|
+
],
|
|
165
|
+
notes: [
|
|
166
|
+
"When the aggregate ultragoal is complete OR the user requests return to planning/clarification, mark ultragoal ready for handoff.",
|
|
167
|
+
],
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
skill: "team",
|
|
171
|
+
blockId: "state",
|
|
172
|
+
sourcePath: skillPath("team"),
|
|
173
|
+
renderOrder: 10,
|
|
174
|
+
markers: { start: "<!-- gjc:cmdref:start state -->", end: "<!-- gjc:cmdref:end state -->" },
|
|
175
|
+
commands: [stateWrite("team"), stateHandoff("team", ["ralplan", "deep-interview", "ultragoal"])],
|
|
176
|
+
examples: [
|
|
177
|
+
{
|
|
178
|
+
label: "handoff state write",
|
|
179
|
+
bytes: '```\ngjc state team write --input \'{"current_phase":"handoff"}\' --json\n```',
|
|
180
|
+
},
|
|
181
|
+
],
|
|
182
|
+
aliasesAndBridges: [
|
|
183
|
+
{
|
|
184
|
+
from: "team",
|
|
185
|
+
to: "ralplan|deep-interview|ultragoal",
|
|
186
|
+
rendered: "gjc state team handoff --to <ralplan|deep-interview|ultragoal> --json",
|
|
187
|
+
},
|
|
188
|
+
],
|
|
189
|
+
notes: [
|
|
190
|
+
"When the team task-set completes OR the user requests return to planning/persistence, mark team ready for handoff.",
|
|
191
|
+
],
|
|
192
|
+
},
|
|
193
|
+
] as const;
|
|
194
|
+
|
|
195
|
+
export function listCommandRefBlocks(skill?: CanonicalGjcWorkflowSkill): CommandRefBlock[] {
|
|
196
|
+
const blocks =
|
|
197
|
+
skill === undefined
|
|
198
|
+
? WORKFLOW_COMMAND_REF_BLOCKS
|
|
199
|
+
: WORKFLOW_COMMAND_REF_BLOCKS.filter(block => block.skill === skill);
|
|
200
|
+
return [...blocks].sort(
|
|
201
|
+
(a, b) => a.skill.localeCompare(b.skill) || a.renderOrder - b.renderOrder || a.blockId.localeCompare(b.blockId),
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export function renderCommandRefBlock(skill: CanonicalGjcWorkflowSkill, blockId = "state"): RenderedCommandRefBlock {
|
|
206
|
+
const block = WORKFLOW_COMMAND_REF_BLOCKS.find(item => item.skill === skill && item.blockId === blockId);
|
|
207
|
+
if (block === undefined) throw new Error(`Unknown command-reference block: ${skill}/${blockId}`);
|
|
208
|
+
|
|
209
|
+
const lines: string[] = [];
|
|
210
|
+
lines.push(block.markers.start);
|
|
211
|
+
lines.push(`### Generated command reference: ${block.blockId}`);
|
|
212
|
+
lines.push("");
|
|
213
|
+
for (const note of block.notes) lines.push(note);
|
|
214
|
+
lines.push("");
|
|
215
|
+
lines.push("Commands:");
|
|
216
|
+
for (const command of block.commands.filter(
|
|
217
|
+
item => item.visibility === "public" && item.includeWhen === "implemented-only",
|
|
218
|
+
)) {
|
|
219
|
+
lines.push(`- \`${command.rendered}\``);
|
|
220
|
+
if (command.note !== undefined) lines.push(` - ${command.note}`);
|
|
221
|
+
}
|
|
222
|
+
lines.push("");
|
|
223
|
+
lines.push("Examples:");
|
|
224
|
+
for (const example of block.examples) {
|
|
225
|
+
if (example.label !== undefined) lines.push(`- ${example.label}:`);
|
|
226
|
+
lines.push(example.bytes);
|
|
227
|
+
}
|
|
228
|
+
lines.push("");
|
|
229
|
+
lines.push("Aliases and bridges:");
|
|
230
|
+
for (const bridge of block.aliasesAndBridges) lines.push(`- ${bridge.from} -> ${bridge.to}: \`${bridge.rendered}\``);
|
|
231
|
+
lines.push(block.markers.end);
|
|
232
|
+
lines.push("");
|
|
233
|
+
|
|
234
|
+
return { skill, blockId: block.blockId, markers: block.markers, bytes: lines.join("\n") };
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export function isCanonicalGjcWorkflowSkill(value: string): value is CanonicalGjcWorkflowSkill {
|
|
238
|
+
return (CANONICAL_GJC_WORKFLOW_SKILLS as readonly string[]).includes(value);
|
|
239
|
+
}
|