@gajae-code/coding-agent 0.2.2 → 0.2.4
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 +45 -8600
- package/dist/types/cli/setup-cli.d.ts +1 -0
- package/dist/types/cli/update-cli.d.ts +3 -0
- package/dist/types/commands/deep-interview.d.ts +41 -0
- package/dist/types/commands/setup.d.ts +3 -0
- package/dist/types/config/settings-schema.d.ts +56 -0
- package/dist/types/defaults/gjc-defaults.d.ts +19 -6
- package/dist/types/discovery/helpers.d.ts +2 -0
- package/dist/types/extensibility/extensions/types.d.ts +6 -0
- package/dist/types/gjc-runtime/deep-interview-runtime.d.ts +18 -0
- package/dist/types/hooks/skill-state.d.ts +5 -0
- package/dist/types/memories/index.d.ts +1 -1
- package/dist/types/memory-backend/local-backend.d.ts +3 -3
- package/dist/types/modes/components/hook-selector.d.ts +7 -0
- package/dist/types/modes/components/settings-selector.d.ts +3 -1
- package/dist/types/modes/controllers/selector-controller.d.ts +1 -0
- package/dist/types/modes/interactive-mode.d.ts +1 -0
- package/dist/types/modes/theme/defaults/index.d.ts +126 -0
- package/dist/types/modes/theme/theme.d.ts +5 -0
- package/dist/types/modes/types.d.ts +1 -0
- package/dist/types/modes/utils/context-usage.d.ts +6 -2
- package/dist/types/sdk.d.ts +6 -2
- package/dist/types/session/agent-session.d.ts +45 -1
- package/dist/types/session/session-manager.d.ts +3 -0
- package/dist/types/setup/model-onboarding-guidance.d.ts +1 -0
- package/dist/types/setup/provider-onboarding.d.ts +29 -5
- package/dist/types/skill-state/active-state.d.ts +26 -1
- package/dist/types/skill-state/deep-interview-mutation-guard.d.ts +1 -1
- package/dist/types/skill-state/initial-phase.d.ts +12 -0
- package/dist/types/task/executor.d.ts +2 -0
- package/dist/types/task/types.d.ts +11 -0
- package/dist/types/tools/index.d.ts +20 -1
- package/dist/types/tools/skill.d.ts +47 -0
- package/dist/types/utils/changelog.d.ts +18 -2
- package/package.json +7 -7
- package/src/cli/setup-cli.ts +26 -12
- package/src/cli/update-cli.ts +67 -16
- package/src/cli.ts +1 -0
- package/src/commands/deep-interview.ts +25 -2
- package/src/commands/setup.ts +2 -0
- package/src/commands/state.ts +1 -0
- package/src/config/settings-schema.ts +63 -0
- package/src/defaults/gjc/skills/deep-interview/SKILL.md +58 -5
- package/src/defaults/gjc/skills/deep-interview/auto-answer-uncertain.md +37 -0
- package/src/defaults/gjc/skills/deep-interview/auto-research-greenfield.md +42 -0
- package/src/defaults/gjc/skills/ralplan/SKILL.md +8 -0
- package/src/defaults/gjc/skills/team/SKILL.md +10 -0
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +19 -6
- package/src/defaults/gjc-defaults.ts +68 -16
- package/src/discovery/helpers.ts +24 -1
- package/src/extensibility/extensions/types.ts +6 -0
- package/src/gjc-runtime/deep-interview-runtime.ts +312 -1
- package/src/gjc-runtime/state-runtime.ts +175 -5
- package/src/goals/tools/goal-tool.ts +5 -1
- package/src/hooks/skill-state.ts +8 -6
- package/src/internal-urls/docs-index.generated.ts +6 -4
- package/src/internal-urls/memory-protocol.ts +3 -2
- package/src/main.ts +2 -3
- package/src/memories/index.ts +6 -4
- package/src/memory-backend/local-backend.ts +14 -6
- package/src/modes/components/hook-selector.ts +156 -1
- package/src/modes/components/settings-selector.ts +16 -12
- package/src/modes/controllers/command-controller.ts +3 -4
- package/src/modes/controllers/extension-ui-controller.ts +1 -0
- package/src/modes/controllers/selector-controller.ts +69 -9
- package/src/modes/interactive-mode.ts +14 -1
- package/src/modes/theme/defaults/blue-crab.json +126 -0
- package/src/modes/theme/defaults/index.ts +2 -0
- package/src/modes/theme/theme.ts +40 -1
- package/src/modes/types.ts +1 -0
- package/src/modes/utils/context-usage.ts +66 -17
- package/src/prompts/agents/architect.md +3 -0
- package/src/prompts/agents/executor.md +2 -0
- package/src/prompts/agents/frontmatter.md +1 -0
- package/src/prompts/memories/unavailable.md +9 -0
- package/src/prompts/system/subagent-system-prompt.md +6 -0
- package/src/prompts/tools/skill.md +28 -0
- package/src/prompts/tools/task.md +3 -0
- package/src/sdk.ts +54 -10
- package/src/session/agent-session.ts +204 -21
- package/src/session/session-manager.ts +9 -1
- package/src/setup/model-onboarding-guidance.ts +6 -3
- package/src/setup/provider-onboarding.ts +177 -16
- package/src/skill-state/active-state.ts +150 -25
- package/src/skill-state/deep-interview-mutation-guard.ts +11 -24
- package/src/skill-state/initial-phase.ts +17 -0
- package/src/slash-commands/builtin-registry.ts +62 -14
- package/src/slash-commands/helpers/context-report.ts +123 -13
- package/src/task/agents.ts +1 -0
- package/src/task/executor.ts +9 -1
- package/src/task/index.ts +91 -4
- package/src/task/types.ts +6 -0
- package/src/tools/ask.ts +2 -0
- package/src/tools/index.ts +23 -1
- package/src/tools/skill.ts +153 -0
- package/src/utils/changelog.ts +67 -44
package/src/cli/update-cli.ts
CHANGED
|
@@ -12,7 +12,7 @@ import { $ } from "bun";
|
|
|
12
12
|
import chalk from "chalk";
|
|
13
13
|
import { theme } from "../modes/theme/theme";
|
|
14
14
|
|
|
15
|
-
const
|
|
15
|
+
const RELEASE_REPO = "Yeachan-Heo/gajae-code";
|
|
16
16
|
const PACKAGE = "@gajae-code/coding-agent";
|
|
17
17
|
|
|
18
18
|
interface ReleaseInfo {
|
|
@@ -122,7 +122,7 @@ async function resolveUpdateTarget(): Promise<UpdateTarget> {
|
|
|
122
122
|
|
|
123
123
|
if (bunBinDir) return { method: "bun" };
|
|
124
124
|
|
|
125
|
-
throw new Error(`Could not resolve ${APP_NAME} binary path in PATH`);
|
|
125
|
+
throw new Error(formatUnsupportedTargetMessage(`Could not resolve ${APP_NAME} binary path in PATH`));
|
|
126
126
|
}
|
|
127
127
|
|
|
128
128
|
/**
|
|
@@ -166,10 +166,7 @@ function compareVersions(a: string, b: string): number {
|
|
|
166
166
|
/**
|
|
167
167
|
* Get the appropriate binary name for this platform.
|
|
168
168
|
*/
|
|
169
|
-
function getBinaryName(): string {
|
|
170
|
-
const platform = process.platform;
|
|
171
|
-
const arch = process.arch;
|
|
172
|
-
|
|
169
|
+
function getBinaryName(platform: NodeJS.Platform = process.platform, arch: string = process.arch): string {
|
|
173
170
|
let os: string;
|
|
174
171
|
switch (platform) {
|
|
175
172
|
case "linux":
|
|
@@ -182,7 +179,7 @@ function getBinaryName(): string {
|
|
|
182
179
|
os = "windows";
|
|
183
180
|
break;
|
|
184
181
|
default:
|
|
185
|
-
throw new Error(`Unsupported platform: ${platform}`);
|
|
182
|
+
throw new Error(formatUnsupportedTargetMessage(`Unsupported platform: ${platform}`));
|
|
186
183
|
}
|
|
187
184
|
|
|
188
185
|
let archName: string;
|
|
@@ -194,7 +191,7 @@ function getBinaryName(): string {
|
|
|
194
191
|
archName = "arm64";
|
|
195
192
|
break;
|
|
196
193
|
default:
|
|
197
|
-
throw new Error(`Unsupported architecture: ${arch}`);
|
|
194
|
+
throw new Error(formatUnsupportedTargetMessage(`Unsupported architecture: ${arch}`));
|
|
198
195
|
}
|
|
199
196
|
|
|
200
197
|
if (os === "windows") {
|
|
@@ -233,6 +230,65 @@ function printVerifiedVersion(expectedVersion: string): void {
|
|
|
233
230
|
console.log(chalk.green(`\n${theme.status.success} Updated to ${expectedVersion}`));
|
|
234
231
|
}
|
|
235
232
|
|
|
233
|
+
function formatBinaryInstallInstruction(platform: NodeJS.Platform = process.platform): string {
|
|
234
|
+
if (platform === "win32") {
|
|
235
|
+
return `For a supported binary install, reinstall with PowerShell: irm https://raw.githubusercontent.com/${RELEASE_REPO}/main/scripts/install.ps1 | iex`;
|
|
236
|
+
}
|
|
237
|
+
return `For a supported binary install, reinstall with: curl -fsSL https://raw.githubusercontent.com/${RELEASE_REPO}/main/scripts/install.sh | sh -s -- --binary`;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
function formatManualUpdateInstructions(platform: NodeJS.Platform = process.platform): string {
|
|
241
|
+
return [
|
|
242
|
+
`If ${APP_NAME} was installed with Bun, run: bun install -g ${PACKAGE}@latest`,
|
|
243
|
+
`If ${APP_NAME} was installed with npm, pnpm, or another package manager, update it with that same manager.`,
|
|
244
|
+
formatBinaryInstallInstruction(platform),
|
|
245
|
+
].join("\n");
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
function formatUnsupportedTargetMessage(reason: string, platform: NodeJS.Platform = process.platform): string {
|
|
249
|
+
return `${reason}.\n${formatManualUpdateInstructions(platform)}`;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function buildReleaseBinaryUrl(
|
|
253
|
+
version: string,
|
|
254
|
+
platform: NodeJS.Platform = process.platform,
|
|
255
|
+
arch: string = process.arch,
|
|
256
|
+
): string {
|
|
257
|
+
const binaryName = getBinaryName(platform, arch);
|
|
258
|
+
const tag = `v${version}`;
|
|
259
|
+
return `https://github.com/${RELEASE_REPO}/releases/download/${tag}/${binaryName}`;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
function formatBinaryDownloadFailureMessage(
|
|
263
|
+
binaryName: string,
|
|
264
|
+
url: string,
|
|
265
|
+
status: string | number,
|
|
266
|
+
platform: NodeJS.Platform = process.platform,
|
|
267
|
+
): string {
|
|
268
|
+
return `Download failed for ${binaryName} from ${url}: ${status}.\n${formatManualUpdateInstructions(platform)}`;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
export function formatBinaryDownloadFailureMessageForTest(
|
|
272
|
+
binaryName: string,
|
|
273
|
+
url: string,
|
|
274
|
+
status: string | number,
|
|
275
|
+
platform: NodeJS.Platform = process.platform,
|
|
276
|
+
): string {
|
|
277
|
+
return formatBinaryDownloadFailureMessage(binaryName, url, status, platform);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
export function buildReleaseBinaryUrlForTest(
|
|
281
|
+
version: string,
|
|
282
|
+
platform: NodeJS.Platform = process.platform,
|
|
283
|
+
arch: string = process.arch,
|
|
284
|
+
): string {
|
|
285
|
+
return buildReleaseBinaryUrl(version, platform, arch);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
export function formatManualUpdateInstructionsForTest(platform: NodeJS.Platform = process.platform): string {
|
|
289
|
+
return formatManualUpdateInstructions(platform);
|
|
290
|
+
}
|
|
291
|
+
|
|
236
292
|
function formatVerificationFailure(result: InstalledVersionVerification, expectedVersion: string): string {
|
|
237
293
|
if (result.actual) {
|
|
238
294
|
return `${APP_NAME} at ${result.path} still reports ${result.actual} (expected ${expectedVersion})`;
|
|
@@ -250,11 +306,7 @@ async function printVerification(expectedVersion: string): Promise<void> {
|
|
|
250
306
|
return;
|
|
251
307
|
}
|
|
252
308
|
console.log(chalk.yellow(`\nWarning: ${formatVerificationFailure(result, expectedVersion)}`));
|
|
253
|
-
console.log(
|
|
254
|
-
chalk.yellow(
|
|
255
|
-
`You may need to reinstall: curl -fsSL https://raw.githubusercontent.com/can1357/gajae-code/main/scripts/install.sh | sh`,
|
|
256
|
-
),
|
|
257
|
-
);
|
|
309
|
+
console.log(chalk.yellow(formatManualUpdateInstructions()));
|
|
258
310
|
}
|
|
259
311
|
|
|
260
312
|
async function unlinkIfExists(filePath: string): Promise<void> {
|
|
@@ -314,8 +366,7 @@ async function updateViaBun(expectedVersion: string): Promise<void> {
|
|
|
314
366
|
*/
|
|
315
367
|
async function updateViaBinaryAt(targetPath: string, expectedVersion: string): Promise<void> {
|
|
316
368
|
const binaryName = getBinaryName();
|
|
317
|
-
const
|
|
318
|
-
const url = `https://github.com/${REPO}/releases/download/${tag}/${binaryName}`;
|
|
369
|
+
const url = buildReleaseBinaryUrl(expectedVersion);
|
|
319
370
|
|
|
320
371
|
const tempPath = `${targetPath}.new`;
|
|
321
372
|
const backupPath = `${targetPath}.bak`;
|
|
@@ -323,7 +374,7 @@ async function updateViaBinaryAt(targetPath: string, expectedVersion: string): P
|
|
|
323
374
|
|
|
324
375
|
const response = await fetch(url, { redirect: "follow" });
|
|
325
376
|
if (!response.ok || !response.body) {
|
|
326
|
-
throw new Error(
|
|
377
|
+
throw new Error(formatBinaryDownloadFailureMessage(binaryName, url, response.statusText || response.status));
|
|
327
378
|
}
|
|
328
379
|
const fileStream = fs.createWriteStream(tempPath, { mode: 0o755 });
|
|
329
380
|
await pipeline(response.body, fileStream);
|
package/src/cli.ts
CHANGED
|
@@ -44,6 +44,7 @@ const commands: CommandEntry[] = [
|
|
|
44
44
|
load: () => import("./commands/contribution-prep").then(m => m.default),
|
|
45
45
|
},
|
|
46
46
|
{ name: "deep-interview", load: () => import("./commands/deep-interview").then(m => m.default) },
|
|
47
|
+
{ name: "update", load: () => import("./commands/update").then(m => m.default) },
|
|
47
48
|
{ name: "launch", load: () => import("./commands/launch").then(m => m.default) },
|
|
48
49
|
];
|
|
49
50
|
|
|
@@ -1,10 +1,33 @@
|
|
|
1
|
-
import { Command } from "@gajae-code/utils/cli";
|
|
1
|
+
import { Command, Flags } from "@gajae-code/utils/cli";
|
|
2
2
|
import { runNativeDeepInterviewCommand } from "../gjc-runtime/deep-interview-runtime";
|
|
3
3
|
|
|
4
4
|
export default class DeepInterview extends Command {
|
|
5
5
|
static description = "Run native GJC deep-interview workflow";
|
|
6
6
|
static strict = false;
|
|
7
|
-
static
|
|
7
|
+
static flags = {
|
|
8
|
+
quick: Flags.boolean({ description: "Seed a quick deep-interview run" }),
|
|
9
|
+
standard: Flags.boolean({ description: "Seed a standard deep-interview run" }),
|
|
10
|
+
deep: Flags.boolean({ description: "Seed a deep deep-interview run" }),
|
|
11
|
+
threshold: Flags.string({ description: "Override ambiguity threshold for kickoff" }),
|
|
12
|
+
"threshold-source": Flags.string({ description: "Describe the threshold override source" }),
|
|
13
|
+
"session-id": Flags.string({
|
|
14
|
+
description: "Route state/spec handoff through a session-scoped .gjc state directory",
|
|
15
|
+
}),
|
|
16
|
+
write: Flags.boolean({ description: "Persist a final deep-interview spec through the sanctioned GJC CLI/API" }),
|
|
17
|
+
stage: Flags.string({ description: 'Spec stage for --write (currently "final")' }),
|
|
18
|
+
slug: Flags.string({ description: "Safe slug for .gjc/specs/deep-interview-<slug>.md" }),
|
|
19
|
+
spec: Flags.string({ description: "Final spec markdown or a path to the final spec markdown" }),
|
|
20
|
+
handoff: Flags.string({ description: 'After --write, hand off to a workflow target (currently "ralplan")' }),
|
|
21
|
+
deliberate: Flags.boolean({
|
|
22
|
+
description: "Shortcut for --write handoff to ralplan in deliberate consensus mode",
|
|
23
|
+
}),
|
|
24
|
+
json: Flags.boolean({ description: "Output JSON" }),
|
|
25
|
+
};
|
|
26
|
+
static examples = [
|
|
27
|
+
'$ gjc deep-interview --standard "<idea>"',
|
|
28
|
+
"$ gjc deep-interview --write --stage final --slug my-feature --spec ./final-spec.md",
|
|
29
|
+
"$ gjc deep-interview --write --stage final --slug my-feature --spec ./final-spec.md --deliberate",
|
|
30
|
+
];
|
|
8
31
|
|
|
9
32
|
async run(): Promise<void> {
|
|
10
33
|
const result = await runNativeDeepInterviewCommand(this.argv, process.cwd());
|
package/src/commands/setup.ts
CHANGED
|
@@ -22,6 +22,7 @@ export default class Setup extends Command {
|
|
|
22
22
|
check: Flags.boolean({ char: "c", description: "Check if dependencies are installed" }),
|
|
23
23
|
force: Flags.boolean({ char: "f", description: "Overwrite existing default workflow skill files" }),
|
|
24
24
|
json: Flags.boolean({ description: "Output status as JSON" }),
|
|
25
|
+
preset: Flags.string({ description: "Provider preset: minimax, minimax-cn, or glm" }),
|
|
25
26
|
compat: Flags.string({ description: "Provider compatibility: openai or anthropic" }),
|
|
26
27
|
provider: Flags.string({ description: "Provider id to add to models.yml" }),
|
|
27
28
|
"base-url": Flags.string({ description: "Provider API base URL" }),
|
|
@@ -38,6 +39,7 @@ export default class Setup extends Command {
|
|
|
38
39
|
json: flags.json,
|
|
39
40
|
check: flags.check,
|
|
40
41
|
force: flags.force,
|
|
42
|
+
preset: flags.preset,
|
|
41
43
|
compat: flags.compat,
|
|
42
44
|
provider: flags.provider,
|
|
43
45
|
baseUrl: flags["base-url"],
|
package/src/commands/state.ts
CHANGED
|
@@ -11,6 +11,7 @@ export default class State extends Command {
|
|
|
11
11
|
"$ gjc state deep-interview read --json",
|
|
12
12
|
'$ gjc state ralplan write --input \'{"phase":"approval","active":true}\' --json',
|
|
13
13
|
"$ gjc state team contract",
|
|
14
|
+
"$ gjc state deep-interview handoff --to ralplan --json",
|
|
14
15
|
];
|
|
15
16
|
|
|
16
17
|
async run(): Promise<void> {
|
|
@@ -843,6 +843,26 @@ export const SETTINGS_SCHEMA = {
|
|
|
843
843
|
"Maximum wait between retries, in ms. When the provider asks us to wait longer than this and no credential or model fallback succeeds, the request fails fast instead of sleeping (e.g. 3-hour Anthropic rate-limit windows).",
|
|
844
844
|
},
|
|
845
845
|
},
|
|
846
|
+
"retry.requestMaxRetries": {
|
|
847
|
+
type: "number",
|
|
848
|
+
default: 5,
|
|
849
|
+
ui: {
|
|
850
|
+
tab: "model",
|
|
851
|
+
label: "Provider Request Retries",
|
|
852
|
+
description:
|
|
853
|
+
"Maximum provider request retries before a stream is established. Counts retries, not the first attempt. Set to 0 to disable provider request retries.",
|
|
854
|
+
},
|
|
855
|
+
},
|
|
856
|
+
"retry.streamMaxRetries": {
|
|
857
|
+
type: "number",
|
|
858
|
+
default: 5,
|
|
859
|
+
ui: {
|
|
860
|
+
tab: "model",
|
|
861
|
+
label: "Provider Stream Retries",
|
|
862
|
+
description:
|
|
863
|
+
"Maximum provider stream replay retries for replay-safe transient stream failures. Counts retries, not the first attempt. Set to 0 to disable provider stream retries.",
|
|
864
|
+
},
|
|
865
|
+
},
|
|
846
866
|
"retry.fallbackChains": { type: "record", default: {} as Record<string, string[]> },
|
|
847
867
|
"retry.fallbackRevertPolicy": {
|
|
848
868
|
type: "enum",
|
|
@@ -1940,6 +1960,16 @@ export const SETTINGS_SCHEMA = {
|
|
|
1940
1960
|
},
|
|
1941
1961
|
},
|
|
1942
1962
|
|
|
1963
|
+
"skill.enabled": {
|
|
1964
|
+
type: "boolean",
|
|
1965
|
+
default: true,
|
|
1966
|
+
ui: {
|
|
1967
|
+
tab: "tools",
|
|
1968
|
+
label: "Skill",
|
|
1969
|
+
description: "Enable the skill tool so the agent can chain into another available skill on its next turn",
|
|
1970
|
+
},
|
|
1971
|
+
},
|
|
1972
|
+
|
|
1943
1973
|
// Fetching and browser
|
|
1944
1974
|
"fetch.enabled": {
|
|
1945
1975
|
type: "boolean",
|
|
@@ -2344,6 +2374,37 @@ export const SETTINGS_SCHEMA = {
|
|
|
2344
2374
|
},
|
|
2345
2375
|
},
|
|
2346
2376
|
|
|
2377
|
+
"task.forkContext.enabled": {
|
|
2378
|
+
type: "boolean",
|
|
2379
|
+
default: false,
|
|
2380
|
+
ui: {
|
|
2381
|
+
tab: "tasks",
|
|
2382
|
+
label: "Fork Context for Subagents",
|
|
2383
|
+
description:
|
|
2384
|
+
"Allow explicitly opted-in subagents to start from a sanitized snapshot of parent context when both the agent and task item also opt in.",
|
|
2385
|
+
},
|
|
2386
|
+
},
|
|
2387
|
+
|
|
2388
|
+
"task.forkContext.maxMessages": {
|
|
2389
|
+
type: "number",
|
|
2390
|
+
default: 50,
|
|
2391
|
+
ui: {
|
|
2392
|
+
tab: "tasks",
|
|
2393
|
+
label: "Fork Context Max Messages",
|
|
2394
|
+
description: "Maximum parent messages copied into an explicitly opted-in subagent fork-context seed.",
|
|
2395
|
+
},
|
|
2396
|
+
},
|
|
2397
|
+
|
|
2398
|
+
"task.forkContext.maxTokens": {
|
|
2399
|
+
type: "number",
|
|
2400
|
+
default: 0,
|
|
2401
|
+
ui: {
|
|
2402
|
+
tab: "tasks",
|
|
2403
|
+
label: "Fork Context Max Tokens",
|
|
2404
|
+
description: "Approximate token cap for fork-context seeds. 0 uses 25% of the target model context window.",
|
|
2405
|
+
},
|
|
2406
|
+
},
|
|
2407
|
+
|
|
2347
2408
|
"task.maxRecursionDepth": {
|
|
2348
2409
|
type: "number",
|
|
2349
2410
|
default: 2,
|
|
@@ -2792,6 +2853,8 @@ export interface RetrySettings {
|
|
|
2792
2853
|
maxRetries: number;
|
|
2793
2854
|
baseDelayMs: number;
|
|
2794
2855
|
maxDelayMs: number;
|
|
2856
|
+
requestMaxRetries: number;
|
|
2857
|
+
streamMaxRetries: number;
|
|
2795
2858
|
}
|
|
2796
2859
|
|
|
2797
2860
|
export interface MemoriesSettings {
|
|
@@ -39,6 +39,7 @@ Inspired by the [Ouroboros project](https://github.com/Q00/ouroboros) which demo
|
|
|
39
39
|
|
|
40
40
|
<Execution_Policy>
|
|
41
41
|
- Ask ONE question at a time -- never batch multiple questions
|
|
42
|
+
- Preserve the user/session language for every user-facing announcement, topology confirmation, option label, and interview question when state includes `language.instruction`; for example Korean initial ideas must receive Korean deep-interview questions unless the user explicitly requests another language
|
|
42
43
|
- Target the WEAKEST clarity dimension with each question
|
|
43
44
|
- Before Round 1 ambiguity scoring, run a one-time Round 0 topology enumeration gate that confirms the top-level component list and locks it into state
|
|
44
45
|
- Make weakest-dimension targeting explicit every round: name the weakest dimension, state its score/gap, and explain why the next question is aimed there
|
|
@@ -54,6 +55,15 @@ Inspired by the [Ouroboros project](https://github.com/Q00/ouroboros) which demo
|
|
|
54
55
|
- Challenge agents activate at specific round thresholds to shift perspective
|
|
55
56
|
</Execution_Policy>
|
|
56
57
|
|
|
58
|
+
<Internal_Auto_Mode_Protocol>
|
|
59
|
+
- `auto-research-greenfield.md` and `auto-answer-uncertain.md` are internal prompt fragments loaded on demand with bundle metadata `kind: "skill-fragment"`; they are not public skills, are never slash-command/discoverable, and must not be registered through any `skill://` route.
|
|
60
|
+
- Load fragments only for the specific hook that needs them, with forked inherited context kept read-only and prompt-budgeted; summarize active interview context before spawning the architect if the payload is large.
|
|
61
|
+
- Auto-mode architects are read-only: no code edits, no `.gjc/` mutation, no workflow chaining, no formatters, and no execution delegation.
|
|
62
|
+
- Validate every fragment response before using it: required sections must be present, candidates/answer must match the requested shape, rationale must cite available context, confidence must be explicit, and insufficient-context fallbacks must be honored.
|
|
63
|
+
- If architect spawn, fragment loading, or response validation fails, continue the normal manual interview path silently and record an internal audit note in state by incrementing `architect_failures`; do not expose tool noise to the user unless it changes the next user-facing question.
|
|
64
|
+
- Track `auto_researched_rounds`, `auto_answered_rounds`, and `architect_failures` in state and final spec metadata.
|
|
65
|
+
</Internal_Auto_Mode_Protocol>
|
|
66
|
+
|
|
57
67
|
|
|
58
68
|
|
|
59
69
|
<Steps>
|
|
@@ -83,6 +93,7 @@ Deep Interview threshold: <resolvedThresholdPercent> (source: <resolvedThreshold
|
|
|
83
93
|
- Substitute `<resolvedThreshold>`, `<resolvedThresholdPercent>`, and `<resolvedThresholdSource>` throughout the remaining instructions before continuing.
|
|
84
94
|
- Include `threshold_source` in the first `gjc state write` payload and preserve it on later state updates; do not edit `.gjc/state` files directly unless an explicit force override is active.
|
|
85
95
|
- Include both threshold and source in the final spec metadata.
|
|
96
|
+
- Read any `language` object from active deep-interview state and carry `language.instruction` forward mechanically. If absent, infer the user/session language from `{{ARGUMENTS}}` only when it is obvious. Do not surprise a Korean session with English questions.
|
|
86
97
|
|
|
87
98
|
## Phase 1: Initialize
|
|
88
99
|
|
|
@@ -133,7 +144,10 @@ Deep Interview threshold: <resolvedThresholdPercent> (source: <resolvedThreshold
|
|
|
133
144
|
"last_targeted_component_id": null
|
|
134
145
|
},
|
|
135
146
|
"challenge_modes_used": [],
|
|
136
|
-
"ontology_snapshots": []
|
|
147
|
+
"ontology_snapshots": [],
|
|
148
|
+
"auto_researched_rounds": [],
|
|
149
|
+
"auto_answered_rounds": [],
|
|
150
|
+
"architect_failures": 0
|
|
137
151
|
}
|
|
138
152
|
}
|
|
139
153
|
```
|
|
@@ -170,7 +184,7 @@ I'm reading this as {N} top-level component(s):
|
|
|
170
184
|
Is that topology right? Should any component be added, removed, merged, split, or explicitly deferred?
|
|
171
185
|
```
|
|
172
186
|
|
|
173
|
-
Options should include contextually relevant choices such as **Looks right**, **Add/remove/merge components**, **Defer one or more components**, plus free-text. This is the only pre-scoring question and preserves the one-question-per-round rule.
|
|
187
|
+
Options should include contextually relevant choices such as **Looks right**, **Add/remove/merge components**, **Defer one or more components**, plus free-text, translated/localized according to `language.instruction` when present. This is the only pre-scoring question and preserves the one-question-per-round rule.
|
|
174
188
|
|
|
175
189
|
3. **Lock topology into state** after the answer. Store a normalized component list and confirmation timestamp:
|
|
176
190
|
|
|
@@ -246,9 +260,15 @@ If any prompt input is too large, summarize it first and then continue from the
|
|
|
246
260
|
| Context Clarity (brownfield) | "How does this fit?" | "I found JWT auth middleware in `src/auth/` (pattern: passport + JWT). Should this feature extend that path or intentionally diverge from it?" |
|
|
247
261
|
| Scope-fuzzy / ontology stress | "What IS the core thing here?" | "You have named Tasks, Projects, and Workspaces across the last rounds. Which one is the core entity, and which are supporting views or containers?" |
|
|
248
262
|
|
|
263
|
+
### Step 2a′: Auto-Research Greenfield Questions
|
|
264
|
+
|
|
265
|
+
When the next question is for a greenfield interview and is tagged `research: true`, load `auto-research-greenfield.md` as an internal `kind: "skill-fragment"` prompt for a fork-context architect before Step 2b. Pass only the tagged question, locked topology summary, prompt-safe initial idea, trimmed prior decisions/gaps, and relevant constraints. The architect must return 2-3 ranked candidates with rationale, confidence, and fallback notes. Validate the shape before use; if valid, incorporate the candidates as concise answer options or context for the single user-facing question and append the round number to `auto_researched_rounds`. If invalid or unavailable, fall back silently to the normal generated question and increment `architect_failures`.
|
|
266
|
+
|
|
267
|
+
Auto-research must never add a public skill entrypoint, never be slash-command/discoverable, never register a `skill://` handler, and never alter the one-question-per-round rule.
|
|
268
|
+
|
|
249
269
|
### Step 2b: Ask the Question
|
|
250
270
|
|
|
251
|
-
Use the `ask` tool with the generated question. Present it clearly with the current ambiguity context:
|
|
271
|
+
Use the `ask` tool with the generated question. Before rendering the prompt/options, apply `language.instruction` from state when present so the entire user-facing question remains in the preserved session language. Present it clearly with the current ambiguity context:
|
|
252
272
|
|
|
253
273
|
```
|
|
254
274
|
Round {n} | Component: {target_component_name} | Targeting: {weakest_dimension} | Why now: {one_sentence_targeting_rationale} | Ambiguity: {score}%
|
|
@@ -258,10 +278,18 @@ Round {n} | Component: {target_component_name} | Targeting: {weakest_dimension}
|
|
|
258
278
|
|
|
259
279
|
Options should include contextually relevant choices plus free-text.
|
|
260
280
|
|
|
281
|
+
### Step 2b′: Auto-Answer Opted-Out Questions
|
|
282
|
+
|
|
283
|
+
After the `ask` tool resolves and before ambiguity scoring, if the user opts out of answering the current question or explicitly asks the agent to decide, load `auto-answer-uncertain.md` as an internal `kind: "skill-fragment"` prompt for a fork-context architect. Pass the opted-out question, prompt-safe transcript summary, locked topology, current scores/gaps, and any auto-research candidates used for the round. The architect must return exactly one decisive answer with rationale, confidence, and explicit uncertainty. Validate the response shape before using it; if valid, record it as the tentative answer for scoring, append the round number to `auto_answered_rounds`, and mark the transcript answer as architect-assisted.
|
|
284
|
+
|
|
285
|
+
Auto-answer has a clarity cap: unless the architect confidence is `high` and uncertainty is negligible, no dimension score improved solely by the auto-answer may exceed `0.85`. If the auto-answer would make ambiguity cross the resolved threshold, ask the user for threshold-crossing confirmation before Phase 4: present the tentative assumption and require explicit confirmation, revision, or continued questioning. On architect failure or invalid response, continue with the user's opt-out as an unresolved gap, increment `architect_failures`, and do not block the interview.
|
|
286
|
+
|
|
261
287
|
### Step 2c: Score Ambiguity
|
|
262
288
|
|
|
263
289
|
After receiving the user's answer, score clarity across all dimensions.
|
|
264
290
|
|
|
291
|
+
If the round used an auto-answer, include the architect answer, rationale, confidence, and uncertainty in the scoring prompt. Apply the Step 2b′ clarity cap mechanically before calculating ambiguity, and treat any low-confidence or insufficient-context auto-answer as an unresolved gap rather than user-confirmed truth.
|
|
292
|
+
|
|
265
293
|
**Scoring prompt** (use opus model, temperature 0.1 for consistency):
|
|
266
294
|
|
|
267
295
|
```
|
|
@@ -355,7 +383,7 @@ Round {n} complete.
|
|
|
355
383
|
|
|
356
384
|
### Step 2e: Update State
|
|
357
385
|
|
|
358
|
-
Update interview state with the new round, global scores, per-component `topology.components[].clarity_scores`, `topology.components[].weakest_dimension`, ontology snapshot,
|
|
386
|
+
Update interview state with the new round, global scores, per-component `topology.components[].clarity_scores`, `topology.components[].weakest_dimension`, ontology snapshot, `topology.last_targeted_component_id`, `auto_researched_rounds`, `auto_answered_rounds`, and `architect_failures` via `gjc state write`; never patch `.gjc/state` directly unless an explicit force override is active.
|
|
359
387
|
|
|
360
388
|
### Step 2f: Check Soft Limits
|
|
361
389
|
|
|
@@ -389,8 +417,9 @@ When ambiguity ≤ threshold (or hard cap / early exit):
|
|
|
389
417
|
1. **Generate the specification** using opus model with the prompt-safe transcript. If the full interview transcript or initial context is too large, include the summary plus all concrete decisions, acceptance criteria, unresolved gaps, and ontology snapshots; never overflow the prompt with raw oversized context.
|
|
390
418
|
2. **Write the final spec through the workflow CLI**: persist the artifact at `.gjc/specs/deep-interview-{slug}.md`
|
|
391
419
|
- Always use this exact final spec path. Do not write temporary working files to the repo root or other ad hoc paths; repos may allowlist `.gjc/` for planning artifacts while protecting product branches.
|
|
392
|
-
- Use the
|
|
420
|
+
- Use the native deep-interview write command with `--write --stage final --slug {slug} --spec <markdown-or-path> [--json]` for artifact and state persistence; direct `.gjc/` file edits are forbidden unless an explicit force override is active.
|
|
393
421
|
- Persist the final `spec_path` in state when available so downstream skills and resumed sessions can pass the artifact path explicitly.
|
|
422
|
+
- If the user preselected the deliberate ralplan path, use the native deep-interview write command with `--write --stage final --slug {slug} --spec <markdown-or-path> --deliberate [--json]` so the final spec is persisted before deep-interview hands off to ralplan.
|
|
394
423
|
|
|
395
424
|
Spec structure:
|
|
396
425
|
|
|
@@ -407,6 +436,9 @@ Spec structure:
|
|
|
407
436
|
- Threshold Source: <resolvedThresholdSource>
|
|
408
437
|
- Initial Context Summarized: {yes|no}
|
|
409
438
|
- Status: {PASSED | BELOW_THRESHOLD_EARLY_EXIT}
|
|
439
|
+
- Auto-Researched Rounds: {auto_researched_rounds}
|
|
440
|
+
- Auto-Answered Rounds: {auto_answered_rounds}
|
|
441
|
+
- Architect Failures: {architect_failures}
|
|
410
442
|
|
|
411
443
|
## Clarity Breakdown
|
|
412
444
|
| Dimension | Score | Weight | Weighted |
|
|
@@ -515,6 +547,23 @@ After the spec is written, mark it `pending approval` and present execution opti
|
|
|
515
547
|
|
|
516
548
|
**IMPORTANT:** On explicit execution selection, **MUST** use the chosen bundled GJC workflow skill entrypoint (`/skill:ralplan` or `/skill:team`) inside the agent session. `gjc ralplan` is a native CLI that accepts the documented skill flags and seeds local `.gjc/state` receipts; agent sessions should still drive the consensus loop through `/skill:ralplan`. `gjc team` is a native tmux runtime command and may be used only when the Team workflow explicitly requires the CLI runtime. Do NOT implement directly. The deep-interview agent is a requirements agent, not an execution agent. If oversized initial context was summarized, pass the spec and prompt-safe summary forward, not the raw oversized source material. Without explicit execution selection, stop with the spec marked `pending approval`.
|
|
517
549
|
|
|
550
|
+
### Phase 5b: Handoff before chain
|
|
551
|
+
|
|
552
|
+
Before invoking `/skill:ralplan`, `/skill:team`, or `/skill:ultragoal`, the final spec must already be persisted through the native deep-interview write command. For ordinary user-selected handoff, mark deep-interview ready for the skill tool's chain guard:
|
|
553
|
+
|
|
554
|
+
```
|
|
555
|
+
gjc state deep-interview write --input '{"current_phase":"handoff"}' --json
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
For a preselected deliberate ralplan path, prefer the single sanctioned bridge command instead:
|
|
559
|
+
|
|
560
|
+
```
|
|
561
|
+
gjc \
|
|
562
|
+
deep-interview --write --stage final --slug {slug} --spec <markdown-or-path> --deliberate --json
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
That command persists `.gjc/specs/deep-interview-{slug}.md`, seeds ralplan in deliberate mode, and performs the safe deep-interview → ralplan state handoff. Skipping spec persistence leaves the Phase 5 chain blocked by design.
|
|
566
|
+
|
|
518
567
|
### Approval-Gated Refinement Path (Recommended)
|
|
519
568
|
|
|
520
569
|
```
|
|
@@ -551,6 +600,8 @@ Skipping any stage is possible but reduces quality assurance:
|
|
|
551
600
|
- Use the GJC workflow CLI to save the final spec at `.gjc/specs/deep-interview-{slug}.md` exactly; do not use `write`, `edit`, or `ast_edit` directly on `.gjc/` paths without force override.
|
|
552
601
|
- Use public GJC workflow entrypoints to bridge to ralplan/team only after explicit execution approval — never implement directly
|
|
553
602
|
- Challenge agent modes are prompt injections, not separate agent spawns
|
|
603
|
+
- Use internal fragment auto-modes only at their documented hooks: `auto-research-greenfield.md` between Step 2a and 2b for greenfield `research: true` questions, and `auto-answer-uncertain.md` as Step 2b′ after `ask` resolves and before scoring.
|
|
604
|
+
- Fragment auto-modes are loaded on demand as `kind: "skill-fragment"`; they are not public workflow skills, not slash-command/discoverable, and not `skill://` registrations.
|
|
554
605
|
</Tool_Usage>
|
|
555
606
|
|
|
556
607
|
<Examples>
|
|
@@ -685,6 +736,8 @@ Why bad: 45% ambiguity means nearly half the requirements are unclear. The mathe
|
|
|
685
736
|
- [ ] Multi-component interviews rotate targeting across active components when N > 1
|
|
686
737
|
- [ ] Spec includes Topology section with confirmed active components and user-confirmed deferrals
|
|
687
738
|
- [ ] Spec includes Ontology (Key Entities) table and Ontology Convergence section
|
|
739
|
+
- [ ] Internal auto-mode fragments, when used, were loaded only on demand as non-public `kind: "skill-fragment"` prompts; responses were validated, failures incremented `architect_failures`, and final metadata includes `auto_researched_rounds`, `auto_answered_rounds`, and `architect_failures`
|
|
740
|
+
- [ ] Auto-answer threshold crossing, if any, received explicit user confirmation before spec crystallization
|
|
688
741
|
</Final_Checklist>
|
|
689
742
|
|
|
690
743
|
<Advanced>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Deep Interview Auto Answer: Uncertain User Opt-Out
|
|
2
|
+
|
|
3
|
+
You are a read-only architect helping the deep-interview workflow resolve one question after the user opted out, answered with uncertainty, or explicitly asked the agent to decide.
|
|
4
|
+
|
|
5
|
+
Inherited context is read-only background. Do not edit code, write files, mutate `.gjc/` state, run formatters, invoke workflow handoffs, or implement anything. Use only inherited context, the opted-out question, prior interview decisions, topology/ontology notes, confirmed constraints, and read-only repo/context inspection if available.
|
|
6
|
+
|
|
7
|
+
Keep the response compact enough to fit into ambiguity scoring.
|
|
8
|
+
|
|
9
|
+
## Task
|
|
10
|
+
|
|
11
|
+
Provide one decisive answer the parent workflow can tentatively carry forward. Choose the most conservative answer that preserves user intent, avoids irreversible assumptions, and keeps the interview moving.
|
|
12
|
+
|
|
13
|
+
## Response Shape
|
|
14
|
+
|
|
15
|
+
Respond with only this JSON object:
|
|
16
|
+
|
|
17
|
+
```json
|
|
18
|
+
{
|
|
19
|
+
"status": "answered",
|
|
20
|
+
"answer": "One concise decisive answer phrased as the assumption Deep Interview should carry.",
|
|
21
|
+
"rationale": [
|
|
22
|
+
"Context or repo fact supporting the answer."
|
|
23
|
+
],
|
|
24
|
+
"confidence": "high|medium|low",
|
|
25
|
+
"uncertainty": "Explicit remaining uncertainty, or null if negligible."
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Rules:
|
|
30
|
+
- `answer` must be non-empty and must not contradict confirmed user constraints.
|
|
31
|
+
- `rationale` must contain 2-4 bullets citing inherited context, confirmed constraints, or repo facts available in the prompt.
|
|
32
|
+
- `confidence` must be `high`, `medium`, or `low`.
|
|
33
|
+
- Use `uncertainty` whenever context is thin, ambiguous, or depends on a product choice the transcript has not settled.
|
|
34
|
+
|
|
35
|
+
## Fallback
|
|
36
|
+
|
|
37
|
+
If inherited context is insufficient for a defensible decisive answer, do not guess. Return the safest reversible default if one exists, mark confidence `low`, set `uncertainty` to `Insufficient context for a reliable answer: <missing decision or evidence>`, and clearly identify what the user must confirm before execution approval.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Deep Interview Auto Research: Greenfield
|
|
2
|
+
|
|
3
|
+
You are a read-only architect helping the deep-interview workflow evaluate one greenfield question tagged `research: true`.
|
|
4
|
+
|
|
5
|
+
Inherited context is read-only background. Do not edit code, write files, mutate `.gjc/` state, run formatters, invoke workflow handoffs, or implement anything. Use only inherited context, the tagged question, prior interview decisions, topology/ontology notes, confirmed constraints, and read-only repo/context inspection if available.
|
|
6
|
+
|
|
7
|
+
Keep the response compact enough to fit back into the parent interview prompt.
|
|
8
|
+
|
|
9
|
+
## Task
|
|
10
|
+
|
|
11
|
+
Return 2-3 ranked candidate answers for the tagged greenfield question. Candidates must be concrete, mutually distinct, consistent with confirmed constraints, and useful as answer options or context for the next single Socratic question.
|
|
12
|
+
|
|
13
|
+
## Response Shape
|
|
14
|
+
|
|
15
|
+
Respond with only this JSON object:
|
|
16
|
+
|
|
17
|
+
```json
|
|
18
|
+
{
|
|
19
|
+
"status": "answered",
|
|
20
|
+
"candidates": [
|
|
21
|
+
{
|
|
22
|
+
"rank": 1,
|
|
23
|
+
"answer": "Concise candidate answer.",
|
|
24
|
+
"rationale": "Why this candidate fits the inherited context and confirmed constraints.",
|
|
25
|
+
"risks_or_tradeoffs": "Main risk, tradeoff, or caveat for this candidate.",
|
|
26
|
+
"confidence": "high|medium|low"
|
|
27
|
+
}
|
|
28
|
+
],
|
|
29
|
+
"recommendation": "One sentence naming the strongest candidate and why it should be offered first.",
|
|
30
|
+
"follow_up_gap": "One sentence naming the remaining uncertainty the user should still confirm."
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Rules:
|
|
35
|
+
- `candidates` must contain 2 or 3 entries when context supports that many.
|
|
36
|
+
- `rank` starts at 1 and increases by 1.
|
|
37
|
+
- `confidence` must be `high`, `medium`, or `low`.
|
|
38
|
+
- Every rationale must cite inherited context, confirmed constraints, or repo facts available in the prompt.
|
|
39
|
+
|
|
40
|
+
## Fallback
|
|
41
|
+
|
|
42
|
+
If inherited context is insufficient to produce at least two meaningful candidates, say so explicitly in `follow_up_gap`, return the best single defensible candidate only if one exists, mark confidence `low`, and name the missing context. Do not fabricate certainty.
|
|
@@ -72,6 +72,14 @@ The consensus workflow:
|
|
|
72
72
|
7. *(--interactive only)* User chooses: Approve team execution, Request changes, or Reject
|
|
73
73
|
8. *(--interactive only)* On approval: invoke `/skill:team` for execution -- never implement directly
|
|
74
74
|
|
|
75
|
+
Before invoking `/skill:team` or `/skill:ultragoal`, mark ralplan ready for handoff so the skill tool's chain guard permits the transition:
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
gjc state ralplan write --input '{"current_phase":"handoff"}' --json
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
The skill tool then dispatches the execution skill same-turn and runs `gjc state ralplan handoff --to <team|ultragoal> --json` in-process to atomically demote ralplan, promote the callee, and sync both `skill-active-state.json` files. You do not need to run the handoff verb yourself.
|
|
82
|
+
|
|
75
83
|
> **Important:** Steps 3 and 4 MUST run sequentially. Do NOT issue both agent Task calls in the same parallel batch. Always await the Architect result before issuing the Critic Task.
|
|
76
84
|
|
|
77
85
|
Follow the Plan skill's full documentation for consensus mode details.
|
|
@@ -394,3 +394,13 @@ Two cleanup paths exist and must not be confused:
|
|
|
394
394
|
**Good:** The user changes only the output shape or downstream delivery step (for example `make a PR`). Preserve earlier non-conflicting workflow constraints and apply the update locally.
|
|
395
395
|
|
|
396
396
|
**Bad:** The user says `continue`, and the workflow restarts discovery or stops before the missing verification/evidence is gathered.
|
|
397
|
+
|
|
398
|
+
## Handoff back to planning or persistence
|
|
399
|
+
|
|
400
|
+
When the team task-set completes OR the user requests return to planning/persistence, mark team ready for handoff so the skill tool's chain guard permits the transition:
|
|
401
|
+
|
|
402
|
+
```
|
|
403
|
+
gjc state team write --input '{"current_phase":"handoff"}' --json
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
The skill tool then dispatches `/skill:ralplan`, `/skill:deep-interview`, or `/skill:ultragoal` same-turn and runs `gjc state team handoff --to <ralplan|deep-interview|ultragoal> --json` in-process to atomically demote team, promote the callee, and sync both `skill-active-state.json` files. You do not need to run the handoff verb yourself.
|
|
@@ -11,7 +11,7 @@ Use when the user asks for `ultragoal`, `create-goals`, `complete-goals`, durabl
|
|
|
11
11
|
|
|
12
12
|
## Purpose
|
|
13
13
|
|
|
14
|
-
`ultragoal` turns a brief into repo-native artifacts and then drives a GJC goal safely through the unified `goal` tool. New plans default to a stable pointer-style aggregate GJC goal for the whole durable plan in `.gjc/ultragoal/goals.json`, including later accepted/appended stories under the original brief constraints, while GJC tracks G001/G002 story progress in the ledger. Ultragoal does not
|
|
14
|
+
`ultragoal` turns a brief into repo-native artifacts and then drives a GJC goal safely through the unified `goal` tool. New plans default to a stable pointer-style aggregate GJC goal for the whole durable plan in `.gjc/ultragoal/goals.json`, including later accepted/appended stories under the original brief constraints, while GJC tracks G001/G002 story progress in the ledger. Ultragoal does not require any `/goal` slash-command between runs. For back-to-back ultragoal runs in one session/thread, call `goal({"op":"drop"})` only when `goal({"op":"get"})` still reports an active aggregate; then call `goal({"op":"create"})`. The goal tool stays armed across drop so the next create works in-session, and no slash-command cleanup exists or is required.
|
|
15
15
|
|
|
16
16
|
- `.gjc/ultragoal/brief.md`
|
|
17
17
|
- `.gjc/ultragoal/goals.json`
|
|
@@ -41,9 +41,12 @@ Use these exact goal-tool calls for the inline goal state:
|
|
|
41
41
|
goal({"op":"get"})
|
|
42
42
|
goal({"op":"create","objective":"<printed aggregate or per-story objective>"})
|
|
43
43
|
goal({"op":"complete"})
|
|
44
|
+
goal({"op":"drop"})
|
|
45
|
+
goal({"op":"resume"})
|
|
44
46
|
```
|
|
47
|
+
`drop` clears the active goal without exiting goal mode; `resume` reactivates a paused goal.
|
|
45
48
|
|
|
46
|
-
|
|
49
|
+
Use `goal({"op":"get"})` snapshots inside Ultragoal for ledger reconciliation. The unified `goal` tool is the only agent-facing surface for goal state; no `/goal` subcommand is required.
|
|
47
50
|
|
|
48
51
|
## Create goals
|
|
49
52
|
|
|
@@ -61,7 +64,7 @@ Loop until `gjc ultragoal status` reports all goals complete:
|
|
|
61
64
|
1. Run `gjc ultragoal complete-goals`.
|
|
62
65
|
2. Read the printed handoff.
|
|
63
66
|
3. Call `goal({"op":"get"})`.
|
|
64
|
-
4. If no active GJC goal exists, call `goal({"op":"create","objective":"<printed payload objective>"})` with the printed payload. In aggregate mode, if the same aggregate objective is already active, continue the current GJC story without creating a new GJC goal.
|
|
67
|
+
4. If no active GJC goal exists, call `goal({"op":"create","objective":"<printed payload objective>"})` with the printed payload. In aggregate mode, if the same aggregate objective is already active, continue the current GJC story without creating a new GJC goal. If `goal({"op":"get"})` shows a stale dropped goal (status `"dropped"`) and a new aggregate must start, no extra cleanup is needed — `goal({"op":"create"})` succeeds directly. If a previous aggregate is still active and you genuinely need a fresh start in the same session, call `goal({"op":"drop"})` first, then `goal({"op":"create"})`.
|
|
65
68
|
5. Complete the current GJC story only.
|
|
66
69
|
6. Run a completion audit against the story objective and real artifacts/tests.
|
|
67
70
|
7. Before any `--status complete` checkpoint, run the mandatory final cleanup/review gate below. In aggregate mode, do **not** call `goal({"op":"complete"})` for intermediate stories; checkpoint each story with a fresh `goal({"op":"get"})` snapshot whose aggregate objective is still `active`. On the final story, use the same fresh active snapshot to create the final aggregate receipt first; only after that receipt exists may `goal({"op":"complete"})` run.
|
|
@@ -192,11 +195,21 @@ Receipts are freshness-scoped:
|
|
|
192
195
|
- Normal later `goal_started` or clean receipt-backed `goal_checkpointed` events for other goals do not stale older per-goal receipts.
|
|
193
196
|
- Appending required goals or changing final required-goal state stales final aggregate receipts. Final aggregate completion requires a fresh final aggregate receipt proving no incomplete, blocked, or `review_blocked` required goals remain.
|
|
194
197
|
|
|
198
|
+
## Handoff back to planning
|
|
199
|
+
|
|
200
|
+
When the aggregate ultragoal is complete OR the user requests return to planning/clarification, mark ultragoal ready for handoff so the skill tool's chain guard permits the backward transition:
|
|
201
|
+
|
|
202
|
+
```
|
|
203
|
+
gjc state ultragoal write --input '{"current_phase":"handoff"}' --json
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
The skill tool then dispatches `/skill:ralplan` or `/skill:deep-interview` same-turn and runs `gjc state ultragoal handoff --to <ralplan|deep-interview> --json` in-process to atomically demote ultragoal, promote the callee, and sync both `skill-active-state.json` files. You do not need to run the handoff verb yourself.
|
|
207
|
+
|
|
195
208
|
## Constraints
|
|
196
209
|
|
|
197
|
-
- The shell command
|
|
198
|
-
-
|
|
199
|
-
-
|
|
210
|
+
- The shell command emits a model-facing handoff for the active GJC agent; it does not invoke any `/goal` slash-command and the agent loop must not depend on any `/goal` subcommand.
|
|
211
|
+
- Use only the unified goal-tool surface from the agent loop: `goal({"op":"get"})`, `goal({"op":"create"})`, `goal({"op":"complete"})`, `goal({"op":"drop"})`, `goal({"op":"resume"})`. `drop` clears the active goal without exiting goal mode so the next `goal({"op":"create"})` works in-session. No slash-command cleanup exists or is required; Ultragoal never calls any `/goal` subcommand.
|
|
212
|
+
- For back-to-back ultragoal runs in the same session/thread, when `goal({"op":"get"})` still reports an active aggregate, call `goal({"op":"drop"})` before `goal({"op":"create"})`; when no active goal exists or the prior aggregate is already complete or dropped, call `goal({"op":"create"})` directly. The goal tool remains callable across drop; no slash-command cleanup exists or is required.
|
|
200
213
|
- Never call `goal({"op":"create"})` when `goal({"op":"get"})` reports a different active goal.
|
|
201
214
|
- Never call `goal({"op":"complete"})` unless the aggregate run or legacy per-story goal is actually complete.
|
|
202
215
|
- In aggregate mode, intermediate and final story checkpoints require a matching `active` GJC goal snapshot; the final story checkpoint creates the final aggregate receipt before `goal({"op":"complete"})` may reconcile the inline goal state.
|