@gajae-code/coding-agent 0.7.2 → 0.7.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 +86 -0
- package/bin/gjc.js +4 -0
- package/dist/types/cli/mcp-cli.d.ts +25 -0
- package/dist/types/cli/plugin-cli.d.ts +2 -0
- package/dist/types/cli.d.ts +6 -0
- package/dist/types/commands/mcp.d.ts +70 -0
- package/dist/types/commands/plugin.d.ts +6 -0
- package/dist/types/commands/session.d.ts +6 -0
- package/dist/types/config/keybindings.d.ts +2 -2
- package/dist/types/config/model-profile-activation.d.ts +8 -1
- package/dist/types/deep-interview/plaintext-gate-guard.d.ts +11 -0
- package/dist/types/extensibility/gjc-plugins/compiler.d.ts +19 -0
- package/dist/types/extensibility/gjc-plugins/constrained-hooks.d.ts +29 -0
- package/dist/types/extensibility/gjc-plugins/index.d.ts +9 -0
- package/dist/types/extensibility/gjc-plugins/injection.d.ts +9 -0
- package/dist/types/extensibility/gjc-plugins/installer.d.ts +13 -0
- package/dist/types/extensibility/gjc-plugins/mcp-policy.d.ts +26 -0
- package/dist/types/extensibility/gjc-plugins/observability.d.ts +27 -0
- package/dist/types/extensibility/gjc-plugins/prompt-appendix.d.ts +16 -0
- package/dist/types/extensibility/gjc-plugins/registry.d.ts +32 -0
- package/dist/types/extensibility/gjc-plugins/runtime-adapters.d.ts +64 -0
- package/dist/types/extensibility/gjc-plugins/session-validation.d.ts +42 -0
- package/dist/types/extensibility/gjc-plugins/types.d.ts +158 -2
- package/dist/types/extensibility/gjc-plugins/validation.d.ts +8 -1
- package/dist/types/gjc-runtime/launch-tmux.d.ts +1 -0
- package/dist/types/gjc-runtime/psmux-detect.d.ts +78 -0
- package/dist/types/gjc-runtime/team-runtime.d.ts +2 -0
- package/dist/types/gjc-runtime/tmux-common.d.ts +20 -1
- package/dist/types/gjc-runtime/tmux-sessions.d.ts +18 -0
- package/dist/types/main.d.ts +2 -0
- package/dist/types/modes/components/custom-editor.d.ts +1 -1
- package/dist/types/modes/components/model-selector.d.ts +8 -0
- package/dist/types/modes/components/status-line/git-utils.d.ts +6 -0
- package/dist/types/modes/theme/defaults/index.d.ts +99 -0
- package/dist/types/notifications/html-format.d.ts +11 -0
- package/dist/types/notifications/index.d.ts +149 -1
- package/dist/types/notifications/lifecycle-commands.d.ts +72 -0
- package/dist/types/notifications/lifecycle-control-runtime.d.ts +98 -0
- package/dist/types/notifications/lifecycle-orchestrator.d.ts +144 -0
- package/dist/types/notifications/operator-runtime.d.ts +52 -0
- package/dist/types/notifications/rate-limit-pool.d.ts +2 -0
- package/dist/types/notifications/recent-activity.d.ts +35 -0
- package/dist/types/notifications/telegram-daemon.d.ts +114 -16
- package/dist/types/notifications/telegram-reference.d.ts +3 -1
- package/dist/types/notifications/topic-registry.d.ts +12 -9
- package/dist/types/runtime-mcp/types.d.ts +7 -0
- package/dist/types/sdk.d.ts +2 -0
- package/dist/types/session/agent-session.d.ts +14 -4
- package/dist/types/session/blob-store.d.ts +25 -0
- package/dist/types/session/session-manager.d.ts +57 -0
- package/dist/types/slash-commands/helpers/fast-status-report.d.ts +6 -0
- package/dist/types/system-prompt.d.ts +2 -0
- package/dist/types/task/executor.d.ts +9 -1
- package/dist/types/tools/composer-bash-policy.d.ts +14 -0
- package/dist/types/tools/index.d.ts +3 -1
- package/dist/types/utils/changelog.d.ts +1 -0
- package/dist/types/web/insane/url-guard.d.ts +6 -3
- package/dist/types/web/scrapers/types.d.ts +5 -0
- package/dist/types/web/scrapers/utils.d.ts +7 -1
- package/package.json +11 -9
- package/scripts/g004-tmux-smoke.ts +100 -0
- package/scripts/g005-daemon-smoke.ts +181 -0
- package/scripts/g011-daemon-path-smoke.ts +153 -0
- package/src/cli/mcp-cli.ts +272 -0
- package/src/cli/plugin-cli.ts +66 -3
- package/src/cli.ts +27 -6
- package/src/commands/mcp.ts +117 -0
- package/src/commands/plugin.ts +4 -0
- package/src/commands/session.ts +18 -0
- package/src/config/keybindings.ts +2 -2
- package/src/config/model-profile-activation.ts +55 -7
- package/src/deep-interview/plaintext-gate-guard.ts +94 -0
- package/src/defaults/gjc/extensions/grok-cli-vendor/biome.json +1 -1
- package/src/defaults/gjc/skills/deep-interview/SKILL.md +7 -6
- package/src/defaults/gjc/skills/team/SKILL.md +5 -3
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +41 -13
- package/src/export/html/index.ts +2 -2
- package/src/extensibility/extensions/runner.ts +1 -0
- package/src/extensibility/gjc-plugins/compiler.ts +351 -0
- package/src/extensibility/gjc-plugins/constrained-hooks.ts +170 -0
- package/src/extensibility/gjc-plugins/index.ts +9 -0
- package/src/extensibility/gjc-plugins/injection.ts +109 -0
- package/src/extensibility/gjc-plugins/installer.ts +434 -0
- package/src/extensibility/gjc-plugins/loader.ts +3 -1
- package/src/extensibility/gjc-plugins/mcp-policy.ts +239 -0
- package/src/extensibility/gjc-plugins/observability.ts +84 -0
- package/src/extensibility/gjc-plugins/paths.ts +1 -1
- package/src/extensibility/gjc-plugins/prompt-appendix.ts +109 -0
- package/src/extensibility/gjc-plugins/registry.ts +180 -0
- package/src/extensibility/gjc-plugins/runtime-adapters.ts +234 -0
- package/src/extensibility/gjc-plugins/schema.ts +250 -20
- package/src/extensibility/gjc-plugins/session-validation.ts +147 -0
- package/src/extensibility/gjc-plugins/types.ts +199 -3
- package/src/extensibility/gjc-plugins/validation.ts +80 -0
- package/src/extensibility/skills.ts +15 -0
- package/src/gjc-runtime/launch-tmux.ts +61 -7
- package/src/gjc-runtime/psmux-detect.ts +239 -0
- package/src/gjc-runtime/team-runtime.ts +56 -23
- package/src/gjc-runtime/tmux-common.ts +30 -3
- package/src/gjc-runtime/tmux-sessions.ts +51 -1
- package/src/gjc-runtime/ultragoal-guard.ts +25 -8
- package/src/gjc-runtime/ultragoal-runtime.ts +75 -15
- package/src/hooks/skill-state.ts +57 -0
- package/src/internal-urls/docs-index.generated.ts +12 -8
- package/src/main.ts +14 -3
- package/src/modes/bridge/bridge-mode.ts +11 -0
- package/src/modes/components/custom-editor.ts +2 -0
- package/src/modes/components/footer.ts +2 -3
- package/src/modes/components/hook-editor.ts +1 -1
- package/src/modes/components/hook-selector.ts +67 -43
- package/src/modes/components/model-selector.ts +56 -11
- package/src/modes/components/status-line/git-utils.ts +25 -0
- package/src/modes/components/status-line.ts +10 -11
- package/src/modes/components/welcome.ts +2 -3
- package/src/modes/controllers/extension-ui-controller.ts +0 -27
- package/src/modes/controllers/selector-controller.ts +53 -11
- package/src/modes/interactive-mode.ts +4 -1
- package/src/modes/shared/agent-wire/scopes.ts +1 -1
- package/src/modes/theme/defaults/gruvbox-dark.json +99 -0
- package/src/modes/theme/defaults/index.ts +2 -0
- package/src/modes/utils/hotkeys-markdown.ts +1 -1
- package/src/notifications/html-format.ts +38 -0
- package/src/notifications/index.ts +242 -12
- package/src/notifications/lifecycle-commands.ts +228 -0
- package/src/notifications/lifecycle-control-runtime.ts +400 -0
- package/src/notifications/lifecycle-orchestrator.ts +358 -0
- package/src/notifications/operator-runtime.ts +171 -0
- package/src/notifications/rate-limit-pool.ts +19 -0
- package/src/notifications/recent-activity.ts +132 -0
- package/src/notifications/telegram-daemon.ts +778 -257
- package/src/notifications/telegram-reference.ts +25 -7
- package/src/notifications/topic-registry.ts +23 -9
- package/src/prompts/agents/executor.md +2 -2
- package/src/runtime-mcp/transports/stdio.ts +38 -4
- package/src/runtime-mcp/types.ts +7 -0
- package/src/sdk.ts +157 -10
- package/src/session/agent-session.ts +166 -74
- package/src/session/blob-store.ts +196 -8
- package/src/session/session-manager.ts +678 -7
- package/src/slash-commands/builtin-registry.ts +23 -3
- package/src/slash-commands/helpers/fast-status-report.ts +13 -3
- package/src/slash-commands/helpers/parse.ts +2 -1
- package/src/system-prompt.ts +9 -0
- package/src/task/executor.ts +31 -7
- package/src/task/index.ts +2 -0
- package/src/tools/ask.ts +5 -1
- package/src/tools/bash.ts +9 -0
- package/src/tools/composer-bash-policy.ts +96 -0
- package/src/tools/fetch.ts +18 -2
- package/src/tools/index.ts +3 -1
- package/src/utils/changelog.ts +8 -0
- package/src/web/insane/url-guard.ts +18 -14
- package/src/web/scrapers/types.ts +143 -45
- package/src/web/scrapers/utils.ts +70 -19
|
@@ -7,8 +7,13 @@ import {
|
|
|
7
7
|
formatAvailableProfileNames,
|
|
8
8
|
resolveProfileBindings,
|
|
9
9
|
} from "./model-profiles";
|
|
10
|
-
import {
|
|
11
|
-
|
|
10
|
+
import {
|
|
11
|
+
GJC_MODEL_ASSIGNMENT_TARGETS,
|
|
12
|
+
type GjcModelAssignmentTargetId,
|
|
13
|
+
isAuthenticated,
|
|
14
|
+
type ModelRegistry,
|
|
15
|
+
} from "./model-registry";
|
|
16
|
+
import { formatModelSelectorValue, resolveModelRoleValue } from "./model-resolver";
|
|
12
17
|
import type { Settings } from "./settings";
|
|
13
18
|
|
|
14
19
|
const LEGACY_MODEL_PROFILE_ALIASES: ReadonlyMap<string, string> = new Map([["codex-standard", "codex-medium"]]);
|
|
@@ -60,6 +65,48 @@ export interface PreparedModelProfileActivation {
|
|
|
60
65
|
*/
|
|
61
66
|
previousSessionDefaultModel: string | undefined;
|
|
62
67
|
}
|
|
68
|
+
export interface MaterializeModelProfileAssignmentOptions {
|
|
69
|
+
session: Pick<
|
|
70
|
+
ModelProfileActivationSession,
|
|
71
|
+
"model" | "thinkingLevel" | "setActiveModelProfile" | "getActiveModelProfile"
|
|
72
|
+
>;
|
|
73
|
+
settings: Pick<Settings, "clearOverride" | "get" | "override" | "set">;
|
|
74
|
+
role: GjcModelAssignmentTargetId;
|
|
75
|
+
selector: string;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function materializeActiveModelProfileAssignment(options: MaterializeModelProfileAssignmentOptions): boolean {
|
|
79
|
+
const activeProfile = options.session.getActiveModelProfile?.() ?? options.settings.get("modelProfile.default");
|
|
80
|
+
if (!activeProfile) return false;
|
|
81
|
+
|
|
82
|
+
const nextModelRoles = { ...options.settings.get("modelRoles") };
|
|
83
|
+
const nextAgentModelOverrides = { ...options.settings.get("task.agentModelOverrides") };
|
|
84
|
+
const target = GJC_MODEL_ASSIGNMENT_TARGETS[options.role];
|
|
85
|
+
|
|
86
|
+
if (options.role === "default") {
|
|
87
|
+
nextModelRoles.default = options.selector;
|
|
88
|
+
} else if (!nextModelRoles.default && options.session.model) {
|
|
89
|
+
nextModelRoles.default = formatModelSelectorValue(
|
|
90
|
+
`${options.session.model.provider}/${options.session.model.id}`,
|
|
91
|
+
options.session.thinkingLevel,
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (target.settingsPath === "modelRoles") {
|
|
96
|
+
nextModelRoles[options.role] = options.selector;
|
|
97
|
+
} else {
|
|
98
|
+
nextAgentModelOverrides[options.role] = options.selector;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
options.settings.set("modelRoles", nextModelRoles);
|
|
102
|
+
options.settings.set("task.agentModelOverrides", nextAgentModelOverrides);
|
|
103
|
+
options.settings.set("modelProfile.default", undefined);
|
|
104
|
+
options.settings.clearOverride("modelProfile.default");
|
|
105
|
+
options.settings.override("modelRoles", nextModelRoles);
|
|
106
|
+
options.settings.override("task.agentModelOverrides", nextAgentModelOverrides);
|
|
107
|
+
options.session.setActiveModelProfile?.(undefined);
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
63
110
|
|
|
64
111
|
export function formatModelProfileCredentialError(profileName: string, providers: readonly string[]): string {
|
|
65
112
|
return `Model profile "${profileName}" requires credentials for: ${providers.join(", ")}. Run /login and configure the missing provider(s), then retry.`;
|
|
@@ -255,20 +302,19 @@ export async function applyPreparedModelProfileActivation(
|
|
|
255
302
|
modelChanged = true;
|
|
256
303
|
}
|
|
257
304
|
if (Object.keys(prepared.modelRoles).length > 0) {
|
|
258
|
-
prepared.settings.override("modelRoles", {
|
|
259
|
-
...prepared.settings.get("modelRoles"),
|
|
260
|
-
...prepared.modelRoles,
|
|
261
|
-
});
|
|
305
|
+
prepared.settings.override("modelRoles", { ...previousModelRoles, ...prepared.modelRoles });
|
|
262
306
|
modelRolesChanged = true;
|
|
263
307
|
}
|
|
264
308
|
if (Object.keys(prepared.agentModelOverrides).length > 0) {
|
|
265
309
|
prepared.settings.override("task.agentModelOverrides", {
|
|
266
|
-
...
|
|
310
|
+
...previousAgentModelOverrides,
|
|
267
311
|
...prepared.agentModelOverrides,
|
|
268
312
|
});
|
|
269
313
|
overridesChanged = true;
|
|
270
314
|
}
|
|
271
315
|
if (options.persistDefault) {
|
|
316
|
+
prepared.settings.set("modelRoles", {});
|
|
317
|
+
prepared.settings.set("task.agentModelOverrides", {});
|
|
272
318
|
prepared.settings.set("modelProfile.default", prepared.profileName);
|
|
273
319
|
defaultChanged = true;
|
|
274
320
|
await prepared.settings.flush();
|
|
@@ -277,6 +323,8 @@ export async function applyPreparedModelProfileActivation(
|
|
|
277
323
|
} catch (error) {
|
|
278
324
|
if (defaultChanged) {
|
|
279
325
|
prepared.settings.set("modelProfile.default", previousPersistedDefault);
|
|
326
|
+
prepared.settings.set("modelRoles", previousModelRoles);
|
|
327
|
+
prepared.settings.set("task.agentModelOverrides", previousAgentModelOverrides);
|
|
280
328
|
}
|
|
281
329
|
if (modelRolesChanged) {
|
|
282
330
|
prepared.settings.override("modelRoles", previousModelRoles);
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
export type DeepInterviewPlaintextAskLeakOption = "Yes, crystallize" | "Adjust wording" | "Missing scope";
|
|
2
|
+
|
|
3
|
+
export type DeepInterviewPlaintextAskLeakResult = {
|
|
4
|
+
kind: "deep_interview_plaintext_ask_leak";
|
|
5
|
+
matchedOptions: DeepInterviewPlaintextAskLeakOption[];
|
|
6
|
+
signals: {
|
|
7
|
+
optionsHeading: true;
|
|
8
|
+
restateIntent: true;
|
|
9
|
+
deepInterviewContext: boolean;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const CANONICAL_OPTIONS: DeepInterviewPlaintextAskLeakOption[] = [
|
|
14
|
+
"Yes, crystallize",
|
|
15
|
+
"Adjust wording",
|
|
16
|
+
"Missing scope",
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
const RESTATE_INTENT_PATTERNS: RegExp[] = [
|
|
20
|
+
/\brestate\b/i,
|
|
21
|
+
/\bconfirmation\b/i,
|
|
22
|
+
/\bconfirm(?:ation|ed|ing)?\b/i,
|
|
23
|
+
/\bcrystall?ize\b/i,
|
|
24
|
+
/\bdoes\s+this\s+(?:capture|match|reflect|summari[sz]e)\b/i,
|
|
25
|
+
/\bbefore\s+(?:i|we)\s+(?:write|finali[sz]e|crystall?ize)\b/i,
|
|
26
|
+
/\bread\s+only\s+this\s+line\b/i,
|
|
27
|
+
/\bturn\s+this\s+into\s+(?:the\s+)?(?:spec|final)\b/i,
|
|
28
|
+
/재진술/,
|
|
29
|
+
/다시\s*말/,
|
|
30
|
+
/확인/,
|
|
31
|
+
/확정/,
|
|
32
|
+
/정리/,
|
|
33
|
+
/요약/,
|
|
34
|
+
/맞(?:습니까|나요|는지)/,
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
const DEEP_INTERVIEW_CONTEXT_PATTERNS: RegExp[] = [
|
|
38
|
+
/\bdeep[ -]?interview\b/i,
|
|
39
|
+
/\bsocratic\b/i,
|
|
40
|
+
/\binterview\s+round\b/i,
|
|
41
|
+
/\bround\s+\d+\b/i,
|
|
42
|
+
/\bambiguity\b/i,
|
|
43
|
+
/\btopology\s+confirmation\b/i,
|
|
44
|
+
/딥\s*인터뷰/,
|
|
45
|
+
/심층\s*인터뷰/,
|
|
46
|
+
/인터뷰\s*(?:라운드|진행|확인)/,
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
const FINAL_ARTIFACT_PATTERNS: RegExp[] = [
|
|
50
|
+
/^\s*#{1,3}\s*(?:(?:final|approved|completed|완료|최종)\s+)?(?:deep[ -]?interview\s+)?(?:spec(?:ification)?|transcript)\b/im,
|
|
51
|
+
/^\s*#{1,3}\s*(?:deep[ -]?interview\s+)?(?:final|approved|completed|완료|최종)\s+(?:spec(?:ification)?|transcript)\b/im,
|
|
52
|
+
/\b(?:final|approved|completed)\s+(?:deep[ -]?interview\s+)?(?:spec(?:ification)?|transcript)\b/i,
|
|
53
|
+
/\binterview\s+transcript\b/i,
|
|
54
|
+
/\.gjc\/specs\//i,
|
|
55
|
+
/최종\s*(?:명세|스펙|기록)/,
|
|
56
|
+
];
|
|
57
|
+
|
|
58
|
+
function hasOptionsHeading(text: string): boolean {
|
|
59
|
+
return /(?:^|\n)\s*options\s*:/i.test(text);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function hasPattern(text: string, patterns: RegExp[]): boolean {
|
|
63
|
+
return patterns.some(pattern => pattern.test(text));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function matchedCanonicalOptions(text: string): DeepInterviewPlaintextAskLeakOption[] {
|
|
67
|
+
const folded = text.toLocaleLowerCase("en-US");
|
|
68
|
+
return CANONICAL_OPTIONS.filter(option => folded.includes(option.toLocaleLowerCase("en-US")));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function looksLikeFinalArtifact(text: string): boolean {
|
|
72
|
+
return hasPattern(text, FINAL_ARTIFACT_PATTERNS);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function detectDeepInterviewPlaintextAskLeak(text: string): DeepInterviewPlaintextAskLeakResult | null {
|
|
76
|
+
const trimmed = text.trim();
|
|
77
|
+
if (trimmed.length === 0) return null;
|
|
78
|
+
if (looksLikeFinalArtifact(trimmed)) return null;
|
|
79
|
+
if (!hasOptionsHeading(trimmed)) return null;
|
|
80
|
+
|
|
81
|
+
const matchedOptions = matchedCanonicalOptions(trimmed);
|
|
82
|
+
if (matchedOptions.length < 2) return null;
|
|
83
|
+
if (!hasPattern(trimmed, RESTATE_INTENT_PATTERNS)) return null;
|
|
84
|
+
|
|
85
|
+
return {
|
|
86
|
+
kind: "deep_interview_plaintext_ask_leak",
|
|
87
|
+
matchedOptions,
|
|
88
|
+
signals: {
|
|
89
|
+
optionsHeading: true,
|
|
90
|
+
restateIntent: true,
|
|
91
|
+
deepInterviewContext: hasPattern(trimmed, DEEP_INTERVIEW_CONTEXT_PATTERNS),
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
}
|
|
@@ -292,7 +292,7 @@ Auto-research must never add a public skill entrypoint, never be slash-command/d
|
|
|
292
292
|
|
|
293
293
|
### Step 2b: Ask the Question
|
|
294
294
|
|
|
295
|
-
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:
|
|
295
|
+
Use the `ask` tool with the generated question. When a question has options, you MUST call `ask` and must not print `Question:`/`Options:` blocks as assistant prose. If you already printed a question/options block as prose, your next action is to call `ask` with the same question/options, not to wait for a typed answer. 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:
|
|
296
296
|
|
|
297
297
|
```
|
|
298
298
|
Round {n} | Component: {target_component_name} | Targeting: {weakest_dimension} | Why now: {one_sentence_targeting_rationale} | Ambiguity: {score}%
|
|
@@ -458,7 +458,7 @@ Also recompute and persist `ambiguity_milestone` each round (detect band transit
|
|
|
458
458
|
|
|
459
459
|
- **Round 3+**: Allow early exit if user says "enough", "let's go", "build it"
|
|
460
460
|
- **Round 10**: Show soft warning: "We're at 10 rounds. Current ambiguity: {score}%. Continue or proceed with current clarity?"
|
|
461
|
-
- **Round
|
|
461
|
+
- **Round 100**: Hard cap: "Maximum interview rounds reached. Proceeding with current clarity level ({score}%)."
|
|
462
462
|
|
|
463
463
|
## Phase 3: Lateral Review Panel (milestone-triggered)
|
|
464
464
|
|
|
@@ -495,7 +495,7 @@ When ambiguity ≤ threshold (or hard cap / early exit):
|
|
|
495
495
|
|
|
496
496
|
**4a. Closure / Acceptance Guard.** Even when ambiguity ≤ threshold, do not treat the math as completion. Run an independent readiness audit from the full main-session perspective (including explore findings, established facts, and triggers the scorer may not have fully weighed). Confirm every active topology component has goal/constraint/criteria coverage, no unresolved or disputed trigger remains on a path that matters, and no low-confidence auto-answer is standing in for user-confirmed truth above the clarity cap. If a material gap exists, explicitly override the gate to the user — "The math says ready, but I am not accepting it yet because {gap}" — and ask the single highest-impact follow-up, returning to Phase 2. Record any override in `state.closure_overrides`.
|
|
497
497
|
|
|
498
|
-
**4b. Restate gate.** Once closure passes, collapse the agreed answers into ONE sentence goal that covers every active component, and confirm it with a single `ask`: "If someone read only this line, would they reach the same outcome you have in mind?" Offer **Yes, crystallize**, **Adjust wording**, and **Missing scope**, plus free-text, applying `language.instruction` when present. On "Adjust wording" / "Missing scope", collect the exact correction with one follow-up `ask`, route it back through Step 2c scoring and established-facts maintenance (a correction can change ambiguity), then re-run closure and ask the Restate gate again. Cap at two loops; if alignment is not reached, return to Phase 2 with a targeted question instead of forcing a goal line. Persist the confirmed line as `state.restated_goal`.
|
|
498
|
+
**4b. Restate gate.** Once closure passes, collapse the agreed answers into ONE sentence goal that covers every active component, and confirm it with a single `ask`: "If someone read only this line, would they reach the same outcome you have in mind?" Offer **Yes, crystallize**, **Adjust wording**, and **Missing scope**, plus free-text, applying `language.instruction` when present. Because this gate has options, it MUST go through `ask`: do not print the Restate question and options as assistant prose with `Question:`/`Options:` labels. If the Restate gate was already printed that way, immediately call `ask` with the same question/options before accepting or waiting for any answer. On "Adjust wording" / "Missing scope", collect the exact correction with one follow-up `ask`, route it back through Step 2c scoring and established-facts maintenance (a correction can change ambiguity), then re-run closure and ask the Restate gate again. Cap at two loops; if alignment is not reached, return to Phase 2 with a targeted question instead of forcing a goal line. Persist the confirmed line as `state.restated_goal`.
|
|
499
499
|
|
|
500
500
|
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.
|
|
501
501
|
- Apply `language.instruction` when present so user-facing prose in the spec preserves the session language; keep code identifiers, file paths, commands, JSON/settings keys, and quoted source text unchanged.
|
|
@@ -690,6 +690,7 @@ Skipping any stage is possible but reduces quality assurance:
|
|
|
690
690
|
|
|
691
691
|
<Tool_Usage>
|
|
692
692
|
- Use the `ask` tool for each interview question — provides clickable UI with contextual options
|
|
693
|
+
- For any option-bearing question, call `ask`; never print `Question:`/`Options:` blocks as assistant prose. If such a block was already printed, call `ask` with the same question/options as the very next action instead of waiting for a typed/prose answer
|
|
693
694
|
- Preserve the GJC `ask` tool path for native interaction; do not introduce parallel structured-question transport into this skill
|
|
694
695
|
- Use `read/search/find exploration or a bounded read-only planner/architect subagent` for brownfield codebase exploration (run BEFORE asking user about codebase)
|
|
695
696
|
- Use opus model (temperature 0.1) for ambiguity scoring — consistency is critical
|
|
@@ -698,7 +699,7 @@ Skipping any stage is possible but reduces quality assurance:
|
|
|
698
699
|
- Use the GJC workflow CLI to save the final spec at `.gjc/_session-{sessionid}/specs/deep-interview-{slug}.md` exactly; do not use `write`, `edit`, or `ast_edit` directly on `.gjc/` paths without force override.
|
|
699
700
|
- Use public GJC workflow entrypoints to bridge to ralplan, ultragoal, or team only after explicit execution approval — never implement directly. Implementation handoff defaults to ultragoal; reserve team for when tmux-based interactive worker parallelization is genuinely required.
|
|
700
701
|
- The lateral-review panel spawns read-only persona subagents (Task tool) in parallel with independent context; it is an assist layer, never an executor and never the completion authority
|
|
701
|
-
- Apply the Refine gate (Step 2b″), the Dialectic Rhythm Guard (Step 2a), and the Closure + Restate gates (Phase 4) through the `ask` tool, preserving `language.instruction` for each
|
|
702
|
+
- Apply the Refine gate (Step 2b″), the Dialectic Rhythm Guard (Step 2a), and the Closure + Restate gates (Phase 4) through the `ask` tool, preserving `language.instruction` for each; if any of these gates has options, the assistant must call `ask` and must not print `Question:`/`Options:` blocks as assistant prose
|
|
702
703
|
- Use internal fragment auto-modes only at their documented hooks: `auto-research-greenfield.md` between Step 2a and 2b for greenfield `research: true` questions, `auto-answer-uncertain.md` as Step 2b′ after `ask` resolves and before scoring, and `lateral-review-panel.md` for the Phase 3 panel personas at ambiguity-milestone transitions and before synthesizing agent-supplied answers.
|
|
703
704
|
- 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.
|
|
704
705
|
</Tool_Usage>
|
|
@@ -787,7 +788,7 @@ Why bad: 45% ambiguity means nearly half the requirements are unclear. The mathe
|
|
|
787
788
|
</Examples>
|
|
788
789
|
|
|
789
790
|
<Escalation_And_Stop_Conditions>
|
|
790
|
-
- **Hard cap at
|
|
791
|
+
- **Hard cap at 100 rounds**: Proceed with whatever clarity exists, noting the risk
|
|
791
792
|
- **Soft warning at 10 rounds**: Offer to continue or proceed
|
|
792
793
|
- **Early exit (round 3+)**: Allow with warning if ambiguity > threshold
|
|
793
794
|
- **User says "stop", "cancel", "abort"**: Stop immediately, save state for resume
|
|
@@ -822,7 +823,7 @@ Optional settings in `.gjc/settings.json`:
|
|
|
822
823
|
"gjc": {
|
|
823
824
|
"deepInterview": {
|
|
824
825
|
"ambiguityThreshold": <resolvedThreshold>,
|
|
825
|
-
"maxRounds":
|
|
826
|
+
"maxRounds": 100,
|
|
826
827
|
"softWarningRounds": 10,
|
|
827
828
|
"minRoundsBeforeExit": 3,
|
|
828
829
|
"enableChallengeAgents": true,
|
|
@@ -68,7 +68,7 @@ requiring a separate linked execution loop up front. GJC team supports current-w
|
|
|
68
68
|
|
|
69
69
|
Use `$ultragoal` for durable leader-owned goal/ledger tracking and `$team` for parallel visible tmux execution lanes. When Team is launched with an active `.gjc/_session-{sessionid}/ultragoal/goals.json`, worker task/status context may include leader-owned Ultragoal context: `.gjc/_session-{sessionid}/ultragoal/goals.json`, `.gjc/_session-{sessionid}/ultragoal/ledger.jsonl`, the active goal id, GJC goal mode, and the `fresh_leader_goal_get_required` checkpoint policy.
|
|
70
70
|
|
|
71
|
-
Workers provide task status and verification evidence only. They do not own Ultragoal goal state, create worker ledgers, mutate `.gjc/_session-{sessionid}/ultragoal`, auto-launch Team from Ultragoal, or perform hidden GJC goal mutation. Workers must not run `gjc ultragoal checkpoint`; checkpoint authority stays with the leader after worker tasks are terminal. Ultragoal does not auto-launch Team and performs no hidden goal mutation. The leader uses terminal Team evidence plus
|
|
71
|
+
Workers provide task status and verification evidence only. They do not own Ultragoal goal state, create worker ledgers, mutate `.gjc/_session-{sessionid}/ultragoal`, auto-launch Team from Ultragoal, or perform hidden GJC goal mutation. Workers must not run `gjc ultragoal checkpoint`; checkpoint authority stays with the leader after worker tasks are terminal. Ultragoal does not auto-launch Team and performs no hidden goal mutation. The leader uses terminal Team evidence plus the current-session active GJC goal snapshot and strict quality gate to run `gjc ultragoal checkpoint --goal-id <id> --status complete --evidence "<team evidence mentioning .gjc/_session-{sessionid}/ultragoal and <id>>" --quality-gate-json <quality-gate-json-or-path>`.
|
|
72
72
|
|
|
73
73
|
### Worker command override
|
|
74
74
|
|
|
@@ -311,8 +311,10 @@ Worker protocol:
|
|
|
311
311
|
Useful runtime env vars:
|
|
312
312
|
|
|
313
313
|
- `GJC_TMUX_COMMAND` / `GJC_TEAM_TMUX_COMMAND`
|
|
314
|
-
- tmux binary/
|
|
315
|
-
-
|
|
314
|
+
- tmux binary/name override (default `tmux` on POSIX, `psmux` / `pmux` / `tmux` on native Windows when one of those resolves on PATH). `GJC_TMUX_COMMAND` applies to every GJC tmux flow; `GJC_TEAM_TMUX_COMMAND` is honored as an alias by the team path. Both resolve through the same resolver, so the team leader and `gjc session ...` always target the same multiplexer. These values are executable path/name overrides, not shell command lines; do not include flags such as `psmux -L <namespace>` in the env var.
|
|
315
|
+
- Native Windows psmux support: psmux is the supported tmux-compatible multiplexer for native Windows `gjc --tmux`, `gjc session`, and `gjc team`. Psmux can be exposed as `psmux.exe` or as its `tmux.exe`/`pmux.exe` aliases. GJC probes `psmux` / `pmux` / `tmux` on Windows PATH, picks the first that resolves, and treats that binary as the multiplexer. Worker commands on Windows are emitted with PowerShell-safe `$env:VAR = 'value';` assignments so psmux's ConPTY panes inherit `GJC_TEAM_*` correctly.
|
|
316
|
+
- Multiplexer detection knobs (Windows): `GJC_PSMUX_COMMAND` forces a wrapper to be treated as psmux, `GJC_PSMUX_DETECTION=off` skips detection, `GJC_PSMUX_FORCE_DETECT=1` re-probes every call. The mouse / set-clipboard / mode-style UX profile is filtered out for psmux; the `@gjc-profile` ownership tag and branch / project / session identity markers still round-trip and are required for `gjc session` and `gjc team`.
|
|
317
|
+
- Windows psmux namespace boundary: psmux `-c <path>` cwd/start-directory flags do not isolate the server namespace; psmux uses the tmux-compatible global `-L <namespace>` flag for isolated server instances. GJC does not currently expose structured runtime `-L` support, because launch, `gjc session`, and `gjc team` must all carry the same namespace prefix together. If you need isolated psmux servers, start `psmux -L <namespace>` yourself before `gjc --tmux` and let GJC attach to it; do not pass `-L` through `GJC_TMUX_COMMAND`.
|
|
316
318
|
- `GJC_TEAM_WORKER_COMMAND`
|
|
317
319
|
- worker command override (default resolves to active GJC entrypoint or `gjc`)
|
|
318
320
|
- `GJC_TEAM_STATE_ROOT`
|
|
@@ -34,7 +34,7 @@ gjc ultragoal create-goals --brief "<brief>"
|
|
|
34
34
|
gjc ultragoal create-goals --brief-file <path>
|
|
35
35
|
gjc ultragoal complete-goals
|
|
36
36
|
gjc ultragoal complete-goals --retry-failed
|
|
37
|
-
gjc ultragoal checkpoint --goal-id <id> --status complete --evidence "<evidence>" --
|
|
37
|
+
gjc ultragoal checkpoint --goal-id <id> --status complete --evidence "<evidence>" --quality-gate-json <quality-gate-json-or-path>
|
|
38
38
|
gjc ultragoal checkpoint --goal-id <id> --status failed --evidence "<blocker/evidence>"
|
|
39
39
|
gjc ultragoal record-review-blockers --goal-id <id> --title "Resolve final review blockers" --objective "<blocker-resolution objective>" --evidence "<review findings>" --gjc-goal-json <active-goal-get-json-or-path>
|
|
40
40
|
```
|
|
@@ -50,7 +50,7 @@ goal({"op":"resume"})
|
|
|
50
50
|
```
|
|
51
51
|
`drop` clears the active goal without exiting goal mode; `resume` reactivates a paused goal.
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
Complete checkpoints source the active GJC goal snapshot from the current session when `--gjc-goal-json` is omitted. Use an explicit `--gjc-goal-json` only as an override; supplied values are still strictly validated and must be active goal-mode snapshots, not `.gjc/ultragoal/goals.json` records.
|
|
54
54
|
|
|
55
55
|
## Create goals
|
|
56
56
|
|
|
@@ -97,9 +97,9 @@ Loop until `gjc ultragoal status` reports all goals complete:
|
|
|
97
97
|
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"})`.
|
|
98
98
|
5. Complete the current GJC story only.
|
|
99
99
|
6. Run a completion audit against the story objective and real artifacts/tests.
|
|
100
|
-
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
|
|
101
|
-
8. Checkpoint the durable ledger
|
|
102
|
-
`gjc ultragoal checkpoint --goal-id <id> --status complete --evidence "<evidence>" --
|
|
100
|
+
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 while the aggregate objective is still `active`. On the final story, create the final aggregate receipt first; only after that receipt exists may `goal({"op":"complete"})` run.
|
|
101
|
+
8. Checkpoint the durable ledger. Complete checkpoints require `--quality-gate-json`; the runtime sources the active GJC goal snapshot from current session state when `--gjc-goal-json` is omitted, and rejects any explicitly supplied bad snapshot:
|
|
102
|
+
`gjc ultragoal checkpoint --goal-id <id> --status complete --evidence "<evidence>" --quality-gate-json <quality-gate-json-or-path>`
|
|
103
103
|
A successful complete checkpoint is story completion, not automatic run completion. Read the checkpoint output: when it prints `Next ultragoal goal: <id>`, continue that active story under the same aggregate GJC goal; when it prints `All ultragoal goals are complete`, the durable run is terminal. `gjc ultragoal complete-goals` remains the supported manual next-story command if continuation output was missed.
|
|
104
104
|
9. If blocked or failed, checkpoint failure:
|
|
105
105
|
`gjc ultragoal checkpoint --goal-id <id> --status failed --evidence "<blocker/evidence>"`
|
|
@@ -179,10 +179,10 @@ For large subgoals with independent slices, the Ultragoal leader must spawn para
|
|
|
179
179
|
|
|
180
180
|
Use ultragoal and team together for a durable Ultragoal story that benefits from one visible tmux worker session. Ultragoal remains leader-owned: `.gjc/_session-{sessionid}/ultragoal/goals.json` stores the story plan and `.gjc/_session-{sessionid}/ultragoal/ledger.jsonl` stores checkpoints. Team is the single-worker tmux execution engine and returns task/evidence status to the leader.
|
|
181
181
|
|
|
182
|
-
The leader checkpoints Ultragoal from Team evidence
|
|
182
|
+
The leader checkpoints Ultragoal from Team evidence; the runtime uses the active current-session GJC goal snapshot unless an explicit `--gjc-goal-json` override is supplied:
|
|
183
183
|
|
|
184
184
|
```sh
|
|
185
|
-
gjc ultragoal checkpoint --goal-id <id> --status complete --evidence "<team evidence mentioning .gjc/_session-{sessionid}/ultragoal and <id>>" --
|
|
185
|
+
gjc ultragoal checkpoint --goal-id <id> --status complete --evidence "<team evidence mentioning .gjc/_session-{sessionid}/ultragoal and <id>>" --quality-gate-json <quality-gate-json-or-path>
|
|
186
186
|
```
|
|
187
187
|
|
|
188
188
|
Workers do not own ultragoal goal state, do not create worker ultragoal ledgers, and do not checkpoint Ultragoal. Workers must not run `gjc ultragoal checkpoint`; checkpoint authority stays with the leader after worker tasks are terminal. Team launch remains explicit; Ultragoal does not auto-launch Team and performs no hidden goal mutation.
|
|
@@ -211,9 +211,9 @@ An ultragoal story cannot be checkpointed `complete` until the active agent has
|
|
|
211
211
|
5. Delegate an `executor` QA/red-team lane to build and run the e2e/read-teaming QA suite appropriate for the story. This lane must try to break the change, not just confirm the happy path. It must start from the approved plan/spec/acceptance criteria, then user-facing contracts, and only then implementation code as supporting evidence. Plan/code mismatches are blockers, not items to paper over with implementation intent.
|
|
212
212
|
6. The executor QA/red-team lane must prove evidence by the real surface under test:
|
|
213
213
|
- GUI/web surfaces require a valid automation transcript plus a non-uniform screenshot. Bare `inlineEvidence` text or typed receipts never prove live GUI/web execution.
|
|
214
|
-
- CLI surfaces require runtime argv replay: `replaySafe: true`, an allowlisted argv `command`, and replayed normalized stdout matching `recordedStdout
|
|
214
|
+
- CLI surfaces require runtime argv replay: `replaySafe: true`, an allowlisted argv `command`, and replayed normalized stdout matching `recordedStdout`. The conservative allowlist is intentionally small: `bun --version`, `node --version`, deterministic `bun/node -e "console.log(...)"`, `npm|pnpm|yarn --version`, `npm|pnpm|yarn list`, read-only `git status|rev-parse|merge-base|diff|show|log` with safe args, and `gjc read|status`. Unsafe, non-deterministic, credentialed, interactive, or otherwise unallowlisted commands require audited `replayExempt` metadata with exact fields `reasonCode`, `reason`, `approvedBy`, and `fallbackArtifactRefs` plus a structurally valid fallback artifact. Allowed `reasonCode` values are exactly `unsafe_side_effect`, `requires_credentials`, `requires_network`, `non_deterministic_external`, `destructive`, `interactive_only`, and `platform_unavailable`.
|
|
215
215
|
- Native/desktop/tui surfaces require a structurally valid screenshot, PTY capture with terminal control codes, or app-automation transcript.
|
|
216
|
-
- API/package/
|
|
216
|
+
- API/package surfaces require a real artifact file or typed receipt whose artifact `kind` contains one of `api`, `package`, `consumer`, `black-box`, or `test-report`; examples: `api-package-test-report`, `package-consumer-report`, `black-box-api-receipt`. Algorithm/math surfaces require a real artifact file or typed receipt whose artifact `kind` contains one of `property`, `boundary`, `edge`, `adversarial`, `failure`, `math`, `algorithm`, or `test-report`; examples: `property-test-report`, `algorithm-boundary-report`. Bare `inlineEvidence` text alone is not sufficient for any surface.
|
|
217
217
|
- The mandatory **computer-use** red-team suite (`kill-switch-bypass`, `suspended-enforcement`, `permission-revoked`, …) is conditional, not universal: require it only when computer/desktop control is genuinely part of the product surface being dogfooded. For every other product type, prove the change through the matching live surface instead — browser-use automation for web/GUI, bash/CLI live invocation or argv replay for CLI, and real artifacts or typed receipts for API/package/algorithm/math. Editing docs, prompts, or skills that merely mention computer-use does not by itself make the computer-use suite applicable; pick the red-team surface that matches what the change actually ships.
|
|
218
218
|
7. The executor QA/red-team lane must report a matrix using `executorQa.contractCoverage`, `executorQa.surfaceEvidence`, `executorQa.adversarialCases`, and `executorQa.artifactRefs`. Not-applicable rows are allowed only in `contractCoverage` and `surfaceEvidence`; each `status: "not_applicable"` row requires `contractRef` plus `reason`. `adversarialCases` rows cannot be not-applicable.
|
|
219
219
|
8. Run a final code review pass and fold it into the strict quality gate. Clean means `architectReview.architectureStatus`, `architectReview.productStatus`, and `architectReview.codeStatus` are all `"CLEAR"`, `architectReview.recommendation` is `"APPROVE"`, executor QA statuses are `"passed"`, iteration is `"passed"` with `fullRerun: true`, every evidence field is non-empty, every required matrix row is present, and every blockers array is empty. `COMMENT`, `WATCH`, `REQUEST CHANGES`, `BLOCK`, missing evidence, missing or shallow matrix rows, plan/code mismatches, or non-empty blockers are non-clean.
|
|
@@ -222,7 +222,7 @@ An ultragoal story cannot be checkpointed `complete` until the active agent has
|
|
|
222
222
|
gjc ultragoal record-review-blockers --goal-id <id> --title "Resolve verification blockers" --objective "<blocker-resolution objective>" --evidence "<architect/executor findings>" --gjc-goal-json <active-goal-get-json-or-path>
|
|
223
223
|
```
|
|
224
224
|
10. Complete or steer through the blocker story, then rerun the full blocking verification loop. Repeat until all verifier lanes are clean.
|
|
225
|
-
11. Only after the loop is clean, checkpoint the story as complete with a structured quality gate and
|
|
225
|
+
11. Only after the loop is clean, checkpoint the story as complete with a structured quality gate and current-session active goal snapshot. The checkpoint creates a receipt; `goals.json.status` alone is not proof. In aggregate mode, the final aggregate receipt must exist before `goal({"op":"complete"})` is allowed.
|
|
226
226
|
|
|
227
227
|
While an Ultragoal run is active, the `ask` tool is blocked for all agents. Record unresolved review decisions as durable blockers with `gjc ultragoal record-review-blockers` instead of prompting interactively.
|
|
228
228
|
|
|
@@ -263,13 +263,25 @@ The native `checkpoint --status complete` command rejects missing or shallow gat
|
|
|
263
263
|
"id": "cli-replay",
|
|
264
264
|
"kind": "command-replay",
|
|
265
265
|
"path": "artifacts/cli-replay.json",
|
|
266
|
-
"description": "artifact file containing argv-only CLI replay JSON: schemaVersion 1, kind cli-replay, replaySafe true, allowlisted command, recordedStdout"
|
|
266
|
+
"description": "artifact file containing argv-only CLI replay JSON: schemaVersion 1, kind cli-replay, replaySafe true, allowlisted command such as bun/node --version or deterministic bun/node -e console.log(...), recordedStdout"
|
|
267
267
|
},
|
|
268
268
|
{
|
|
269
269
|
"id": "adversarial-report",
|
|
270
270
|
"kind": "failure-mode-test",
|
|
271
271
|
"path": "artifacts/adversarial-report.txt",
|
|
272
272
|
"description": "boundary, property, adversarial, or failure-mode result"
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
"id": "api-package-report",
|
|
276
|
+
"kind": "api-package-test-report",
|
|
277
|
+
"path": "artifacts/api-package-report.txt",
|
|
278
|
+
"description": "API/package consumer or endpoint verification output"
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
"id": "algorithm-report",
|
|
282
|
+
"kind": "property-test-report",
|
|
283
|
+
"path": "artifacts/algorithm-report.txt",
|
|
284
|
+
"description": "Algorithm/math property, boundary, or invariant verification output"
|
|
273
285
|
}
|
|
274
286
|
],
|
|
275
287
|
"contractCoverage": [
|
|
@@ -306,6 +318,22 @@ The native `checkpoint --status complete` command rejects missing or shallow gat
|
|
|
306
318
|
"verdict": "passed",
|
|
307
319
|
"artifactRefs": ["cli-replay"]
|
|
308
320
|
},
|
|
321
|
+
{
|
|
322
|
+
"id": "surface-api",
|
|
323
|
+
"contractRef": "API/package public interface under test",
|
|
324
|
+
"surface": "api/package",
|
|
325
|
+
"invocation": "real endpoint call, package consumer call, or schema contract check",
|
|
326
|
+
"verdict": "passed",
|
|
327
|
+
"artifactRefs": ["api-package-report"]
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
"id": "surface-algorithm",
|
|
331
|
+
"contractRef": "algorithm/math invariant under test",
|
|
332
|
+
"surface": "algorithm/math",
|
|
333
|
+
"invocation": "property, boundary, or invariant test run",
|
|
334
|
+
"verdict": "passed",
|
|
335
|
+
"artifactRefs": ["algorithm-report"]
|
|
336
|
+
},
|
|
309
337
|
{
|
|
310
338
|
"id": "surface-out-of-scope",
|
|
311
339
|
"contractRef": "surface intentionally outside this story",
|
|
@@ -364,6 +392,6 @@ The skill tool then dispatches `/skill:ralplan` or `/skill:deep-interview` same-
|
|
|
364
392
|
- 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.
|
|
365
393
|
- Never call `goal({"op":"create"})` when `goal({"op":"get"})` reports a different active goal.
|
|
366
394
|
- Never call `goal({"op":"complete"})` unless the aggregate run or legacy per-story goal is actually complete.
|
|
367
|
-
- 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.
|
|
368
|
-
- Completion checkpoints require read-only goal snapshot reconciliation:
|
|
395
|
+
- In aggregate mode, intermediate and final story checkpoints require a matching `active` GJC goal snapshot; omitted complete-checkpoint `--gjc-goal-json` reads that snapshot from current session state, and the final story checkpoint creates the final aggregate receipt before `goal({"op":"complete"})` may reconcile the inline goal state.
|
|
396
|
+
- Completion checkpoints require read-only goal snapshot reconciliation: omit `--gjc-goal-json` to use current session state, or pass an explicit JSON/path override that remains strictly validated; shell commands and hooks must not mutate goal state.
|
|
369
397
|
- Treat `ledger.jsonl` as the durable audit trail; checkpoint after every success or failure.
|
package/src/export/html/index.ts
CHANGED
|
@@ -125,7 +125,7 @@ export async function exportSessionToHtml(
|
|
|
125
125
|
|
|
126
126
|
const sessionData: SessionData = {
|
|
127
127
|
header: sm.getHeader(),
|
|
128
|
-
entries: sm.
|
|
128
|
+
entries: sm.getEntriesForExport(),
|
|
129
129
|
leafId: sm.getLeafId(),
|
|
130
130
|
systemPrompt: state?.systemPrompt.join("\n\n"),
|
|
131
131
|
tools: state?.tools?.map(t => ({ name: t.name, description: t.description })),
|
|
@@ -153,7 +153,7 @@ export async function exportFromFile(inputPath: string, options?: ExportOptions
|
|
|
153
153
|
try {
|
|
154
154
|
const sessionData: SessionData = {
|
|
155
155
|
header: sm.getHeader(),
|
|
156
|
-
entries: sm.
|
|
156
|
+
entries: sm.getEntriesForExport(),
|
|
157
157
|
leafId: sm.getLeafId(),
|
|
158
158
|
};
|
|
159
159
|
|