@gajae-code/coding-agent 0.11.8 → 0.11.9

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.
Files changed (57) hide show
  1. package/CHANGELOG.md +18 -1
  2. package/dist/types/cli.d.ts +1 -0
  3. package/dist/types/config/model-profiles.d.ts +2 -3
  4. package/dist/types/gjc-runtime/deep-interview-ambiguity.d.ts +12 -5
  5. package/dist/types/gjc-runtime/deep-interview-draft.d.ts +8 -0
  6. package/dist/types/gjc-runtime/deep-interview-payload.d.ts +41 -0
  7. package/dist/types/gjc-runtime/deep-interview-recorder.d.ts +32 -17
  8. package/dist/types/gjc-runtime/deep-interview-repair.d.ts +17 -0
  9. package/dist/types/gjc-runtime/deep-interview-state.d.ts +135 -4
  10. package/dist/types/gjc-runtime/state-writer.d.ts +44 -0
  11. package/dist/types/gjc-runtime/workflow-manifest.d.ts +5 -3
  12. package/dist/types/modes/components/welcome.d.ts +2 -0
  13. package/dist/types/runtime-mcp/redaction.d.ts +2 -0
  14. package/dist/types/sdk/bus/chat-daemon-control.d.ts +3 -1
  15. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +3 -1
  16. package/dist/types/session/internal/managed-session-scope.d.ts +12 -2
  17. package/dist/types/session/internal/managed-session-storage.d.ts +8 -3
  18. package/dist/types/session/session-manager.d.ts +5 -1
  19. package/dist/types/session/session-storage.d.ts +13 -0
  20. package/dist/types/skill-state/active-state.d.ts +4 -0
  21. package/package.json +8 -8
  22. package/src/cli/mcp-cli.ts +4 -21
  23. package/src/cli.ts +32 -0
  24. package/src/commands/deep-interview.ts +9 -4
  25. package/src/commit/agentic/index.ts +3 -3
  26. package/src/commit/map-reduce/index.ts +2 -2
  27. package/src/config/model-profiles.ts +2 -3
  28. package/src/defaults/gjc/skills/deep-interview/SKILL.md +78 -163
  29. package/src/gjc-runtime/deep-interview-ambiguity.ts +68 -47
  30. package/src/gjc-runtime/deep-interview-draft.ts +842 -0
  31. package/src/gjc-runtime/deep-interview-payload.ts +262 -0
  32. package/src/gjc-runtime/deep-interview-recorder.ts +294 -226
  33. package/src/gjc-runtime/deep-interview-repair.ts +1674 -0
  34. package/src/gjc-runtime/deep-interview-runtime.ts +264 -103
  35. package/src/gjc-runtime/deep-interview-state.ts +916 -4
  36. package/src/gjc-runtime/ralplan-runtime.ts +3 -1
  37. package/src/gjc-runtime/state-writer.ts +166 -2
  38. package/src/gjc-runtime/workflow-manifest.generated.json +386 -1
  39. package/src/gjc-runtime/workflow-manifest.ts +191 -5
  40. package/src/internal-urls/docs-index.generated.ts +3 -2
  41. package/src/modes/components/welcome.ts +10 -2
  42. package/src/modes/interactive-mode.ts +29 -9
  43. package/src/prompts/system/system-prompt.md +1 -0
  44. package/src/runtime-mcp/json-rpc.ts +7 -4
  45. package/src/runtime-mcp/redaction.ts +30 -0
  46. package/src/sdk/broker/session-index.ts +11 -1
  47. package/src/sdk/bus/chat-daemon-control.ts +5 -3
  48. package/src/sdk/bus/telegram-daemon-contract.ts +3 -1
  49. package/src/sdk/bus/telegram-daemon.ts +18 -2
  50. package/src/session/agent-session.ts +86 -0
  51. package/src/session/internal/managed-session-scope.ts +206 -111
  52. package/src/session/internal/managed-session-storage.ts +17 -4
  53. package/src/session/session-manager.ts +96 -33
  54. package/src/session/session-storage.ts +23 -0
  55. package/src/skill-state/active-state.ts +10 -0
  56. package/src/task/executor.ts +13 -5
  57. package/src/tools/ask.ts +1 -0
package/CHANGELOG.md CHANGED
@@ -2,6 +2,21 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.11.9] - 2026-07-24
6
+
7
+ ### Fixed
8
+
9
+ - Alibaba Token Plan canonical first-event timeouts now surface without session retry/fallback replay and are not internally retried by auto-compaction, preventing repeated provider usage (#3026).
10
+
11
+ - Telegram notification topics now fence malformed successful `createForumTopic` responses per session endpoint, preventing repeated ambiguous topic creation while keeping explicit Bot API failures retryable.
12
+ - Windows managed-session resume no longer reports `durability_failed` when Bun rejects `fsync` on the read-only descriptor used to revalidate an existing canonical binding; Windows now uses an owner-writable descriptor for that durability fence while retaining no-follow and pre/post identity/content checks.
13
+ - SDK daemon CLI end-to-end tests now drain spawned child stdout and stderr concurrently with process exit, preventing CI pipe teardown races from replacing the product exit contract with SIGPIPE status 141 (#3024).
14
+ - Interactive launch bootstrap is now suppressed for parser-accepted `--print=`, `--help=`, and `--version=` equals forms, keeping non-interactive output free of the warming-workspace preamble on TTYs.
15
+ - Managed legacy-session artifact migration now accepts up to 50,000 files, processes copy work in bounded batches, and reports capacity exhaustion separately from unsafe artifact topology (#2935).
16
+ - Kimi Code first-event timeouts now surface after the provider's continuous first-event wait instead of replaying the full request from zero.
17
+
18
+ - Rejected subagent schema payloads now retain their complete structured data in canonical output artifacts; inline results remain bounded while `agent://` output stays lossless (#2894).
19
+ - Managed legacy-session artifact migration now validates Windows directory roots from the native tree snapshot, tolerates only lazy metadata on plain Windows directories, and replays both clean and cleanup-pending detaches while retaining fail-closed receipt validation. Canonical binding durability sync uses a writable no-follow handle on Windows NTFS stacks that reject `FlushFileBuffers` on read-only handles (#3015, #2913).
5
20
  ## [0.11.8] - 2026-07-23
6
21
  ### Added
7
22
 
@@ -15,6 +30,7 @@
15
30
 
16
31
  - Runtime MCP OAuth credentials are now bound to their authorized server origin and token endpoint, reject redirecting refresh responses, and fail closed when legacy or changed configuration lacks an exact match.
17
32
  - `/share` now keeps full-session HTML in owner-private unpredictable staging until the share handler or `gh gist create` process has fully stopped; cancelling a blocked gist upload terminates and awaits that process before reporting cancellation and removing the export.
33
+ - MCP diagnostics now redact opaque endpoint paths, user information, query values, and fragments without changing outbound requests, and parse-failure logs omit response bodies that could echo request secrets.
18
34
  - Telegram notification daemon self-heals degraded on-disk state: permanently missing scan roots are pruned (so one deleted worktree no longer disables orphan-topic cleanup), and retained exact-unlink transition/placeholder artifacts are reaped on ownership acquire and each scan. `gjc daemon reload` can recover without manual filesystem surgery (#2956).
19
35
  - On macOS, resuming a managed session no longer fails with `identity_mismatch` when the first write-append open changes only file `ctime` (e.g. APFS write-provenance / `com.apple.provenance`). `appendSync` allows a single bounded re-capture + retry when `dev`/`ino`/`size`/`mtime`/SHA-256 remain unchanged, and still rejects real content races and repeated ctime transitions (#2944).
20
36
  - Interactive `/resume` / `AgentSession.switchSession()` now awaits verified managed `local://` legacy-root migration for the newly selected session before post-commit lifecycle proceeds, matching cold-start `createAgentSession()` readiness from #2797 so synchronous `local://` resolution no longer fails with "legacy migration must complete before path resolution" after a mid-session switch (#2925).
@@ -45,6 +61,7 @@
45
61
  - ACP session close now rotates idempotency keys for resumed attachment generations while retaining the same key across terminally uncertain close retries.
46
62
  - ConversationStore now tolerates only unsupported Windows parent-directory durability errors after preserving temporary-file fsync and atomic rename.
47
63
  - Ralplan no longer re-asks for execution approval when the user already explicitly named `ultragoal` or `team` in the current turn; that naming is the consent.
64
+ - Interactive Windows startup now stays keyboard-ready with large session histories and native multiplexers by showing an interactive-only bootstrap before the first TUI start, deferring bounded recent-session discovery until afterward, and reducing psmux frame pressure while preserving the three-second animation and update checks.
48
65
 
49
66
  - Cron guidance now routes silent recurring polling and event-driven PR/CI watchers to `monitor`, because every cron firing starts a normal assistant turn and prompt wording cannot reliably suppress its response.
50
67
  - Ordinary `ask` calls now normalize a provider-emitted `deepInterview: null` placeholder instead of misclassifying it as malformed Round-0 intent recovery data and rejecting it before coercion.
@@ -269,11 +286,11 @@
269
286
 
270
287
  ## [0.10.1] - 2026-07-13
271
288
 
289
+ - Deep-interview bundled guidance now uses the typed native setup, topology, answer-recovery, round-result, selective inspection, and sanity-check commands for normal workflow state changes. Generic `gjc state` remains limited to documented compatibility/recovery handoff paths; ambiguity, receipts, revisions, topology persistence, and diagnosis/repair remain runtime-owned.
272
290
  ### Added
273
291
 
274
292
  - Added an owner-proof idle session reaper and `gjc_coordinator_stop_session` for ephemeral (delegate-created) coordinator sessions. Termination goes exclusively through the canonical SDK broker `session.close` lifecycle (durable process identity verified before close) — never a raw `process.kill` or tmux control. The reaper re-validates ephemeral and no-active-turn state at close time under the same per-session mutation lock as delegate reuse, and purges coordinator metadata only after SDK closure is verified, retaining it when closure cannot be confirmed (#2080).
275
293
 
276
- - Added an owner-proof idle session reaper and `gjc_coordinator_stop_session` for ephemeral (delegate-created) coordinator sessions. Termination goes exclusively through the owner-proof `forceCloseGjcTmuxSession` path (pid, native session id, owner generation, server key, and start time all verified before SIGTERM) — never a raw `process.kill`. The reaper binds each close to the persisted runtime-state file, re-validates ephemeral and no-active-turn at kill time under the same per-session mutation lock as delegate reuse, and purges state only on verified termination (#2080).
277
294
  - SDK clients can now pass an explicit thinking level to `model.set`, atomically applying the effective model and thinking level to the active session and the machine-global default for future sessions, while project policy and resumed session history retain precedence.
278
295
  - Context-usage tokens/% now use provider-reported usage as the single source of truth on every surface. `AgentSession.getContextUsage()` returns a source-tagged snapshot (`source: "provider_anchor" | "heuristic" | "unknown"`), and the status-line `context_pct` segment, inline model percentage, and `/context` totals consume that snapshot instead of recomputing an independent heuristic sum — so footer, status line, `/context`, ACP, and RPC can no longer disagree about the same session state. Heuristic estimation now applies only when no provider anchor exists (session start, aborted/error-only turns), and that fallback now includes the fixed system-prompt/tool/skill context it previously omitted. The pre-prompt compaction estimate honors the latest-compaction boundary (never anchors on stale pre-compaction usage totals), unknown post-compaction usage stays unknown (status line renders `?`; ACP omits the `usage_update` instead of reporting `used: 0`), and `/context` labels its total by provenance with a reconciliation line when the estimated category composition diverges from the provider-reported total.
279
296
  - Post-durable default-model-selection failures now expose a stable SDK error with bounded `restored`, `partial`, or `unknown` rollback state; preflight and validation errors remain unchanged.
@@ -6,6 +6,7 @@
6
6
  import "@gajae-code/utils/postmortem";
7
7
  import { Command, type CommandEntry } from "@gajae-code/utils/cli";
8
8
  export declare const commands: CommandEntry[];
9
+ export declare function interactiveBootstrapText(argv: readonly string[], stdinIsTTY?: boolean, stdoutIsTTY?: boolean): string | undefined;
9
10
  export declare class RootHelpCommand extends Command {
10
11
  static description: string;
11
12
  static hidden: boolean;
@@ -1,7 +1,6 @@
1
- import type { GjcModelAssignmentTargetId } from "./model-registry";
2
1
  import { type ModelSelectorValue } from "./model-selector-value";
3
- import type { ModelsConfig } from "./models-config-schema";
4
- export type ModelProfileRole = GjcModelAssignmentTargetId;
2
+ import type { GJC_MODEL_ASSIGNMENT_TARGET_IDS, ModelsConfig } from "./models-config-schema";
3
+ export type ModelProfileRole = (typeof GJC_MODEL_ASSIGNMENT_TARGET_IDS)[number];
5
4
  export interface ModelProfileDefinition {
6
5
  name: string;
7
6
  requiredProviders: string[];
@@ -9,15 +9,13 @@ export interface AmbiguityClampResult {
9
9
  effective: number;
10
10
  clamped: boolean;
11
11
  }
12
- /** Compute the deterministic floor from the inner deep-interview `state` object. */
12
+ /** Compute the deterministic floor from integer units of persisted evidence. */
13
13
  export declare function computeAmbiguityFloor(inner: unknown): AmbiguityFloorBreakdown;
14
14
  /** Clamp an LLM-reported ambiguity to the deterministic floor: `max(reported, floor)`. */
15
15
  export declare function clampReportedAmbiguity(reported: number, floor: number): AmbiguityClampResult;
16
16
  /**
17
- * Mark every established fact recorded in `retractedRound` as disputed. This is the
18
- * mechanical contradiction signal for answer retraction: when the user replaces an
19
- * already-scored answer (A -> B pivot), the facts that answer established can no
20
- * longer be trusted, so they raise the floor until re-confirmed or superseded.
17
+ * Legacy pure utility for migrations and explicit repair flows. The recorder does
18
+ * not dispute facts when an answer is retracted: scored evidence is immutable.
21
19
  * Returns new arrays/objects; never mutates the input.
22
20
  */
23
21
  export declare function disputeFactsFromRetractedRound(facts: readonly unknown[], retractedRound: number): {
@@ -37,3 +35,12 @@ export interface AppliedAmbiguityFloor {
37
35
  * (state CLI write/reconcile, recorder) applies this immediately before persisting.
38
36
  */
39
37
  export declare function applyAmbiguityFloorToEnvelope(value: unknown): AppliedAmbiguityFloor;
38
+ export type DeepInterviewAmbiguityMilestone = "initial" | "progress" | "refined" | "ready";
39
+ export declare function deriveAmbiguityMilestone(effectiveUnits: number, thresholdUnits: number): DeepInterviewAmbiguityMilestone;
40
+ export declare function scoreToUnits(score: number): number;
41
+ export declare function weightedAmbiguityUnits(scores: {
42
+ goal: number;
43
+ constraints: number;
44
+ criteria: number;
45
+ context?: number;
46
+ }, type: "greenfield" | "brownfield"): number;
@@ -0,0 +1,8 @@
1
+ import { type DeepInterviewDraftKind } from "./deep-interview-payload";
2
+ export interface DeepInterviewDraftResult {
3
+ status: number;
4
+ stdout?: string;
5
+ stderr?: string;
6
+ }
7
+ export declare function runDeepInterviewDraftCommand(input: readonly string[], cwd: string): Promise<DeepInterviewDraftResult>;
8
+ export declare function runDeepInterviewDraftInternalConsumeCommand(draftId: string, expectedDraftRevision: number, kind: DeepInterviewDraftKind, cwd: string): Promise<DeepInterviewDraftResult>;
@@ -0,0 +1,41 @@
1
+ import type { DeepInterviewRoundResultV1 } from "./deep-interview-state";
2
+ export declare const DEEP_INTERVIEW_DRAFT_KINDS: readonly ["initialize-context", "confirm-topology", "record-answer", "apply-round-result"];
3
+ export type DeepInterviewDraftKind = (typeof DEEP_INTERVIEW_DRAFT_KINDS)[number];
4
+ export type DeepInterviewDraftPayload = Record<string, unknown>;
5
+ export type DraftScalarType = "string" | "id" | "text" | "score" | "number" | "safe-int" | "boolean" | "enum";
6
+ export interface DraftLeafDescriptor {
7
+ kind: "leaf";
8
+ type: DraftScalarType;
9
+ nullable?: boolean;
10
+ maxBytes?: number;
11
+ values?: readonly string[];
12
+ optional?: boolean;
13
+ dynamicMapValue?: boolean;
14
+ }
15
+ export interface DraftObjectDescriptor {
16
+ kind: "object";
17
+ fields: Record<string, DraftDescriptor>;
18
+ optional?: boolean;
19
+ dynamicMapValue?: boolean;
20
+ dynamicValue?: DraftLeafDescriptor;
21
+ }
22
+ export interface DraftArrayDescriptor {
23
+ kind: "array";
24
+ item: DraftLeafDescriptor | DraftObjectDescriptor;
25
+ maxItems: number;
26
+ optional?: boolean;
27
+ }
28
+ export type DraftDescriptor = DraftLeafDescriptor | DraftObjectDescriptor | DraftArrayDescriptor;
29
+ export declare function deepInterviewDraftSchema(kind: DeepInterviewDraftKind): DraftObjectDescriptor;
30
+ /** Shared strict payload decoders used by compatibility JSON and CLI-owned drafts. */
31
+ export declare function decodeInitializeContextPayload(payload: unknown): Record<string, unknown>;
32
+ export declare function decodeConfirmTopologyPayload(payload: unknown): Record<string, unknown>;
33
+ export declare function decodeRecordAnswerPayload(payload: unknown): {
34
+ question: string;
35
+ answer: {
36
+ selected_options: string[];
37
+ custom_input: string | null;
38
+ };
39
+ };
40
+ export declare function decodeApplyRoundResultPayload(payload: unknown, state: Record<string, unknown>): DeepInterviewRoundResultV1;
41
+ export declare function validateDraftPayload(kind: DeepInterviewDraftKind, payload: unknown, state?: Record<string, unknown>): void;
@@ -1,4 +1,4 @@
1
- import { type DeepInterviewEstablishedFact, type DeepInterviewIntentItem, type DeepInterviewIntentSubstitution, type DeepInterviewRoundRecord, type DeepInterviewStateEnvelope, type DeepInterviewTriggerMetadata } from "./deep-interview-state";
1
+ import { type DeepInterviewEstablishedFact, type DeepInterviewIntentItem, type DeepInterviewIntentSubstitution, type DeepInterviewRoundRecord, type DeepInterviewRoundResultV1, type DeepInterviewStateEnvelope, type DeepInterviewTriggerMetadata } from "./deep-interview-state";
2
2
  export * from "./deep-interview-ambiguity";
3
3
  export * from "./deep-interview-state";
4
4
  /**
@@ -40,6 +40,8 @@ export interface DeepInterviewScoringInput {
40
40
  scores: Record<string, number>;
41
41
  ambiguity: number;
42
42
  triggers?: DeepInterviewTriggerMetadata[];
43
+ /** Complete native round result for typed callers. */
44
+ roundResult?: DeepInterviewRoundResultV1;
43
45
  }
44
46
  export type AppendOrMergeAction = "created" | "noop" | "replaced";
45
47
  export interface AppendOrMergeResult {
@@ -67,11 +69,9 @@ export interface TransitionValidationResult {
67
69
  }
68
70
  export declare function buildAnswerShell(input: DeepInterviewAnswerInput, now?: string): DeepInterviewRoundRecord;
69
71
  /**
70
- * Append-or-merge by `round_key`. Exactly one record per key:
71
- * - no existing record -> append (`created`);
72
- * - identical question_hash + answer_hash -> deterministic no-op (`noop`);
73
- * - same key, different hashes -> deterministic replacement of the prior shell
74
- * (`replaced`); the prior answer for that key is superseded and lifecycle resets.
72
+ * Append-or-merge by `round_key`. An answer is a no-op only when its complete
73
+ * canonical shell identity matches; a scored record is immutable evidence and
74
+ * cannot be replaced by a late answer.
75
75
  */
76
76
  export declare function appendOrMergeRound(rounds: readonly DeepInterviewRoundRecord[], shell: DeepInterviewRoundRecord): AppendOrMergeResult;
77
77
  /**
@@ -94,28 +94,43 @@ export declare function ensureDeepInterviewStateShape(value: unknown): DeepInter
94
94
  export declare function projectCompactState(value: unknown, options?: {
95
95
  lastN?: number;
96
96
  }): DeepInterviewCompactState;
97
+ interface RecorderMutationOptions {
98
+ sessionId?: string;
99
+ expectedRevision?: number;
100
+ }
101
+ export interface DeepInterviewPostCommitWarning {
102
+ code: "DI_POST_COMMIT_AUDIT_FAILED" | "DI_POST_COMMIT_ACTIVITY_FAILED" | "DI_POST_COMMIT_HUD_FAILED";
103
+ message: string;
104
+ }
105
+ export declare function runDeepInterviewPostCommitEffects(options: {
106
+ cwd: string;
107
+ statePath: string;
108
+ sessionId: string;
109
+ envelope: Record<string, unknown>;
110
+ revision: number;
111
+ writer: string;
112
+ auditWarnings?: readonly {
113
+ code: "DI_POST_COMMIT_AUDIT_FAILED";
114
+ message: string;
115
+ }[];
116
+ }): Promise<DeepInterviewPostCommitWarning[]>;
97
117
  /** Refresh the best-effort HUD cache from persisted deep-interview state. */
98
118
  export declare function syncDeepInterviewRecorderHud(cwd: string, statePath: string, sessionId: string | undefined): Promise<void>;
99
119
  /**
100
120
  * Record an `answered` shell for one round (append-or-merge by durable key).
101
121
  *
102
- * Retraction dynamics: replacing an already-`scored` answer is a mechanical
103
- * contradiction signal (the user pivoted). The facts that round established are
104
- * marked disputed, which raises the deterministic ambiguity floor immediately —
105
- * without waiting for the LLM scorer to self-report a trigger.
122
+ * Replacing an already-scored answer is rejected with
123
+ * `DI_ANSWER_LIFECYCLE_CONFLICT`; scored evidence is immutable.
106
124
  */
107
- export declare function appendOrMergeDeepInterviewRound(cwd: string, statePath: string, input: DeepInterviewAnswerInput, options?: {
108
- sessionId?: string;
109
- }): Promise<{
125
+ export declare function appendOrMergeDeepInterviewRound(cwd: string, statePath: string, input: DeepInterviewAnswerInput, options?: RecorderMutationOptions): Promise<{
110
126
  action: AppendOrMergeAction;
111
127
  record: DeepInterviewRoundRecord;
112
- disputedFactIds?: string[];
128
+ warnings: DeepInterviewPostCommitWarning[];
113
129
  }>;
114
130
  /** Merge scoring output into the same round record, transitioning to `scored`. */
115
- export declare function enrichDeepInterviewRoundScoring(cwd: string, statePath: string, input: DeepInterviewScoringInput, options?: {
116
- sessionId?: string;
117
- }): Promise<{
131
+ export declare function enrichDeepInterviewRoundScoring(cwd: string, statePath: string, input: DeepInterviewScoringInput, options?: RecorderMutationOptions): Promise<{
118
132
  record: DeepInterviewRoundRecord;
133
+ warnings: DeepInterviewPostCommitWarning[];
119
134
  }>;
120
135
  /** Compact projection so callers read a slice instead of the full transcript. */
121
136
  export declare function readDeepInterviewStateCompact(statePath: string, options?: {
@@ -0,0 +1,17 @@
1
+ import { type DeepInterviewRoundResultV1 } from "./deep-interview-state";
2
+ export interface DeepInterviewRepairResult {
3
+ status: number;
4
+ stdout?: string;
5
+ stderr?: string;
6
+ }
7
+ export declare const DEEP_INTERVIEW_REPAIR_VERBS: readonly ["initialize-context", "confirm-topology", "record-answer", "apply-round-result", "inspect", "sanity-check"];
8
+ export type DeepInterviewRepairVerb = (typeof DEEP_INTERVIEW_REPAIR_VERBS)[number];
9
+ export declare function isDeepInterviewRepairVerb(value: string): value is DeepInterviewRepairVerb;
10
+ export declare function decodeDeepInterviewAnswerJson(value: unknown): {
11
+ selected_options: string[];
12
+ custom_input: string | null;
13
+ };
14
+ export declare function decodeDeepInterviewRoundResultJson(value: unknown, state: Record<string, unknown>): DeepInterviewRoundResultV1;
15
+ export declare function decodeDeepInterviewSetupJson(value: unknown): Record<string, unknown>;
16
+ export declare function decodeDeepInterviewTopologyJson(value: unknown): Record<string, unknown>;
17
+ export declare function runDeepInterviewRepairCommand(args: readonly string[], cwd: string): Promise<DeepInterviewRepairResult>;
@@ -1,3 +1,4 @@
1
+ import { computeAmbiguityFloor, type DeepInterviewAmbiguityMilestone } from "./deep-interview-ambiguity";
1
2
  /**
2
3
  * Pure, dependency-free foundation for deep-interview state shape.
3
4
  *
@@ -35,10 +36,6 @@ export interface DeepInterviewTriggerMetadata {
35
36
  status: DeepInterviewTriggerStatus;
36
37
  component: string;
37
38
  dimension: string;
38
- priorDimensionScore?: number;
39
- newDimensionScore?: number;
40
- priorAmbiguity?: number;
41
- newAmbiguity?: number;
42
39
  evidence?: string;
43
40
  contradictedFactId?: string;
44
41
  /** Required when status is `disputed` or `unresolved` to exempt the invariant. */
@@ -68,9 +65,11 @@ export interface DeepInterviewRoundRecord {
68
65
  /** Deterministic floor in effect when this round was scored, when it clamped. */
69
66
  ambiguity_floor?: number;
70
67
  triggers?: DeepInterviewTriggerMetadata[];
68
+ round_result_digest?: string;
71
69
  }
72
70
  export interface DeepInterviewStateEnvelope {
73
71
  threshold?: number;
72
+ threshold_units?: number;
74
73
  threshold_source?: string;
75
74
  state?: Record<string, unknown>;
76
75
  [key: string]: unknown;
@@ -197,3 +196,135 @@ export declare function assertDeepInterviewIntentReview(value: unknown, locked:
197
196
  round: unknown;
198
197
  answer_hash: unknown;
199
198
  }[]): asserts value is DeepInterviewIntentReview;
199
+ export type DeepInterviewDimension = "goal" | "constraints" | "criteria" | "context";
200
+ export type DeepInterviewResolution = "auto_research_accepted" | "auto_answer" | "direct" | "refined" | "cited_confirmation";
201
+ export interface DeepInterviewFactOperation {
202
+ op: "add" | "dispute" | "supersede";
203
+ id: string;
204
+ statement?: string;
205
+ component?: string;
206
+ dimension?: DeepInterviewDimension;
207
+ evidence?: string;
208
+ target_id?: string;
209
+ }
210
+ export interface DeepInterviewOntologyEntity {
211
+ id: string;
212
+ name: string;
213
+ type: string;
214
+ fields: string[];
215
+ }
216
+ export interface DeepInterviewOntologyRelationship {
217
+ id: string;
218
+ from_entity_id: string;
219
+ to_entity_id: string;
220
+ type: string;
221
+ }
222
+ export interface DeepInterviewOntologyReasoning {
223
+ statement: string;
224
+ evidence?: string;
225
+ }
226
+ export interface DeepInterviewOntologyInput {
227
+ entities: DeepInterviewOntologyEntity[];
228
+ relationships: DeepInterviewOntologyRelationship[];
229
+ reasoning: DeepInterviewOntologyReasoning[];
230
+ }
231
+ export interface DeepInterviewComponentUpdate {
232
+ component_id: string;
233
+ scores: Record<DeepInterviewDimension, number>;
234
+ }
235
+ /**
236
+ * Optional legacy assertions accepted only when they agree with the native
237
+ * target. The persisted target is always derived from component scores.
238
+ */
239
+ export interface DeepInterviewTargetingInput {
240
+ target_component_id?: string;
241
+ target_dimension?: DeepInterviewDimension;
242
+ weakest_component_id?: string;
243
+ weakest_dimension?: DeepInterviewDimension;
244
+ last_targeted_component_id?: string | null;
245
+ }
246
+ export interface DeepInterviewRoundBookkeeping {
247
+ resolution: DeepInterviewResolution;
248
+ round_ids?: string[];
249
+ counter_deltas?: Record<string, number>;
250
+ }
251
+ /**
252
+ * Closed evidence submitted for one scoring transaction. All convergence values
253
+ * (ambiguity, floor, milestone, ontology counts, rotation, and streak) are
254
+ * native-derived and intentionally cannot be supplied here.
255
+ */
256
+ export interface DeepInterviewRoundResultV1 {
257
+ global_scores: Record<DeepInterviewDimension, number>;
258
+ component_updates?: DeepInterviewComponentUpdate[];
259
+ targeting?: DeepInterviewTargetingInput;
260
+ triggers?: DeepInterviewTriggerMetadata[];
261
+ fact_ops?: DeepInterviewFactOperation[];
262
+ ontology?: DeepInterviewOntologyInput | DeepInterviewOntologyEntity[];
263
+ bookkeeping?: DeepInterviewRoundBookkeeping;
264
+ /** Compatibility adapter for recorder callers; never persisted as the v1 wire shape. */
265
+ component_scores?: Record<string, Record<DeepInterviewDimension, number>>;
266
+ auto_answered?: boolean;
267
+ }
268
+ /**
269
+ * Version 1 native projection returned by `apply-round-result` as
270
+ * `native_projection`. This is the complete renderable convergence surface;
271
+ * callers must not derive or supplement it from candidate scorer input.
272
+ */
273
+ export interface DeepInterviewRoundResultProjection {
274
+ score_units: Partial<Record<DeepInterviewDimension, number>>;
275
+ weighted_ambiguity: number;
276
+ weighted_ambiguity_units: number;
277
+ floor: number;
278
+ floor_units: number;
279
+ floor_cause: ReturnType<typeof computeAmbiguityFloor>;
280
+ effective_ambiguity: number;
281
+ effective_ambiguity_units: number;
282
+ prior_effective_ambiguity: number | null;
283
+ direction: "increased" | "decreased" | "unchanged" | "initial";
284
+ ambiguity_milestone: DeepInterviewAmbiguityMilestone;
285
+ topology: unknown;
286
+ topology_counts: {
287
+ active: number;
288
+ deferred: number;
289
+ total: number;
290
+ };
291
+ ontology: unknown;
292
+ ontology_counts: {
293
+ stable: number;
294
+ changed: number;
295
+ new: number;
296
+ basis: string;
297
+ };
298
+ targeting: {
299
+ target_component_id: string | null;
300
+ target_dimension: DeepInterviewDimension | null;
301
+ last_targeted_component_id: string | null;
302
+ };
303
+ transition: {
304
+ round_key: string;
305
+ lifecycle: "scored";
306
+ auto_answer_streak: number;
307
+ };
308
+ }
309
+ export type DeepInterviewApplyRoundResult = {
310
+ kind: "noop";
311
+ envelope: DeepInterviewStateEnvelope;
312
+ projection?: DeepInterviewRoundResultProjection;
313
+ } | {
314
+ kind: "write";
315
+ envelope: DeepInterviewStateEnvelope;
316
+ projection: DeepInterviewRoundResultProjection;
317
+ };
318
+ /** Strict UTF-8 JSON serialization used by v1 replay digests. */
319
+ export declare function canonicalDeepInterviewJson(value: unknown): string;
320
+ export declare function deepInterviewRoundResultDigest(input: {
321
+ round: number;
322
+ question_id: string;
323
+ round_id?: string | null;
324
+ result: unknown;
325
+ }): string;
326
+ /** Complete persisted answer identity; omitted optional values normalize to null. */
327
+ export declare function deepInterviewAnswerIdentityEqual(a: Pick<DeepInterviewRoundRecord, "round" | "round_key" | "round_id" | "question_id" | "component" | "dimension" | "question_text" | "question_hash" | "selected_options" | "custom_input">, b: Pick<DeepInterviewRoundRecord, "round" | "round_key" | "round_id" | "question_id" | "component" | "dimension" | "question_text" | "question_hash" | "selected_options" | "custom_input">): boolean;
328
+ /** Apply one closed v1 scoring round. The input contains evidence only; all convergence state is derived here. */
329
+ export declare function applyDeepInterviewRoundResultV1(envelopeValue: unknown, roundKey: string, result: DeepInterviewRoundResultV1, now: string): DeepInterviewApplyRoundResult;
330
+ export declare function validateDeepInterviewV1Envelope(value: Record<string, unknown>): void;
@@ -46,6 +46,47 @@ export interface WorkflowEnvelopeIntegrityMismatch {
46
46
  expected: string;
47
47
  actual: string;
48
48
  }
49
+ export type WorkflowReceiptVerification = "legacy" | "native-valid" | "receipt-malformed" | "receipt-missing" | "checksum-mismatch";
50
+ export interface GuardedWorkflowEnvelopeTransformOptions extends StateWriterOptions {
51
+ expectedRevision: number;
52
+ /** Additional native schema validation applied to both current and candidate envelopes. */
53
+ validate?: (value: Record<string, unknown>, legacy: boolean) => void;
54
+ transform: (current: Record<string, unknown>, context: {
55
+ revision: number;
56
+ legacy: boolean;
57
+ }) => {
58
+ kind: "noop";
59
+ } | {
60
+ kind: "write";
61
+ value: Record<string, unknown>;
62
+ } | Promise<{
63
+ kind: "noop";
64
+ } | {
65
+ kind: "write";
66
+ value: Record<string, unknown>;
67
+ }>;
68
+ }
69
+ export interface GuardedWorkflowEnvelopeWarning {
70
+ code: "DI_POST_COMMIT_AUDIT_FAILED";
71
+ message: string;
72
+ }
73
+ export type GuardedWorkflowEnvelopeTransformResult = {
74
+ path: string;
75
+ written: false;
76
+ reason: "noop";
77
+ revision: number;
78
+ warnings: [];
79
+ } | {
80
+ path: string;
81
+ written: true;
82
+ revision: number;
83
+ stamped: Record<string, unknown>;
84
+ warnings: GuardedWorkflowEnvelopeWarning[];
85
+ };
86
+ export declare class GuardedWorkflowEnvelopeError extends Error {
87
+ readonly code: string;
88
+ constructor(code: string);
89
+ }
49
90
  export interface WorkflowTransactionJournal {
50
91
  version: 1;
51
92
  mutation_id: string;
@@ -80,6 +121,7 @@ export interface StateWriterOptions {
80
121
  receipt?: StateWriterReceiptContext;
81
122
  audit?: StateWriterAuditContext;
82
123
  sourceRevision?: number;
124
+ orderingRevision?: number;
83
125
  /**
84
126
  * Cross-process lock tuning for read-modify-write paths that route through
85
127
  * `withWorkflowStateLock` / `updateJsonAtomic`. Omit for the hardened
@@ -141,6 +183,7 @@ export type StrictMutationReadResult = {
141
183
  };
142
184
  export declare function readExistingStateForMutation(filePath: string): Promise<StrictMutationReadResult>;
143
185
  export declare function workflowEnvelopeContentSha256(value: unknown): string;
186
+ export declare function verifyWorkflowEnvelopeReceiptValue(value: unknown, filePath: string): WorkflowReceiptVerification;
144
187
  export declare function stampWorkflowEnvelopeChecksum<T>(value: T, filePath: string, computedAt?: string): T;
145
188
  export declare function detectWorkflowEnvelopeIntegrityMismatch(filePath: string): Promise<WorkflowEnvelopeIntegrityMismatch | undefined>;
146
189
  type ActiveStateCacheInvalidator = (cwd?: string, sessionId?: string) => void;
@@ -148,6 +191,7 @@ export declare function setActiveStateCacheInvalidator(invalidator: ActiveStateC
148
191
  export declare function persistedStateRevision(value: unknown): number;
149
192
  export declare function writeGuardedJsonAtomic(targetPath: string, value: unknown, options: GuardedStateWriterOptions): Promise<GuardedWriteResult>;
150
193
  export declare function writeGuardedWorkflowEnvelopeAtomic(targetPath: string, value: unknown, options: GuardedStateWriterOptions): Promise<GuardedWriteResult>;
194
+ export declare function transformGuardedWorkflowEnvelopeAtomic(targetPath: string, options: GuardedWorkflowEnvelopeTransformOptions): Promise<GuardedWorkflowEnvelopeTransformResult>;
151
195
  export declare function writeJsonAtomic(targetPath: string, value: unknown, options?: StateWriterOptions): Promise<string>;
152
196
  export declare function writeWorkflowEnvelopeAtomic(targetPath: string, value: unknown, options?: StateWriterOptions): Promise<string>;
153
197
  export declare function writeTextAtomic(targetPath: string, text: string, options?: StateWriterOptions): Promise<string>;
@@ -1,7 +1,6 @@
1
1
  /**
2
2
  * TypeScript is the authoritative source of truth for GJC workflow manifests.
3
- * Any JSON manifest projection is derived from this module and must never be
4
- * hand-edited.
3
+ * Keep the checked-in JSON projection synchronized manually with this module.
5
4
  */
6
5
  import { type CanonicalGjcWorkflowSkill } from "../skill-state/canonical-skills";
7
6
  export interface WorkflowState {
@@ -18,7 +17,9 @@ export interface WorkflowVerb {
18
17
  name: string;
19
18
  planned?: boolean;
20
19
  /** Invocation surface that exposes this verb in the real CLI parser. */
21
- surface?: "state-action" | "command-positional" | "command-flag";
20
+ surface?: "state-action" | "command-positional" | "command-flag" | "draft-action";
21
+ /** Legacy surface retained for callers that have not migrated to normal typed commands. */
22
+ compatibilityOnly?: boolean;
22
23
  }
23
24
  export interface TypedArgSpec {
24
25
  name: string;
@@ -26,6 +27,7 @@ export interface TypedArgSpec {
26
27
  enumValues?: string[];
27
28
  required?: boolean;
28
29
  appliesToVerbs?: string[];
30
+ compatibilityOnly?: boolean;
29
31
  planned?: boolean;
30
32
  }
31
33
  export interface RetentionPolicy {
@@ -45,3 +45,5 @@ export declare class WelcomeComponent implements Component {
45
45
  setLspServers(servers: LspServerInfo[]): void;
46
46
  render(termWidth: number): string[];
47
47
  }
48
+ /** Resolve the intro cadence without making tests mutate global process state. */
49
+ export declare function resolveWelcomeIntroTickMs(platform?: NodeJS.Platform, tmux?: string | undefined): number;
@@ -0,0 +1,2 @@
1
+ export declare function redactMCPEndpoint(value: string | undefined): string | undefined;
2
+ export declare function redactMCPDiagnosticValue(value: unknown): unknown;
@@ -13,7 +13,9 @@ export type ChatDaemonAction = "stop" | "reload";
13
13
  * authority declaration contract with bounded frame-delivery acknowledgement.
14
14
  * Generation 11 accepts typed retained exact-unlink cleanup authority — a
15
15
  * concrete detached quarantine plus a proven-absent canonical lock pathname —
16
- * when deleting an observed owner-lock lease.
16
+ * when deleting an observed owner-lock lease. Generation 12 refreshes retained
17
+ * native path and process authority semantics. Generation 13 rejects special
18
+ * files before retained native authority opens.
17
19
  */
18
20
  export declare const CHAT_DAEMON_GENERATIONS: Readonly<Record<ChatDaemonKind, number>>;
19
21
  export declare function chatDaemonGeneration(kind: ChatDaemonKind): number;
@@ -36,5 +36,7 @@ export declare const NOTIFICATION_PROTOCOL_VERSION = 3;
36
36
  * Generation 25 adds startup dead-root prune + leak-artifact self-heal
37
37
  * on TelegramNotificationDaemon.run (#2958). Generation 26 adds bounded reload
38
38
  * cooldown and lazy Telegram topic lifecycle safeguards (#2956, #2960, #2984).
39
+ * Generation 27 refreshes retained native path and process authority semantics.
40
+ * Generation 28 rejects special files before retained native authority opens.
39
41
  */
40
- export declare const DAEMON_GENERATION = 26;
42
+ export declare const DAEMON_GENERATION = 28;
@@ -1,6 +1,7 @@
1
1
  import * as native from "@gajae-code/natives";
2
2
  import type { ResumeSessionIdentity } from "../session-manager";
3
- import { type ManagedDirectoryRoot, type ManagedSessionSecurityPolicy } from "./managed-session-storage";
3
+ import { type NativeDirectoryTreeSnapshot } from "../session-storage";
4
+ import { type ManagedDirectoryRoot, type ManagedSessionSecurityPolicy, type ManagedStorageLock } from "./managed-session-storage";
4
5
  export declare const MANAGED_SESSION_LAYOUT_VERSION: 2;
5
6
  export declare const MANAGED_SESSION_IDENTITY_VERSION: 1;
6
7
  export declare const MANAGED_SESSION_BINDING_FILE = ".gjc-managed-session-scope.v2.json";
@@ -67,7 +68,7 @@ export type ManagedCandidateListing = {
67
68
  code: "scan_failed" | "unsafe_root" | "invalid_candidate";
68
69
  message: string;
69
70
  };
70
- export type ManagedOpenFailure = "migration_busy" | "binding_conflict" | "binding_invalid" | "destination_conflict" | "source_changed" | "unsafe_artifacts" | "durability_failed" | "atomic_unavailable" | "invalid_request" | "durability_not_provable" | "migration_retired" | "legacy_migration_disabled" | "managed_storage_unsupported";
71
+ export type ManagedOpenFailure = "migration_busy" | "binding_conflict" | "binding_invalid" | "destination_conflict" | "source_changed" | "unsafe_artifacts" | "artifact_capacity_exceeded" | "durability_failed" | "atomic_unavailable" | "invalid_request" | "durability_not_provable" | "migration_retired" | "legacy_migration_disabled" | "managed_storage_unsupported";
71
72
  export type ManagedOpenCandidateResult = {
72
73
  kind: "opened";
73
74
  path: string;
@@ -114,10 +115,19 @@ interface ManagedScopeInput {
114
115
  export declare function resolveManagedScope(input: ManagedScopeInput): ManagedScopeResolution;
115
116
  /** Resolve a scope for a synchronous write without mutating an existing ACL mismatch. */
116
117
  export declare function resolveManagedScopeForWrite(input: ManagedScopeInput): ManagedScopeResolution;
118
+ export declare function canonicalBindingOpenFlags(platform?: NodeJS.Platform): number;
119
+ export declare function fsyncCanonicalBinding(bindingPath: string, expected: string): void;
117
120
  export declare function ensureManagedScope(scope: ManagedScope, policy?: ManagedSessionSecurityPolicy): Promise<ManagedScopeResolution>;
118
121
  /** Synchronously create and validate the v2 binding before a default session writer exists. */
119
122
  export declare function prepareManagedSessionScopeForWriteSync(scope: ManagedScope, policy?: ManagedSessionSecurityPolicy, authority?: ManagedCandidateWriteAuthority): ManagedScopeResolution;
120
123
  export declare function listManagedCandidates(scope: ManagedScope): ManagedCandidateListing;
124
+ export declare function matchesMigrationArtifactRoot(pathname: string, identity: {
125
+ dev: bigint;
126
+ ino: bigint;
127
+ size: bigint;
128
+ mtimeNs: bigint;
129
+ }, expectedTree: NativeDirectoryTreeSnapshot, platform?: NodeJS.Platform): boolean;
130
+ export declare function restorePreparedArtifactRoot(scope: ManagedScope, source: ManagedCandidate, lock?: ManagedStorageLock): void;
121
131
  /** Resume tombstoned cleanup under its original operation lease without restoring retired candidates. */
122
132
  export declare function reconcileManagedTombstones(scope: ManagedScope): Promise<void>;
123
133
  /** Create the v2 binding and private write protocol directories before managed writes. */
@@ -1,9 +1,10 @@
1
1
  import { type NativeDirectoryTreeSnapshot, type NativeOwnerOnlySecurityResult, type RecoveryFsRoot } from "@gajae-code/natives";
2
2
  import { type NativePublishOutcome } from "./native-publish-outcome";
3
3
  export declare const MANAGED_ARTIFACT_MAX_DEPTH = 32;
4
- export declare const MANAGED_ARTIFACT_MAX_FILES = 10000;
4
+ export declare const MANAGED_ARTIFACT_MAX_FILES = 50000;
5
5
  export declare const MANAGED_ARTIFACT_MAX_FILE_BYTES: number;
6
6
  export declare const MANAGED_ARTIFACT_MAX_TOTAL_BYTES: number;
7
+ export declare const MANAGED_ARTIFACT_COPY_BATCH_SIZE = 256;
7
8
  export declare class ManagedPublishError extends Error {
8
9
  readonly classification: "destination_conflict" | "atomic_unavailable" | "invalid_request" | "durability_not_provable" | "identity_mismatch" | "io_error" | "durability_failed";
9
10
  readonly diagnostic: string;
@@ -12,7 +13,7 @@ export declare class ManagedPublishError extends Error {
12
13
  /** Cleanup is safe only when the native move reports that it did not commit. */
13
14
  export declare function mayCleanManagedTreeStaging(error: unknown): boolean;
14
15
  export type ManagedSessionSecurityPolicy = "default" | "windows-existing-verify-first";
15
- export type ManagedStorageFailure = "migration_busy" | "binding_conflict" | "binding_invalid" | "destination_conflict" | "source_changed" | "unsafe_artifacts" | "durability_failed" | "atomic_unavailable" | "durability_not_provable" | "migration_retired" | "managed_storage_unsupported";
16
+ export type ManagedStorageFailure = "migration_busy" | "binding_conflict" | "binding_invalid" | "destination_conflict" | "source_changed" | "unsafe_artifacts" | "artifact_capacity_exceeded" | "durability_failed" | "atomic_unavailable" | "durability_not_provable" | "migration_retired" | "managed_storage_unsupported";
16
17
  export interface ManagedStorageLock {
17
18
  path: string;
18
19
  attemptId: string;
@@ -104,8 +105,12 @@ export declare function replaceManagedFile(destination: string, bytes: Uint8Arra
104
105
  export declare function copyManagedFileNoReplace(source: string, destination: string, snapshot?: ManagedFileSnapshot, root?: ManagedDirectoryRoot, policy?: ManagedSessionSecurityPolicy): Promise<void>;
105
106
  /** Acquire a lease lock with bounded wait, heartbeats, conservative stale reclaim, and fencing. */
106
107
  export declare function acquireManagedLock(locksDirectory: string, name: string, root?: ManagedDirectoryRoot, policy?: ManagedSessionSecurityPolicy): Promise<ManagedStorageLock>;
108
+ export interface ManagedArtifactTreeLimits {
109
+ maxFiles?: number;
110
+ maxTotalBytes?: number;
111
+ }
107
112
  /** Bounds a no-follow artifact tree before it can be copied or deleted. */
108
- export declare function validateManagedArtifactTree(root: string): void;
113
+ export declare function validateManagedArtifactTree(root: string, limits?: ManagedArtifactTreeLimits): void;
109
114
  /** Flush a copied managed artifact tree, including empty directories, before publishing its receipt. */
110
115
  export declare function fsyncManagedArtifactTree(root: string): NativeDirectoryTreeSnapshot;
111
116
  export declare function publishManagedTombstone(destination: string, record: Record<string, unknown>, assertOwned?: () => void): Promise<void>;