@gajae-code/coding-agent 0.11.8 → 0.11.10
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 +35 -1
- package/dist/types/cli.d.ts +1 -0
- package/dist/types/config/model-profiles.d.ts +2 -3
- package/dist/types/config/model-registry.d.ts +2 -0
- package/dist/types/gjc-runtime/deep-interview-ambiguity.d.ts +12 -5
- package/dist/types/gjc-runtime/deep-interview-draft.d.ts +8 -0
- package/dist/types/gjc-runtime/deep-interview-payload.d.ts +41 -0
- package/dist/types/gjc-runtime/deep-interview-recorder.d.ts +32 -17
- package/dist/types/gjc-runtime/deep-interview-repair.d.ts +17 -0
- package/dist/types/gjc-runtime/deep-interview-state.d.ts +135 -4
- package/dist/types/gjc-runtime/state-writer.d.ts +45 -0
- package/dist/types/gjc-runtime/workflow-manifest.d.ts +5 -3
- package/dist/types/modes/components/welcome.d.ts +2 -0
- package/dist/types/modes/controllers/selector-controller.d.ts +16 -8
- package/dist/types/runtime-mcp/redaction.d.ts +2 -0
- package/dist/types/sdk/bus/chat-daemon-control.d.ts +3 -1
- package/dist/types/sdk/bus/daemon-paths.d.ts +1 -0
- package/dist/types/sdk/bus/index.d.ts +8 -1
- package/dist/types/sdk/bus/operator-runtime.d.ts +1 -0
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +14 -7
- package/dist/types/sdk/bus/telegram-daemon.d.ts +74 -5
- package/dist/types/sdk/session.d.ts +7 -0
- package/dist/types/session/agent-session.d.ts +2 -0
- package/dist/types/session/internal/managed-session-scope.d.ts +13 -3
- package/dist/types/session/internal/managed-session-storage.d.ts +8 -3
- package/dist/types/session/session-manager.d.ts +5 -1
- package/dist/types/session/session-storage.d.ts +13 -0
- package/dist/types/skill-state/active-state.d.ts +4 -0
- package/dist/types/task/provider-retry-status.d.ts +13 -0
- package/dist/types/task/types.d.ts +3 -0
- package/dist/types/tools/index.d.ts +3 -1
- package/package.json +8 -8
- package/scripts/generate-sdk-operation-inventory.ts +1 -0
- package/src/cli/mcp-cli.ts +4 -21
- package/src/cli/notify-cli.ts +1 -0
- package/src/cli.ts +32 -0
- package/src/commands/deep-interview.ts +9 -4
- package/src/commit/agentic/index.ts +3 -3
- package/src/commit/map-reduce/index.ts +2 -2
- package/src/config/model-profiles.ts +9 -10
- package/src/config/model-registry.ts +4 -2
- package/src/defaults/gjc/skills/deep-interview/SKILL.md +78 -163
- package/src/eval/js/tool-bridge.ts +1 -1
- package/src/gjc-runtime/deep-interview-ambiguity.ts +68 -47
- package/src/gjc-runtime/deep-interview-draft.ts +843 -0
- package/src/gjc-runtime/deep-interview-payload.ts +262 -0
- package/src/gjc-runtime/deep-interview-recorder.ts +310 -227
- package/src/gjc-runtime/deep-interview-repair.ts +1674 -0
- package/src/gjc-runtime/deep-interview-runtime.ts +264 -103
- package/src/gjc-runtime/deep-interview-state.ts +916 -4
- package/src/gjc-runtime/ralplan-runtime.ts +3 -1
- package/src/gjc-runtime/state-writer.ts +166 -2
- package/src/gjc-runtime/workflow-manifest.generated.json +386 -1
- package/src/gjc-runtime/workflow-manifest.ts +191 -5
- package/src/hooks/skill-state.ts +23 -1
- package/src/internal-urls/docs-index.generated.ts +6 -5
- package/src/modes/components/welcome.ts +10 -2
- package/src/modes/controllers/selector-controller.ts +38 -8
- package/src/modes/interactive-mode.ts +29 -9
- package/src/prompts/agent-fragments/restricted-bash.md +1 -1
- package/src/prompts/agents/architect.md +8 -1
- package/src/prompts/agents/critic.md +8 -1
- package/src/prompts/agents/planner.md +8 -1
- package/src/prompts/system/system-prompt.md +1 -0
- package/src/runtime-mcp/json-rpc.ts +7 -4
- package/src/runtime-mcp/redaction.ts +30 -0
- package/src/sdk/broker/identity.ts +22 -12
- package/src/sdk/broker/session-index.ts +11 -1
- package/src/sdk/bus/chat-daemon-control.ts +5 -3
- package/src/sdk/bus/daemon-paths.ts +2 -0
- package/src/sdk/bus/index.ts +60 -5
- package/src/sdk/bus/notification-service.ts +19 -5
- package/src/sdk/bus/operator-runtime.ts +31 -5
- package/src/sdk/bus/telegram-cli.ts +6 -13
- package/src/sdk/bus/telegram-daemon-cli.ts +8 -3
- package/src/sdk/bus/telegram-daemon-contract.ts +15 -7
- package/src/sdk/bus/telegram-daemon-control.ts +14 -5
- package/src/sdk/bus/telegram-daemon.ts +685 -120
- package/src/sdk/protocol/operation-inventory.generated.json +11 -0
- package/src/sdk/session.ts +12 -0
- package/src/session/agent-session.ts +140 -10
- package/src/session/internal/managed-session-scope.ts +339 -228
- package/src/session/internal/managed-session-storage.ts +17 -4
- package/src/session/session-manager.ts +96 -33
- package/src/session/session-storage.ts +23 -0
- package/src/skill-state/active-state.ts +10 -0
- package/src/skill-state/workflow-mutation-guard.ts +41 -7
- package/src/task/executor.ts +154 -44
- package/src/task/provider-retry-status.ts +88 -0
- package/src/task/render.ts +45 -26
- package/src/task/types.ts +3 -0
- package/src/tools/ask.ts +1 -0
- package/src/tools/bash-allowed-prefixes.ts +45 -1
- package/src/tools/index.ts +3 -1
- package/src/tools/subagent-render.ts +74 -16
- package/src/tools/subagent.ts +2 -0
- package/vendor/insane-search/MANIFEST.json +4 -1
- package/vendor/insane-search/engine/bias_check.py +5 -0
- package/vendor/insane-search/engine/fetch_chain.py +67 -1
- package/vendor/insane-search/engine/transport.py +13 -2
- package/vendor/insane-search/engine/validators.py +4 -1
|
@@ -2,7 +2,8 @@ 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
|
-
static description =
|
|
5
|
+
static description =
|
|
6
|
+
"Run native GJC deep-interview workflow. Use `draft` for editable CLI-owned mutation inputs; JSON repair verbs are compatibility-only.";
|
|
6
7
|
static strict = false;
|
|
7
8
|
static flags = {
|
|
8
9
|
quick: Flags.boolean({ description: "Seed a quick deep-interview run" }),
|
|
@@ -26,9 +27,13 @@ export default class DeepInterview extends Command {
|
|
|
26
27
|
json: Flags.boolean({ description: "Output JSON" }),
|
|
27
28
|
};
|
|
28
29
|
static examples = [
|
|
29
|
-
'$ gjc deep-interview --trace --standard "<idea>"',
|
|
30
|
-
"$ gjc deep-interview
|
|
31
|
-
"$ gjc deep-interview --
|
|
30
|
+
'$ gjc deep-interview --trace --standard "<idea>" --json',
|
|
31
|
+
"$ gjc deep-interview draft create --for initialize-context --session-id <id> --json",
|
|
32
|
+
"$ gjc deep-interview draft edit --draft-id <id> --expected-draft-revision 1 --op set --path /type --value greenfield --json",
|
|
33
|
+
"$ gjc deep-interview draft check --draft-id <id> --json",
|
|
34
|
+
"$ gjc deep-interview initialize-context --draft-id <id> --expected-draft-revision <n> --json",
|
|
35
|
+
"$ gjc deep-interview --write --stage final --slug my-feature --spec ./final-spec.md --json",
|
|
36
|
+
"$ gjc deep-interview inspect --session-id <id> --selector summary --json",
|
|
32
37
|
];
|
|
33
38
|
|
|
34
39
|
async run(): Promise<void> {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as path from "node:path";
|
|
2
2
|
import { createInterface } from "node:readline/promises";
|
|
3
|
-
import { $env, getProjectDir, isEnoent, prompt } from "@gajae-code/utils";
|
|
3
|
+
import { $env, $pickenv, getProjectDir, isEnoent, prompt } from "@gajae-code/utils";
|
|
4
4
|
import { applyChangelogProposals } from "../../commit/changelog";
|
|
5
5
|
import { detectChangelogBoundaries } from "../../commit/changelog/detect";
|
|
6
6
|
import { parseUnreleasedSection } from "../../commit/changelog/parse";
|
|
@@ -88,7 +88,7 @@ export async function runAgenticCommit(args: CommitCommandArgs): Promise<void> {
|
|
|
88
88
|
} else {
|
|
89
89
|
process.stdout.write(" └─ (none found)\n");
|
|
90
90
|
}
|
|
91
|
-
const forceFallback = $
|
|
91
|
+
const forceFallback = $pickenv("GJC_COMMIT_TEST_FALLBACK", "PI_COMMIT_TEST_FALLBACK")?.toLowerCase() === "true";
|
|
92
92
|
if (forceFallback) {
|
|
93
93
|
process.stdout.write("● Forcing fallback commit generation...\n");
|
|
94
94
|
const fallbackProposal = generateFallbackProposal(numstat);
|
|
@@ -152,7 +152,7 @@ export async function runAgenticCommit(args: CommitCommandArgs): Promise<void> {
|
|
|
152
152
|
}
|
|
153
153
|
|
|
154
154
|
if (!usedFallback && !commitState.proposal && !commitState.splitProposal) {
|
|
155
|
-
if ($
|
|
155
|
+
if ($pickenv("GJC_COMMIT_NO_FALLBACK", "PI_COMMIT_NO_FALLBACK")?.toLowerCase() !== "true") {
|
|
156
156
|
process.stdout.write("● Agent did not provide proposal, using fallback...\n");
|
|
157
157
|
commitState.proposal = generateFallbackProposal(numstat);
|
|
158
158
|
usedFallback = true;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ThinkingLevel } from "@gajae-code/agent-core";
|
|
2
2
|
import type { Api, Model } from "@gajae-code/ai";
|
|
3
|
-
import { $
|
|
3
|
+
import { $pickenv } from "@gajae-code/utils";
|
|
4
4
|
import { parseFileDiffs } from "../../commit/git/diff";
|
|
5
5
|
import type { ConventionalAnalysis } from "../../commit/types";
|
|
6
6
|
import { isExcludedFile } from "../../commit/utils/exclusions";
|
|
@@ -34,7 +34,7 @@ export interface MapReduceInput {
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
export function shouldUseMapReduce(diff: string, settings?: MapReduceSettings): boolean {
|
|
37
|
-
if ($
|
|
37
|
+
if ($pickenv("GJC_COMMIT_MAP_REDUCE", "PI_COMMIT_MAP_REDUCE")?.toLowerCase() === "false") return false;
|
|
38
38
|
if (settings?.enabled === false) return false;
|
|
39
39
|
const minFiles = settings?.minFiles ?? MIN_FILES_FOR_MAP_REDUCE;
|
|
40
40
|
const maxFileTokens = settings?.maxFileTokens ?? MAX_FILE_TOKENS;
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { sanitizeText } from "@gajae-code/utils";
|
|
2
|
-
import type { GjcModelAssignmentTargetId } from "./model-registry";
|
|
3
2
|
import { type ModelSelectorValue, normalizeModelSelectorValue } from "./model-selector-value";
|
|
4
|
-
import type { ModelsConfig } from "./models-config-schema";
|
|
3
|
+
import type { GJC_MODEL_ASSIGNMENT_TARGET_IDS, ModelsConfig } from "./models-config-schema";
|
|
5
4
|
|
|
6
|
-
export type ModelProfileRole =
|
|
5
|
+
export type ModelProfileRole = (typeof GJC_MODEL_ASSIGNMENT_TARGET_IDS)[number];
|
|
7
6
|
|
|
8
7
|
export interface ModelProfileDefinition {
|
|
9
8
|
name: string;
|
|
@@ -101,11 +100,11 @@ export const BUILTIN_MODEL_PROFILES: readonly ModelProfileDefinition[] = [
|
|
|
101
100
|
architect: "opencode-go/deepseek-v4-pro",
|
|
102
101
|
}),
|
|
103
102
|
profile("claude-opus", ["anthropic"], {
|
|
104
|
-
default: "anthropic/claude-opus-
|
|
103
|
+
default: "anthropic/claude-opus-5:xhigh",
|
|
105
104
|
executor: "anthropic/claude-sonnet-5",
|
|
106
|
-
planner: "anthropic/claude-opus-
|
|
107
|
-
critic: "anthropic/claude-opus-
|
|
108
|
-
architect: "anthropic/claude-opus-
|
|
105
|
+
planner: "anthropic/claude-opus-5:low",
|
|
106
|
+
critic: "anthropic/claude-opus-5:high",
|
|
107
|
+
architect: "anthropic/claude-opus-5:xhigh",
|
|
109
108
|
}),
|
|
110
109
|
profile("claude-fable", ["anthropic"], {
|
|
111
110
|
default: "anthropic/claude-fable-5:xhigh",
|
|
@@ -272,7 +271,7 @@ export const BUILTIN_MODEL_PROFILES: readonly ModelProfileDefinition[] = [
|
|
|
272
271
|
critic: "alibaba-token-plan/qwen3.8-max-preview:xhigh",
|
|
273
272
|
}),
|
|
274
273
|
profile("opus-codex", ["anthropic", "openai-codex"], {
|
|
275
|
-
default: "anthropic/claude-opus-
|
|
274
|
+
default: "anthropic/claude-opus-5:xhigh",
|
|
276
275
|
executor: "openai-codex/gpt-5.6-terra:low",
|
|
277
276
|
planner: "anthropic/claude-sonnet-5",
|
|
278
277
|
critic: "openai-codex/gpt-5.6-sol:xhigh",
|
|
@@ -288,8 +287,8 @@ export const BUILTIN_MODEL_PROFILES: readonly ModelProfileDefinition[] = [
|
|
|
288
287
|
profile("fable-opus-codex", ["anthropic", "openai-codex"], {
|
|
289
288
|
default: "anthropic/claude-fable-5:high",
|
|
290
289
|
executor: "openai-codex/gpt-5.6-terra:medium",
|
|
291
|
-
planner: "anthropic/claude-opus-
|
|
292
|
-
critic: "anthropic/claude-opus-
|
|
290
|
+
planner: "anthropic/claude-opus-5:medium",
|
|
291
|
+
critic: "anthropic/claude-opus-5:high",
|
|
293
292
|
architect: "openai-codex/gpt-5.6-sol:xhigh",
|
|
294
293
|
}),
|
|
295
294
|
];
|
|
@@ -2564,13 +2564,14 @@ export class ModelRegistry {
|
|
|
2564
2564
|
async getApiKey(
|
|
2565
2565
|
model: Model<Api>,
|
|
2566
2566
|
sessionId?: string,
|
|
2567
|
-
options: { credentialSelector?: AuthCredentialSelector } = {},
|
|
2567
|
+
options: { credentialSelector?: AuthCredentialSelector; signal?: AbortSignal } = {},
|
|
2568
2568
|
): Promise<string | undefined> {
|
|
2569
2569
|
return this.#getApiKeyOrNoAuth(model.provider, () =>
|
|
2570
2570
|
this.authStorage.getApiKey(model.provider, sessionId, {
|
|
2571
2571
|
baseUrl: model.baseUrl,
|
|
2572
2572
|
modelId: model.id,
|
|
2573
2573
|
credentialSelector: options.credentialSelector,
|
|
2574
|
+
signal: options.signal,
|
|
2574
2575
|
}),
|
|
2575
2576
|
);
|
|
2576
2577
|
}
|
|
@@ -2582,12 +2583,13 @@ export class ModelRegistry {
|
|
|
2582
2583
|
provider: string,
|
|
2583
2584
|
sessionId?: string,
|
|
2584
2585
|
baseUrl?: string,
|
|
2585
|
-
options: { credentialSelector?: AuthCredentialSelector } = {},
|
|
2586
|
+
options: { credentialSelector?: AuthCredentialSelector; signal?: AbortSignal } = {},
|
|
2586
2587
|
): Promise<string | undefined> {
|
|
2587
2588
|
return this.#getApiKeyOrNoAuth(provider, () =>
|
|
2588
2589
|
this.authStorage.getApiKey(provider, sessionId, {
|
|
2589
2590
|
baseUrl,
|
|
2590
2591
|
credentialSelector: options.credentialSelector,
|
|
2592
|
+
signal: options.signal,
|
|
2591
2593
|
}),
|
|
2592
2594
|
);
|
|
2593
2595
|
}
|
|
@@ -96,14 +96,15 @@ If this raw bundled skill is loaded by GJC's native skill loader through `/skill
|
|
|
96
96
|
## Corrupt current-session state recovery
|
|
97
97
|
|
|
98
98
|
When deep-interview detects its own current-session state is corrupt, tampered, unreadable, or stale on resume, run `gjc state clear --force --mode deep-interview` before reseeding or restarting. Scope the clear to the current session via `--session-id`, the command payload, or `GJC_SESSION_ID`; it clears only deep-interview state for that session and never clears other skills or sessions.
|
|
99
|
+
For ordinary diagnosis, run `gjc deep-interview sanity-check --session-id <id> --json` first, then use the issue's selector with `inspect` to read only the affected summary, topology, pending shell, round, facts, triggers, or floor. Repair a healthy, repairable local issue with its matching typed operation (`initialize-context`, `confirm-topology`, `record-answer`, or `apply-round-result`) and the current revision. Do not use grep/sed edits, direct `.gjc/` edits, generic envelope replacement, or `--force` as a repair mechanism; use generic `gjc state` only for the compatibility clear/handoff paths documented here.
|
|
99
100
|
|
|
100
101
|
## Phase 0: Resolve Ambiguity Threshold (blocking prerequisite)
|
|
101
102
|
|
|
102
103
|
Complete this phase before Phase 1, before brownfield exploration, before GJC state persistence, before Round 0, and before any ambiguity scoring. Do not continue if the resolved threshold and source are unknown.
|
|
103
104
|
|
|
104
|
-
1. **
|
|
105
|
-
-
|
|
106
|
-
- If
|
|
105
|
+
1. **Inspect the native summary first**:
|
|
106
|
+
- Run `gjc deep-interview inspect --session-id <id> --selector summary --json`.
|
|
107
|
+
- If the summary contains a finite `threshold` and its preserved source is available from native state, use those values, set `<resolvedThreshold>`, `<resolvedThresholdPercent>`, and `<resolvedThresholdSource>`, and skip optional settings-file reads. This is the normal `/skill:deep-interview` path because the native hook already resolved settings quietly before loading the skill.
|
|
107
108
|
2. **Only if native state lacks a resolved threshold, read threshold settings in runtime precedence order**:
|
|
108
109
|
- YAML config first: read the **single** modern config path the environment selects — `$GJC_CODING_AGENT_DIR/config.yml` when `GJC_CODING_AGENT_DIR` is set, else `$GJC_CONFIG_DIR/agent/config.yml` when `GJC_CONFIG_DIR` is set, else `~/.gjc/agent/config.yml`. Do not cascade through the other YAML locations when the selected one is absent or invalid.
|
|
109
110
|
- Then JSON settings: project settings `./.gjc/settings.json`, then user settings `[$GJC_CONFIG_DIR|~/.gjc]/settings.json`.
|
|
@@ -119,19 +120,19 @@ Deep Interview threshold: <resolvedThresholdPercent> (source: <resolvedThreshold
|
|
|
119
120
|
```
|
|
120
121
|
|
|
121
122
|
5. **Carry threshold source forward mechanically**:
|
|
122
|
-
-
|
|
123
|
-
- Include `threshold_source` in the first `gjc state write` payload and preserve it on later state updates; do not edit `.gjc/_session-{sessionid}/state` files directly unless an explicit force override is active.
|
|
123
|
+
- Pass threshold/source only as bounded setup evidence to `initialize-context`; native state owns the envelope, revision, receipt, lifecycle, derived ambiguity, and later updates. Do not reconstruct or submit a generic state envelope during normal flow.
|
|
124
124
|
- Include both threshold and source in the final spec metadata.
|
|
125
125
|
- Read any `language` object from active deep-interview state and carry `language.instruction` forward mechanically. If absent, default to English unless `{{ARGUMENTS}}` makes another user/session language obvious or the user explicitly requests another language. Do not add language-specific special cases.
|
|
126
126
|
|
|
127
127
|
## Phase 0.5: Suitability Gate
|
|
128
128
|
|
|
129
|
-
Run this gate after the Phase 0 threshold marker and before Phase 1, brownfield exploration,
|
|
129
|
+
Run this gate after the Phase 0 threshold marker and before Phase 1, brownfield exploration, typed initialization, Round 0, ambiguity scoring, or spec writing.
|
|
130
130
|
|
|
131
131
|
If the user request appended after this skill as the final `User:` line is already clear, bounded, low-risk, and asks for a quick fix, single change, known file/symbol edit, explicit command, or direct answer:
|
|
132
132
|
|
|
133
133
|
1. **Stop deep-interview immediately**:
|
|
134
|
-
- First inspect current-session state with `gjc
|
|
134
|
+
- First inspect current-session state with `gjc deep-interview inspect --session-id <current-session-id> --selector summary --json`.
|
|
135
|
+
- For compatibility-only recovery where typed inspection is unavailable, `gjc state read --mode deep-interview --json` may confirm whether this narrow clear is safe; never use it to rebuild or replace state.
|
|
135
136
|
- Clear through `gjc state clear --force --mode deep-interview --json` only when the state is a newly seeded empty interview: no recorded `rounds`, no `spec_path`, no `handoff_from`, no final/pending spec, and no user-confirmed topology.
|
|
136
137
|
- If state already contains rounds, a spec path, handoff metadata, pending approval, or confirmed topology, do not clear it. Preserve the active interview and ask the user whether to continue, cancel, or explicitly clear the workflow.
|
|
137
138
|
- Do not initialize deep-interview state.
|
|
@@ -181,46 +182,17 @@ Run this phase only when the active deep-interview state or invocation indicates
|
|
|
181
182
|
- Preferred: pass the spec markdown **inline** to the native deep-interview write command (`--write … --spec "<markdown>"`) — no scratch file is needed. The CLI is the only sanctioned writer for `.gjc/_session-{sessionid}/specs`.
|
|
182
183
|
- Only if a spec is too large to pass inline, stage it with the `write` tool to a system temp directory (`os.tmpdir()`/`$TMPDIR`, `/tmp`, `/var/tmp`) outside the project tree, then pass that path to `--spec`. The planning phase-boundary block tolerates these neutral temp writes; never stage interview artifacts inside the repo or under `.gjc/`, and do not improvise repo-relative scratch files.
|
|
183
184
|
|
|
184
|
-
4. **Initialize
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
"initial_idea": "<prompt-safe initial-context summary or user input>",
|
|
194
|
-
"initial_context_summary": "<summary if oversized, else null>",
|
|
195
|
-
"rounds": [],
|
|
196
|
-
"established_facts": [],
|
|
197
|
-
"current_ambiguity": 1.0,
|
|
198
|
-
"threshold": <resolvedThreshold>,
|
|
199
|
-
"threshold_source": "<resolvedThresholdSource>",
|
|
200
|
-
"language": "<existing language object from active state, if present>",
|
|
201
|
-
"trace_summary": "<bounded trace summary when --trace is active, else null>",
|
|
202
|
-
"codebase_context": null,
|
|
203
|
-
"topology": {
|
|
204
|
-
"status": "pending|confirmed|legacy_missing",
|
|
205
|
-
"confirmed_at": null,
|
|
206
|
-
"components": [],
|
|
207
|
-
"deferrals": [],
|
|
208
|
-
"last_targeted_component_id": null
|
|
209
|
-
},
|
|
210
|
-
"ontology_snapshots": [],
|
|
211
|
-
"auto_researched_rounds": [],
|
|
212
|
-
"auto_answered_rounds": [],
|
|
213
|
-
"lateral_reviews": [],
|
|
214
|
-
"lateral_panel_failures": 0,
|
|
215
|
-
"auto_answer_streak": 0,
|
|
216
|
-
"refined_rounds": [],
|
|
217
|
-
"closure_overrides": [],
|
|
218
|
-
"restated_goal": null,
|
|
219
|
-
"ambiguity_milestone": "initial",
|
|
220
|
-
"architect_failures": 0
|
|
221
|
-
}
|
|
222
|
-
}
|
|
185
|
+
4. **Initialize through a CLI-owned draft.** Create an `initialize-context` draft, edit only its bounded fields, check it, then consume it through the typed command. Never serialize a setup request, envelope, or derived values inline:
|
|
186
|
+
```sh
|
|
187
|
+
gjc deep-interview draft create --for initialize-context --session-id <id> --json
|
|
188
|
+
# Capture draft_id and draft_revision from the response.
|
|
189
|
+
gjc deep-interview draft edit --draft-id <draft_id> --expected-draft-revision <draft_revision> --op set --path /type --value greenfield --json
|
|
190
|
+
gjc deep-interview draft edit --draft-id <draft_id> --expected-draft-revision <next_draft_revision> --op set --path /initial_idea --value "<prompt-safe idea>" --json
|
|
191
|
+
gjc deep-interview draft edit --draft-id <draft_id> --expected-draft-revision <next_draft_revision> --op set --path /threshold_source --value "<source>" --json
|
|
192
|
+
gjc deep-interview draft check --draft-id <draft_id> --json
|
|
193
|
+
gjc deep-interview initialize-context --draft-id <draft_id> --expected-draft-revision <latest_draft_revision> --json
|
|
223
194
|
```
|
|
195
|
+
`draft create` records the state base revision; every edit returns the next `draft_revision`. The native runtime validates, consumes, stamps, and owns the complete state. Retain the returned state revision for inspection only; mutations consume their own checked draft.
|
|
224
196
|
|
|
225
197
|
5. **Announce the interview** to the user:
|
|
226
198
|
|
|
@@ -267,46 +239,20 @@ Options should include contextually relevant choices such as **Looks right**, **
|
|
|
267
239
|
|
|
268
240
|
The Round 0 `ask` call MUST include `deepInterview.round = 0`, `deepInterview.component = "review-topology"`, `deepInterview.dimension = "topology"`, `deepInterview.intent_contract.items` containing the exact displayed locked-intent items, and `deepInterview.intent_contract.confirmation_options` listing only the displayed affirmative labels that lock the proposal (normally **Looks right**). The runtime recorder canonicalizes and locks this contract only when the user selects one of those labels; correction, deferral, free-text, and clarification answers never lock the pre-question proposal. Do not manually copy raw free text into intent evidence, and do not continue if this required recorder write fails.
|
|
269
241
|
|
|
270
|
-
3. **Lock topology
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
"id": "component-slug",
|
|
280
|
-
"name": "Component Name",
|
|
281
|
-
"description": "Confirmed top-level outcome",
|
|
282
|
-
"status": "active|deferred",
|
|
283
|
-
"evidence": ["initial prompt phrase or brownfield citation"],
|
|
284
|
-
"clarity_scores": {
|
|
285
|
-
"goal": null,
|
|
286
|
-
"constraints": null,
|
|
287
|
-
"criteria": null,
|
|
288
|
-
"context": null
|
|
289
|
-
},
|
|
290
|
-
"weakest_dimension": null
|
|
291
|
-
}
|
|
292
|
-
],
|
|
293
|
-
"deferrals": [
|
|
294
|
-
{
|
|
295
|
-
"component_id": "component-slug",
|
|
296
|
-
"reason": "User-confirmed deferral reason",
|
|
297
|
-
"confirmed_at": "<ISO-8601 timestamp>"
|
|
298
|
-
}
|
|
299
|
-
],
|
|
300
|
-
"last_targeted_component_id": null
|
|
301
|
-
}
|
|
302
|
-
}
|
|
242
|
+
3. **Lock topology through a CLI-owned draft** after the answer. Create a `confirm-topology` draft, use a valueless append on a missing object-item array to add an `{}` scaffold, set scalar leaves, and check it. A valueless append on a missing scalar-item array initializes `[]`; on an existing scalar-item array, append still requires `--value` or `--value-file`. For a topology with zero deferrals, initialize `/deferred_components` with that valueless scalar-array append, then consume it:
|
|
243
|
+
```sh
|
|
244
|
+
gjc deep-interview draft create --for confirm-topology --session-id <id> --json
|
|
245
|
+
gjc deep-interview draft edit --draft-id <draft_id> --expected-draft-revision <draft_revision> --op append --path /components --json
|
|
246
|
+
gjc deep-interview draft edit --draft-id <draft_id> --expected-draft-revision <next_draft_revision> --op set --path /components/0/id --value <component_id> --json
|
|
247
|
+
gjc deep-interview draft edit --draft-id <draft_id> --expected-draft-revision <next_draft_revision> --op set --path /components/0/name --value "<component name>" --json
|
|
248
|
+
gjc deep-interview draft edit --draft-id <draft_id> --expected-draft-revision <next_draft_revision> --op append --path /deferred_components --json
|
|
249
|
+
gjc deep-interview draft check --draft-id <draft_id> --json
|
|
250
|
+
gjc deep-interview confirm-topology --draft-id <draft_id> --expected-draft-revision <latest_draft_revision> --json
|
|
303
251
|
```
|
|
252
|
+
The recorder still persists `state.intent_contract` from the Round 0 `ask` answer. The runtime validates pending/legacy state, preserves declared ordering, detects conflicting confirmations, derives component state, and returns the new revision. Do not replace `topology` through `gjc state write`.
|
|
253
|
+
It contains the four exact categories `artifact`, `surface`, `integration`, and `constraint`; every item has a unique category-prefixed ID (for example `surface:review`). The recorder canonically sorts items, persists the full SHA-256 manifest digest, and binds confirmation to a redacted answer-hash reference. Before spec persistence, include every preserved locked ID literally in the final spec. For a proposed missing locked ID, ask one intent-review question through `ask`; the runtime records `pending` unless the user selects an exact approval option, and spec persistence/handoff fail closed for missing, stale, or unrecorded reduction-review evidence. Intent review authorizes only that output reduction, never execution or handoff.
|
|
304
254
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
Before spec persistence, include every preserved locked ID literally in the final spec. Additions and clarifications need no extra question; the runtime derives and persists a `not_required` review when every locked ID remains. For any proposed missing locked ID, ask one intent-review question through `ask` and include `deepInterview.intent_review` with the proposed `observed_items`, every `supporting_substitution`, and the exact `approval_options` labels that count as approval. The runtime recorder writes `pending` when the user does not approve and writes `approved` only when an approval option is selected, binding the review to the recorder-generated answer hash without storing raw answer text. Approved reductions require every removed ID to map to an observed replacement ID. Spec persistence and handoff fail closed for missing, pending, malformed, stale, or unrecorded reduction review evidence. Intent review approves only that output reduction and never authorizes execution or ralplan handoff.
|
|
308
|
-
|
|
309
|
-
4. **Legacy state migration:** When resuming an existing `deep-interview` state file that lacks `topology`, treat it as `"status": "legacy_missing"`. If no final `spec_path` exists yet, run Round 0 before the next ambiguity scoring pass and then continue with the existing transcript. If a final spec already exists, do not rewrite history; note in any handoff that topology was not captured for that legacy interview.
|
|
255
|
+
4. **Legacy state migration:** When a resumed legacy interview lacks confirmed topology and no final `spec_path` exists, run Round 0 and use `confirm-topology` before the next ambiguity scoring pass. If a final spec already exists, do not rewrite history; note in any handoff that topology was not captured for that legacy interview.
|
|
310
256
|
|
|
311
257
|
5. **Single-component pass-through:** If the user confirms one active component, Phase 2 proceeds with the existing flow while still carrying `topology.components[0]` into scoring and spec output.
|
|
312
258
|
|
|
@@ -370,9 +316,19 @@ Options should include contextually relevant choices plus free-text, translated/
|
|
|
370
316
|
|
|
371
317
|
After applying `language.instruction` to the visible question, options, and generated rationale, apply the self-proofread once to new prose only (DIPP-5); preserve only the Round/Component/Targeting/Ambiguity line structure, fixed labels, numeric ambiguity value, component/target identifiers, and `deepInterview.*` metadata keys. Do not exempt generated natural-language rationale such as Why now.
|
|
372
318
|
|
|
373
|
-
When calling `ask`, SHOULD include optional structured metadata so the runtime can record the round without manual state writes: `deepInterview.round_id?`, `deepInterview.round`, `deepInterview.component`, `deepInterview.dimension`, and `deepInterview.ambiguity`. Keep this metadata aligned with the visible Round/Component/Targeting/Ambiguity line
|
|
319
|
+
When calling `ask`, SHOULD include optional structured metadata so the runtime can record the round without manual state writes: `deepInterview.round_id?`, `deepInterview.round`, `deepInterview.component`, `deepInterview.dimension`, and `deepInterview.ambiguity`. Keep this metadata aligned with the visible Round/Component/Targeting/Ambiguity line. Recorder-first remains mandatory. If the runtime did not record the answer shell, inspect `pending` or `round` to obtain its identity, then create a `record-answer` draft with that identity, edit scalar leaves, scaffold option arrays, and consume it:
|
|
320
|
+
```sh
|
|
321
|
+
gjc deep-interview draft create --for record-answer --session-id <id> --round <n> --question-id <id> [--round-id <id>] [--component-id <id>] [--dimension <dimension>] --json
|
|
322
|
+
gjc deep-interview draft edit --draft-id <draft_id> --expected-draft-revision <draft_revision> --op set --path /question --value "<question>" --json
|
|
323
|
+
gjc deep-interview draft edit --draft-id <draft_id> --expected-draft-revision <next_draft_revision> --op append --path /answer/selected_options --json
|
|
324
|
+
gjc deep-interview draft edit --draft-id <draft_id> --expected-draft-revision <next_draft_revision> --op set --path /answer/selected_options/0 --value "<selected option>" --json
|
|
325
|
+
gjc deep-interview draft edit --draft-id <draft_id> --expected-draft-revision <next_draft_revision> --op set --path /answer/custom_input --null --json
|
|
326
|
+
gjc deep-interview draft check --draft-id <draft_id> --json
|
|
327
|
+
gjc deep-interview record-answer --draft-id <draft_id> --expected-draft-revision <latest_draft_revision> --json
|
|
328
|
+
```
|
|
329
|
+
Do not recreate transcript, rounds, or generic state JSON.
|
|
374
330
|
|
|
375
|
-
If the `ask` tool returns `clarificationQuestion`, treat it as a non-answer about the displayed choices. Answer the clarification briefly from the current interview context, then call `ask` again with the exact original question, options, and `deepInterview.*` metadata. A clarification bypasses Step 2b′ auto-answer, Step 2b″ free-text refine, Step 2c ambiguity scoring, Step 2d
|
|
331
|
+
If the `ask` tool returns `clarificationQuestion`, treat it as a non-answer about the displayed choices. Answer the clarification briefly from the current interview context, then call `ask` again with the exact original question, options, and `deepInterview.*` metadata. A clarification bypasses Step 2b′ auto-answer, Step 2b″ free-text refine, Step 2c ambiguity scoring, Step 2d apply-and-report, and Step 2e soft-limit checks; it must not be recorded as a round answer. This does not violate the one-question-per-round rule because the round remains unresolved until the user submits a real listed option or `Other` answer.
|
|
376
332
|
|
|
377
333
|
### Step 2b′: Auto-Answer Opted-Out Questions
|
|
378
334
|
|
|
@@ -406,24 +362,17 @@ Ambiguity-raising triggers:
|
|
|
406
362
|
|
|
407
363
|
Use **mechanism A** for every ambiguity rise: a trigger LOWERS the affected component/dimension clarity score, and the existing weighted formula raises ambiguity. There is **no separate penalty term**; ambiguity remains bounded by the same greenfield/brownfield formula.
|
|
408
364
|
|
|
409
|
-
**
|
|
410
|
-
|
|
411
|
-
- `+0.10` per established fact marked `disputed` that has no `superseded_by` resolution (contradiction pressure)
|
|
412
|
-
- `+0.05` per active topology component whose goal/constraints/criteria clarity is still unscored (gap pressure — persist `topology.components[].clarity_scores` every round or the floor blocks convergence)
|
|
413
|
-
- `+0.05 × (auto-answered rounds / scored rounds)` (assumption dilution)
|
|
365
|
+
**Native ambiguity and floor.** Submit candidate component scores, trigger/fact operations, ontology evidence, targeting, and bookkeeping in `RoundResult`; the runtime alone derives weighted ambiguity, floor, effective ambiguity, milestone, ontology stability, trigger correspondence, rotation, and auto-resolution streak. Do not calculate, assert, or persist any of those derived values in the request.
|
|
414
366
|
|
|
415
|
-
|
|
416
|
-
- Replacing an already-scored answer for the same round (a retraction/pivot) automatically marks that round's established facts as disputed; ambiguity rises mechanically even when no trigger is reported. Treat a floor-driven rise as trigger evidence and score the affected dimensions accordingly.
|
|
417
|
-
- A disputed fact keeps the floor at or above `0.10` — above the default threshold — so convergence is blocked until the dispute is resolved: either the user re-confirms the original fact (set `disputed: false`) or the superseding decision is recorded as a new established fact and the old fact gets `superseded_by: <new fact id>`. Never delete the contradicted fact.
|
|
418
|
-
- When the effective score was clamped upward, the persisted round carries `reported_ambiguity` (your raw score) and `ambiguity_floor`; report the floor and its dominant cause in the Step 2d table instead of pretending the raw score held.
|
|
367
|
+
The native floor retains contradiction pressure, unscored active-component pressure, and auto-answer dilution. A disputed fact blocks convergence until it is resolved through the typed fact operation; never delete contradicted history. When the response reports a clamp, show the returned floor and dominant cause rather than inventing a score.
|
|
419
368
|
|
|
420
369
|
The rise is SILENT: no modal, no forced-resolution step, and no dedicated conflict UI. Surface it through the normal per-round report and by targeting the next question at the affected component/dimension.
|
|
421
370
|
|
|
422
|
-
Structured scorer output is required. Include `triggers`, `trigger_status`, `affected_component`, `affected_dimension`, `prior_dimension_score`, `new_dimension_score`, `
|
|
371
|
+
Structured scorer output is required. Include `triggers`, `trigger_status`, `affected_component`, `affected_dimension`, `prior_dimension_score`, `new_dimension_score`, `evidence`, `contradicted_established_fact` when relevant, and `disputed_unresolved_rationale` when applicable. Do not include prior/new ambiguity, floor, effective ambiguity, or milestone assertions.
|
|
423
372
|
|
|
424
373
|
Established-facts maintenance: promote stable confirmed decisions into `state.established_facts` with source/evidence; when a new answer contradicts an established fact, mark the fact disputed and preserve the contradicted fact instead of deleting it. When the user later confirms the new direction, record the superseding decision as a new established fact and set `superseded_by: <new fact id>` on the disputed fact — that is the only way to release the deterministic floor pressure while keeping the audit trail.
|
|
425
374
|
|
|
426
|
-
TRANSITION VALIDATION: if a trigger is present, the affected dimension must not improve
|
|
375
|
+
TRANSITION VALIDATION: if a trigger is present, the affected dimension must not improve unless the trigger is explicitly marked disputed or unresolved with rationale. The runtime validates and returns the authoritative ambiguity transition.
|
|
427
376
|
|
|
428
377
|
Convergence Pacing deferral: do not add a min-round floor, score-drop cap, confidence dampening, or other explicit pacing brake. Bidirectional scoring is the pacing mechanism.
|
|
429
378
|
|
|
@@ -464,7 +413,7 @@ Also identify:
|
|
|
464
413
|
- weakest_dimension: the single lowest-confidence dimension for that component this round
|
|
465
414
|
- weakest_dimension_rationale: one sentence explaining why this component/dimension pair is the highest-leverage target for the next question
|
|
466
415
|
- component_scores: object keyed by component id, with per-dimension scores and gaps
|
|
467
|
-
- structured_scorer_output: object containing triggers, trigger_status, affected_component, affected_dimension, prior_dimension_score, new_dimension_score,
|
|
416
|
+
- structured_scorer_output: object containing triggers, trigger_status, affected_component, affected_dimension, prior_dimension_score, new_dimension_score, evidence, contradicted_established_fact when relevant, and disputed_unresolved_rationale when applicable; do not include ambiguity, floor, or milestone values
|
|
468
417
|
|
|
469
418
|
5. Ontology Extraction: Identify all key entities (nouns) discussed in the transcript.
|
|
470
419
|
|
|
@@ -479,85 +428,51 @@ For each entity provide:
|
|
|
479
428
|
Respond as JSON. Include an additional "ontology" key containing the entities array alongside the dimension scores.
|
|
480
429
|
```
|
|
481
430
|
|
|
482
|
-
**
|
|
483
|
-
|
|
484
|
-
Greenfield: `ambiguity = 1 - (goal × 0.40 + constraints × 0.30 + criteria × 0.30)`
|
|
485
|
-
Brownfield: `ambiguity = 1 - (goal × 0.35 + constraints × 0.25 + criteria × 0.25 + context × 0.15)`
|
|
486
|
-
Brownfield adds the 15% Context Clarity dimension (Goal/Constraint/Criteria become 35/25/25) because safely modifying existing code requires understanding the system being changed.
|
|
487
|
-
|
|
488
|
-
**Calculate ontology stability:**
|
|
489
|
-
|
|
490
|
-
**Round 1 special case:** For the first round, skip stability comparison. All entities are "new". Set stability_ratio = N/A. If any round produces zero entities, set stability_ratio = N/A (avoids division by zero).
|
|
491
|
-
|
|
492
|
-
For rounds 2+, compare with the previous round's entity list:
|
|
493
|
-
- `stable_entities`: entities present in both rounds with the same name
|
|
494
|
-
- `changed_entities`: entities with different names but the same type AND >50% field overlap (treated as renamed, not new+removed)
|
|
495
|
-
- `new_entities`: entities in this round not matched by name or fuzzy-match to any previous entity
|
|
496
|
-
- `removed_entities`: entities in the previous round not matched to any current entity
|
|
497
|
-
- `stability_ratio`: (stable + changed) / total_entities (0.0 to 1.0, where 1.0 = fully converged)
|
|
498
|
-
|
|
499
|
-
This formula counts renamed entities (changed) toward stability. Renamed entities indicate the concept persists even if the name shifted — this is convergence, not instability. Two entities with different names but the same `type` and >50% field overlap should be classified as "changed" (renamed), not as one removed and one added.
|
|
500
|
-
|
|
501
|
-
**Show your work:** Before reporting stability numbers, briefly list which entities were matched (by name or fuzzy) and which are new/removed. This lets the user sanity-check the matching.
|
|
502
|
-
|
|
503
|
-
Store the ontology snapshot (entities + stability_ratio + matching_reasoning) in `state.ontology_snapshots[]`.
|
|
504
|
-
|
|
505
|
-
### Step 2d: Report Progress
|
|
506
|
-
|
|
507
|
-
After scoring, show the user their progress:
|
|
431
|
+
**Ontology input:** provide entities, relationships, and concise reasoning in `RoundResult`. The runtime determines first-round/no-entity handling, exact-name stability, deterministic renamed matching, counts, ratio, and snapshot persistence. Report the returned ontology result; do not send caller-computed counts, ratios, or snapshots.
|
|
508
432
|
|
|
433
|
+
### Step 2d: Apply Round Result and Report Progress
|
|
434
|
+
After `ask` has recorded (or `record-answer` has recovered) the answer shell, inspect `pending` or `round` for its identity. Create an `apply-round-result` draft, edit only bounded scorer evidence, check it, and consume it once:
|
|
435
|
+
```sh
|
|
436
|
+
gjc deep-interview draft create --for apply-round-result --session-id <id> --round-key <round_key> --json
|
|
437
|
+
gjc deep-interview draft edit --draft-id <draft_id> --expected-draft-revision <draft_revision> --op set --path /global_scores/goal --value 0.8 --json
|
|
438
|
+
gjc deep-interview draft edit --draft-id <draft_id> --expected-draft-revision <next_draft_revision> --op append --path /component_updates --json
|
|
439
|
+
gjc deep-interview draft edit --draft-id <draft_id> --expected-draft-revision <next_draft_revision> --op set --path /component_updates/0/component_id --value <component_id> --json
|
|
440
|
+
gjc deep-interview draft check --draft-id <draft_id> --json
|
|
441
|
+
gjc deep-interview apply-round-result --draft-id <draft_id> --expected-draft-revision <latest_draft_revision> --json
|
|
509
442
|
```
|
|
510
|
-
|
|
443
|
+
`RoundResult` remains candidate scores, component updates, triggers, fact operations, ontology input, targeting, and bookkeeping only. The runtime performs one authoritative transaction, returns native-derived scoring and the new revision, and rejects stale, conflicting, malformed, or unrecoverable state. Never enrich a round through `gjc state write`.
|
|
511
444
|
|
|
512
|
-
|
|
513
|
-
|-----------|-------|--------|----------|-----|
|
|
514
|
-
| Goal | {s} | {w} | {s*w} | {gap or "Clear"} |
|
|
515
|
-
| Constraints | {s} | {w} | {s*w} | {gap or "Clear"} |
|
|
516
|
-
| Success Criteria | {s} | {w} | {s*w} | {gap or "Clear"} |
|
|
517
|
-
| Context (brownfield) | {s} | {w} | {s*w} | {gap or "Clear"} |
|
|
518
|
-
| **Ambiguity** | | | **{prior_score}% -> {score}% {up|down|flat}** | {if up: trigger name such as "A direct contradiction"} |
|
|
519
|
-
| **Floor** (only when clamped) | | | **{floor}%** | {dominant cause: disputed fact / unscored component / auto-answer dilution} |
|
|
445
|
+
After the typed transaction succeeds, consume `<native>.native_projection` as the version 1 native projection. Render only the paths listed below; do not report candidate values, inspect-state values, locally calculated values, names, weights, gaps, thresholds, ratios, causes, or milestone transitions that the projection does not expose.
|
|
520
446
|
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
**Ontology:** {entity_count} entities | Stability: {stability_ratio} | New: {new} | Changed: {changed} | Stable: {stable}
|
|
524
|
-
**Milestone:** {prior_milestone} → {current_milestone}{milestone_transition ? " — lateral panel convened" : ""}
|
|
525
|
-
|
|
526
|
-
**Next target:** {target_component_name} / {weakest_dimension} — {weakest_dimension_rationale}
|
|
527
|
-
|
|
528
|
-
{score <= threshold ? "Clarity threshold met! Ready to proceed." : "Focusing next question on: {weakest_dimension}"}
|
|
447
|
+
```text
|
|
448
|
+
Round {n} complete.
|
|
529
449
|
|
|
450
|
+
Ambiguity: prior {<native>.native_projection.prior_effective_ambiguity}; current {<native>.native_projection.effective_ambiguity} ({<native>.native_projection.direction})
|
|
451
|
+
Floor: {<native>.native_projection.floor}
|
|
452
|
+
Milestone: {<native>.native_projection.ambiguity_milestone}
|
|
453
|
+
Topology: target {<native>.native_projection.targeting.target_component_id}; active {<native>.native_projection.topology_counts.active}; deferred {<native>.native_projection.topology_counts.deferred}; total {<native>.native_projection.topology_counts.total}
|
|
454
|
+
Ontology: stable {<native>.native_projection.ontology_counts.stable}; changed {<native>.native_projection.ontology_counts.changed}; new {<native>.native_projection.ontology_counts.new}
|
|
455
|
+
Next target: {<native>.native_projection.targeting.target_component_id} / {<native>.native_projection.targeting.target_dimension}
|
|
456
|
+
Auto-answer streak: {<native>.native_projection.transition.auto_answer_streak}
|
|
530
457
|
```
|
|
531
458
|
|
|
532
|
-
|
|
459
|
+
`prior_effective_ambiguity` may be `null` on the first scored round; show that returned value rather than inventing a prior percentage. The transition lifecycle and round identity remain available at `<native>.native_projection.transition.lifecycle` and `<native>.native_projection.transition.round_key` for control flow, but are not progress prose.
|
|
533
460
|
|
|
534
|
-
|
|
461
|
+
Apply `language.instruction` when present before showing this progress report; apply the self-proofread once (DIPP-5) to narrative status text, generated prose cells, gaps, and next-target phrasing while preserving the real native projection paths and fixed report structure.
|
|
535
462
|
|
|
536
|
-
### Step 2e:
|
|
537
|
-
|
|
538
|
-
Update state in two phases. The `ask` answer is first recorded by the runtime as an `answered` shell. Scoring then enriches the same round record to `scored` with global scores, per-component `topology.components[].clarity_scores`, `topology.components[].weakest_dimension`, trigger metadata, established-facts changes, ontology snapshot, `topology.last_targeted_component_id`, `auto_researched_rounds`, `auto_answered_rounds`, and `architect_failures`. When `deepInterview` ask metadata is present, no manual per-round `gjc state write` is required for the answer shell; only scoring enrichment/state maintenance remains. When metadata is absent, use the legacy `gjc state write` path to persist the new round and never patch `.gjc/_session-{sessionid}/state` directly unless an explicit force override is active.
|
|
539
|
-
Also recompute and persist `ambiguity_milestone` each round (detect band transitions for the Phase 3 panel), and persist `auto_answer_streak`, `refined_rounds`, `lateral_reviews`, and `lateral_panel_failures` alongside the existing fields.
|
|
540
|
-
|
|
541
|
-
### Step 2f: Check Tiered Confirmation Cadence
|
|
463
|
+
### Step 2e: Check Tiered Confirmation Cadence
|
|
542
464
|
|
|
543
465
|
Confirmation cadence is tiered by round, adopted from ouroboros's ooo interview, while the hard safety cap is retained:
|
|
544
466
|
|
|
545
467
|
- **Rounds 1-3 (auto-continue)**: minimum context gathering — proceed to the next question without a "continue?" prompt.
|
|
546
|
-
- **Rounds 4-15 (ask to continue)**: after each round, ask "Continue, or proceed with current clarity ({
|
|
547
|
-
- **Rounds 16+ (diminishing-returns warning)**: keep asking "Continue?" but prefix a diminishing-returns warning: "We're at {n} rounds (ambiguity: {
|
|
468
|
+
- **Rounds 4-15 (ask to continue)**: after each round, ask "Continue, or proceed with current clarity ({<native>.native_projection.effective_ambiguity}%)?" so the user controls depth.
|
|
469
|
+
- **Rounds 16+ (diminishing-returns warning)**: keep asking "Continue?" but prefix a diminishing-returns warning: "We're at {n} rounds (ambiguity: {<native>.native_projection.effective_ambiguity}%); each further round yields less. Continue or proceed?"
|
|
548
470
|
- **Round 3+ early exit**: still allow immediate exit if the user says "enough", "let's go", "build it".
|
|
549
|
-
- **Round 100 (hard cap)**: "Maximum interview rounds reached. Proceeding with current clarity level ({
|
|
471
|
+
- **Round 100 (hard cap)**: "Maximum interview rounds reached. Proceeding with current clarity level ({<native>.native_projection.effective_ambiguity}%)." The tiered cadence never removes this hard safety cap.
|
|
550
472
|
|
|
551
473
|
## Phase 3: Lateral Review Panel (milestone-triggered)
|
|
552
474
|
|
|
553
|
-
The
|
|
554
|
-
|
|
555
|
-
| Band | Ambiguity |
|
|
556
|
-
|------|-----------|
|
|
557
|
-
| `initial` | > 0.60 |
|
|
558
|
-
| `progress` | 0.60 ≥ a > 0.30 |
|
|
559
|
-
| `refined` | 0.30 ≥ a > threshold |
|
|
560
|
-
| `ready` | ≤ threshold |
|
|
475
|
+
The runtime returns the sole ready-first milestone mapping: `ready` when effective ambiguity is at or below the frozen threshold; otherwise `initial` above 0.60, `progress` above 0.30, and `refined` at or below 0.30. Use the returned milestone rather than recalculating bands.
|
|
561
476
|
|
|
562
477
|
A transition occurs whenever the band changes versus the prior scored round — in either direction, since bidirectional scoring can move the band back up. On a transition, and also before synthesizing any agent-supplied answer (auto-research candidates, an auto-answer, or a code/brownfield auto-confirm that carries real interpretation), convene the panel before generating or asking the next question.
|
|
563
478
|
|
|
@@ -657,7 +572,7 @@ Spec structure:
|
|
|
657
572
|
{List stable confirmed decisions promoted into `state.established_facts`, including source round, evidence, and disputed status when any fact was contradicted.}
|
|
658
573
|
|
|
659
574
|
## Trigger Metadata
|
|
660
|
-
{Summarize per-round trigger metadata: trigger label/status, affected component/dimension,
|
|
575
|
+
{Summarize per-round trigger metadata: trigger label/status, affected component/dimension, native-returned effective ambiguity transition, evidence, contradicted established fact when relevant, and disputed/unresolved rationale when applicable.}
|
|
661
576
|
|
|
662
577
|
## Lateral Review Panel
|
|
663
578
|
{Summarize convened panels: round, milestone transition or pre-answer trigger, personas dispatched, and the concrete findings folded into questions. Note any lateral_panel_failures.}
|
|
@@ -800,7 +715,7 @@ Skipping any stage is possible but reduces quality assurance:
|
|
|
800
715
|
- Use `read/search/find exploration or a bounded read-only planner/architect subagent` for brownfield codebase exploration (run BEFORE asking user about codebase)
|
|
801
716
|
- Use opus model (temperature 0.1) for ambiguity scoring — consistency is critical
|
|
802
717
|
- Round 0 topology confirmation happens before ambiguity scoring; Phase 2 scoring must honor locked topology and rotate targeting across active components when more than one is present
|
|
803
|
-
-
|
|
718
|
+
- Normal interview persistence uses CLI-owned drafts: `gjc deep-interview draft create|edit|show|check|rebase|discard`, followed by the matching typed command with `--draft-id --expected-draft-revision <latest_draft_revision> --json`. All public draft commands require standalone `--json`; value-taking flags use exactly `--name value`, while `--json` and `--null` take no value, and there is no public `draft consume` command. Use `--value`, standalone `--null`, and append scaffolds for bounded payload fields: valueless append on a missing object-item array appends `{}`, valueless append on a missing scalar-item array initializes `[]`, and appending to an existing scalar-item array requires `--value` or `--value-file`. Retain each returned `draft_revision`. `check` reports a stale state base but does not mutate; explicitly `rebase` only with the caller-observed `--to-state-revision` and then check again. Inline JSON request flags are compatibility-only. Never construct a full payload or generic `gjc state write --input` envelope. Generic `gjc state` remains compatibility/recovery-only for the explicit clear and final handoff paths; never edit `.gjc/_session-{sessionid}/state` directly without force override.
|
|
804
719
|
- 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.
|
|
805
720
|
- 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.
|
|
806
721
|
- 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
|
|
@@ -942,7 +857,7 @@ Optional settings in `.gjc/settings.json`:
|
|
|
942
857
|
|
|
943
858
|
## Resume
|
|
944
859
|
|
|
945
|
-
If interrupted, run `/skill:deep-interview` again.
|
|
860
|
+
If interrupted, run `/skill:deep-interview` again. Resume through `gjc deep-interview inspect --session-id <id> --selector summary --json`, then selectively inspect topology, pending shells, recent scored rounds, facts, triggers, or floor as needed; do not read or edit `.gjc/_session-{sessionid}/state` files directly unless an explicit force override is active.
|
|
946
861
|
|
|
947
862
|
## Integration with staged team routing
|
|
948
863
|
|
|
@@ -30,7 +30,7 @@ function toolResultHasError(result: AgentToolResult): boolean {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
function getTool(session: ToolSession, name: string): AgentTool {
|
|
33
|
-
const tool = session.getToolByName?.(name);
|
|
33
|
+
const tool = session.getToolForExecution ? session.getToolForExecution(name) : session.getToolByName?.(name);
|
|
34
34
|
if (!tool) {
|
|
35
35
|
throw new ToolError(`Unknown tool from js runtime: ${name}`);
|
|
36
36
|
}
|