@gajae-code/coding-agent 0.2.5 → 0.3.0

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 (112) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/types/async/job-manager.d.ts +84 -2
  3. package/dist/types/commands/harness.d.ts +37 -0
  4. package/dist/types/config/settings-schema.d.ts +6 -0
  5. package/dist/types/config/settings.d.ts +2 -0
  6. package/dist/types/deep-interview/render-middleware.d.ts +5 -0
  7. package/dist/types/extensibility/custom-tools/types.d.ts +1 -0
  8. package/dist/types/extensibility/extensions/types.d.ts +6 -0
  9. package/dist/types/extensibility/shared-events.d.ts +1 -0
  10. package/dist/types/gjc-runtime/state-graph.d.ts +4 -0
  11. package/dist/types/gjc-runtime/state-migrations.d.ts +24 -0
  12. package/dist/types/gjc-runtime/state-renderer.d.ts +65 -0
  13. package/dist/types/gjc-runtime/state-runtime.d.ts +2 -0
  14. package/dist/types/gjc-runtime/state-validation.d.ts +6 -0
  15. package/dist/types/gjc-runtime/state-writer.d.ts +137 -0
  16. package/dist/types/gjc-runtime/team-runtime.d.ts +81 -7
  17. package/dist/types/gjc-runtime/workflow-manifest.d.ts +54 -0
  18. package/dist/types/harness-control-plane/classifier.d.ts +13 -0
  19. package/dist/types/harness-control-plane/control-endpoint.d.ts +30 -0
  20. package/dist/types/harness-control-plane/finalize.d.ts +47 -0
  21. package/dist/types/harness-control-plane/frame-mapper.d.ts +29 -0
  22. package/dist/types/harness-control-plane/operate.d.ts +35 -0
  23. package/dist/types/harness-control-plane/owner.d.ts +46 -0
  24. package/dist/types/harness-control-plane/preserve.d.ts +19 -0
  25. package/dist/types/harness-control-plane/receipts.d.ts +88 -0
  26. package/dist/types/harness-control-plane/rpc-adapter.d.ts +66 -0
  27. package/dist/types/harness-control-plane/seams.d.ts +21 -0
  28. package/dist/types/harness-control-plane/session-lease.d.ts +65 -0
  29. package/dist/types/harness-control-plane/state-machine.d.ts +19 -0
  30. package/dist/types/harness-control-plane/storage.d.ts +53 -0
  31. package/dist/types/harness-control-plane/types.d.ts +162 -0
  32. package/dist/types/hooks/skill-keywords.d.ts +2 -1
  33. package/dist/types/hooks/skill-state.d.ts +2 -29
  34. package/dist/types/modes/components/hook-selector.d.ts +1 -0
  35. package/dist/types/modes/interactive-mode.d.ts +1 -0
  36. package/dist/types/modes/types.d.ts +1 -0
  37. package/dist/types/sdk.d.ts +2 -0
  38. package/dist/types/session/agent-session.d.ts +8 -0
  39. package/dist/types/skill-state/active-state.d.ts +2 -0
  40. package/dist/types/skill-state/deep-interview-mutation-guard.d.ts +1 -1
  41. package/dist/types/skill-state/workflow-state-contract.d.ts +24 -0
  42. package/dist/types/task/executor.d.ts +3 -0
  43. package/dist/types/task/types.d.ts +55 -3
  44. package/dist/types/tools/subagent.d.ts +11 -1
  45. package/package.json +7 -7
  46. package/src/async/job-manager.ts +298 -6
  47. package/src/cli/auth-broker-cli.ts +1 -0
  48. package/src/cli/config-cli.ts +10 -2
  49. package/src/cli.ts +2 -0
  50. package/src/commands/harness.ts +592 -0
  51. package/src/commands/team.ts +36 -39
  52. package/src/config/settings-schema.ts +7 -0
  53. package/src/config/settings.ts +5 -0
  54. package/src/deep-interview/render-middleware.ts +366 -0
  55. package/src/defaults/gjc/skills/team/SKILL.md +47 -21
  56. package/src/defaults/gjc/skills/ultragoal/SKILL.md +78 -11
  57. package/src/extensibility/custom-tools/types.ts +1 -0
  58. package/src/extensibility/extensions/types.ts +6 -0
  59. package/src/extensibility/shared-events.ts +1 -0
  60. package/src/gjc-runtime/deep-interview-runtime.ts +40 -21
  61. package/src/gjc-runtime/goal-mode-request.ts +11 -3
  62. package/src/gjc-runtime/ralplan-runtime.ts +25 -10
  63. package/src/gjc-runtime/state-graph.ts +86 -0
  64. package/src/gjc-runtime/state-migrations.ts +132 -0
  65. package/src/gjc-runtime/state-renderer.ts +345 -0
  66. package/src/gjc-runtime/state-runtime.ts +733 -21
  67. package/src/gjc-runtime/state-validation.ts +49 -0
  68. package/src/gjc-runtime/state-writer.ts +718 -0
  69. package/src/gjc-runtime/team-runtime.ts +1083 -89
  70. package/src/gjc-runtime/ultragoal-runtime.ts +348 -19
  71. package/src/gjc-runtime/workflow-manifest.generated.json +1497 -0
  72. package/src/gjc-runtime/workflow-manifest.ts +425 -0
  73. package/src/harness-control-plane/classifier.ts +128 -0
  74. package/src/harness-control-plane/control-endpoint.ts +137 -0
  75. package/src/harness-control-plane/finalize.ts +222 -0
  76. package/src/harness-control-plane/frame-mapper.ts +286 -0
  77. package/src/harness-control-plane/operate.ts +225 -0
  78. package/src/harness-control-plane/owner.ts +553 -0
  79. package/src/harness-control-plane/preserve.ts +102 -0
  80. package/src/harness-control-plane/receipts.ts +216 -0
  81. package/src/harness-control-plane/rpc-adapter.ts +276 -0
  82. package/src/harness-control-plane/seams.ts +39 -0
  83. package/src/harness-control-plane/session-lease.ts +388 -0
  84. package/src/harness-control-plane/state-machine.ts +97 -0
  85. package/src/harness-control-plane/storage.ts +257 -0
  86. package/src/harness-control-plane/types.ts +214 -0
  87. package/src/hooks/skill-keywords.ts +4 -2
  88. package/src/hooks/skill-state.ts +24 -41
  89. package/src/internal-urls/docs-index.generated.ts +1 -1
  90. package/src/modes/components/assistant-message.ts +5 -1
  91. package/src/modes/components/hook-selector.ts +72 -2
  92. package/src/modes/controllers/event-controller.ts +71 -6
  93. package/src/modes/controllers/extension-ui-controller.ts +6 -0
  94. package/src/modes/controllers/input-controller.ts +9 -1
  95. package/src/modes/controllers/selector-controller.ts +2 -1
  96. package/src/modes/interactive-mode.ts +1 -0
  97. package/src/modes/types.ts +1 -0
  98. package/src/prompts/agents/executor.md +13 -0
  99. package/src/prompts/tools/subagent.md +33 -3
  100. package/src/sdk.ts +4 -0
  101. package/src/session/agent-session.ts +231 -33
  102. package/src/session/session-manager.ts +13 -1
  103. package/src/skill-state/active-state.ts +58 -65
  104. package/src/skill-state/deep-interview-mutation-guard.ts +91 -13
  105. package/src/skill-state/initial-phase.ts +2 -0
  106. package/src/skill-state/workflow-state-contract.ts +26 -0
  107. package/src/task/executor.ts +50 -8
  108. package/src/task/index.ts +120 -8
  109. package/src/task/render.ts +6 -3
  110. package/src/task/types.ts +56 -3
  111. package/src/tools/ask.ts +28 -7
  112. package/src/tools/subagent.ts +255 -64
@@ -0,0 +1,65 @@
1
+ export interface SessionLease {
2
+ ownerId: string;
3
+ sessionId: string;
4
+ pid: number;
5
+ leaseTokenHash: string;
6
+ endpoint: {
7
+ kind: "unix-socket" | "fifo";
8
+ path: string;
9
+ } | null;
10
+ eventsPath: string;
11
+ heartbeatAt: string;
12
+ expiresAt: string;
13
+ leaseEpoch: number;
14
+ writer: {
15
+ ownerId: string;
16
+ leaseEpoch: number;
17
+ };
18
+ }
19
+ export declare class LeaseError extends Error {
20
+ readonly code: string;
21
+ constructor(message: string, code: string);
22
+ }
23
+ export type LeaseStatus = "missing" | "live" | "expiredAlive" | "dead" | "epermAlive";
24
+ type PidStatus = "alive" | "dead" | "eperm";
25
+ export declare function readLease(root: string, sessionId: string): Promise<SessionLease | null>;
26
+ export declare function isExpired(lease: SessionLease, clock?: () => number): boolean;
27
+ export declare function classifyLeaseStatus(lease: SessionLease | null, opts?: {
28
+ clock?: () => number;
29
+ probe?: (pid: number) => PidStatus;
30
+ }): LeaseStatus;
31
+ /** Liveness probe via signal 0. Defaults to the real process table; injectable for tests. */
32
+ export declare function isOwnerAlive(pid: number, probe?: (pid: number) => boolean): boolean;
33
+ export declare function isStale(lease: SessionLease, opts?: {
34
+ clock?: () => number;
35
+ probe?: (pid: number) => boolean;
36
+ }): boolean;
37
+ export interface AcquireOptions {
38
+ ownerId: string;
39
+ pid: number;
40
+ endpoint?: SessionLease["endpoint"];
41
+ eventsPath: string;
42
+ ttlMs: number;
43
+ clock?: () => number;
44
+ probe?: (pid: number) => boolean | PidStatus;
45
+ }
46
+ export interface AcquiredLease {
47
+ lease: SessionLease;
48
+ token: string;
49
+ }
50
+ /**
51
+ * Acquire (or take over a stale) lease. Fails closed with `lease_held` when a live,
52
+ * unexpired lease is held by a different owner. Re-acquiring as the current owner refreshes.
53
+ */
54
+ export declare function acquireLease(root: string, sessionId: string, opts: AcquireOptions): Promise<AcquiredLease>;
55
+ /** Refresh the lease expiry. Only the recorded owner may heartbeat (single-writer). */
56
+ export declare function heartbeat(root: string, sessionId: string, ownerId: string, ttlMs: number, clock?: () => number): Promise<SessionLease>;
57
+ /** Whether `ownerId` is the live, unexpired single writer permitted to append events. */
58
+ export declare function canWriteEvents(lease: SessionLease, ownerId: string, clock?: () => number): boolean;
59
+ /** Release the lease (owner shutdown). Only the holder may release. */
60
+ export declare function releaseLease(root: string, sessionId: string, ownerId: string): Promise<void>;
61
+ export declare function reapDeadOwnerArtifacts(root: string, sessionId: string, expectedOwnerId: string, expectedEpoch: number, opts?: {
62
+ clock?: () => number;
63
+ probe?: (pid: number) => PidStatus;
64
+ }): Promise<boolean>;
65
+ export {};
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Lifecycle state machine + the universal `{state, evidence, nextAllowedActions}` contract.
3
+ *
4
+ * `nextAllowedActions` is the forcing function: it tells the caller exactly which
5
+ * primitives are currently permitted and, when not, why. Owner-routed verbs
6
+ * (`submit`) report `owner-not-live` when no `RuntimeOwner` holds the session lease.
7
+ */
8
+ import type { HarnessLifecycle, NextAllowedAction, PrimitiveResponse, SessionState, SessionStateView } from "./types";
9
+ export declare function isTerminal(lifecycle: HarnessLifecycle): boolean;
10
+ export declare function canTransition(from: HarnessLifecycle, to: HarnessLifecycle): boolean;
11
+ export declare function assertTransition(from: HarnessLifecycle, to: HarnessLifecycle): void;
12
+ /**
13
+ * Derive the permitted next actions for a session given its lifecycle and whether
14
+ * a live owner currently holds the lease.
15
+ */
16
+ export declare function nextAllowedActions(lifecycle: HarnessLifecycle, ownerLive: boolean): NextAllowedAction[];
17
+ export declare function buildStateView(state: SessionState, ownerLive: boolean): SessionStateView;
18
+ /** Build the universal contract response carried by every primitive. */
19
+ export declare function buildResponse<E extends Record<string, unknown>>(state: SessionState, ownerLive: boolean, evidence: E, ok?: boolean): PrimitiveResponse<E>;
@@ -0,0 +1,53 @@
1
+ import type { EventEnvelope, ReceiptFamily, SessionState } from "./types";
2
+ export declare const MAX_UNIX_SOCKET_PATH_BYTES = 100;
3
+ export declare function controlSocketPath(root: string, sessionId: string, env?: NodeJS.ProcessEnv): string;
4
+ export declare class StorageError extends Error {
5
+ readonly code: string;
6
+ constructor(message: string, code: string);
7
+ }
8
+ /** Resolve the harness state root from explicit value, env, or cwd default. */
9
+ export declare function resolveHarnessRoot(opts?: {
10
+ root?: string;
11
+ cwd?: string;
12
+ env?: NodeJS.ProcessEnv;
13
+ }): string;
14
+ export declare function assertSafeSessionId(id: string): void;
15
+ export declare function generateSessionId(prefix?: string): string;
16
+ export interface SessionPaths {
17
+ dir: string;
18
+ state: string;
19
+ lease: string;
20
+ events: string;
21
+ receiptsIndex: string;
22
+ receiptsDir: string;
23
+ artifactsDir: string;
24
+ controlSock: string;
25
+ controlFifo: string;
26
+ gjcSessionDir: string;
27
+ }
28
+ export declare function sessionPaths(root: string, sessionId: string): SessionPaths;
29
+ export declare function readSessionState(root: string, sessionId: string): Promise<SessionState | null>;
30
+ export declare function writeSessionState(root: string, state: SessionState): Promise<void>;
31
+ export declare function sessionExists(root: string, sessionId: string): Promise<boolean>;
32
+ /** Append a single severity envelope to events.jsonl. Single-writer discipline is the owner's job (M3). */
33
+ export declare function appendEvent(root: string, sessionId: string, envelope: EventEnvelope): Promise<void>;
34
+ /** Read events from cursor (exclusive). Tail-only: never mutates the log. */
35
+ export declare function readEvents(root: string, sessionId: string, fromCursor?: number): Promise<EventEnvelope[]>;
36
+ export interface ReceiptIndexEntry {
37
+ receiptId: string;
38
+ family: ReceiptFamily;
39
+ valid: boolean;
40
+ createdAt: string;
41
+ path: string;
42
+ }
43
+ /**
44
+ * Persist a receipt immutably. Fails closed if the receipt id already exists,
45
+ * then appends an index entry to receipts.jsonl.
46
+ */
47
+ export declare function writeReceiptImmutable(root: string, sessionId: string, family: ReceiptFamily, receiptId: string, value: {
48
+ receiptId: string;
49
+ family: ReceiptFamily;
50
+ valid: boolean;
51
+ createdAt: string;
52
+ }): Promise<ReceiptIndexEntry>;
53
+ export declare function readReceiptIndex(root: string, sessionId: string, family?: ReceiptFamily): Promise<ReceiptIndexEntry[]>;
@@ -0,0 +1,162 @@
1
+ /**
2
+ * Core types for the gajae-code-native coding-harness operations control plane (v1).
3
+ *
4
+ * See the approved consensus plan at
5
+ * `.gjc/plans/ralplan/2026-06-02-0853-3e33/stage-02-revision.md` and the spec at
6
+ * `.gjc/specs/deep-interview-harness-control-plane.md`.
7
+ *
8
+ * v1 implements the gajae-code adapter only. omx/codex/remote/auth are deferred seams.
9
+ */
10
+ /** Harnesses the control plane can operate. v1 implements `gajae-code` only. */
11
+ export type Harness = "gajae-code" | "codex" | "omx";
12
+ /** Lifecycle states of an operated session. */
13
+ export type HarnessLifecycle = "new" | "started" | "submitted" | "observing" | "recovering" | "validating" | "finalizing" | "completed" | "blocked" | "retired";
14
+ /** Event severities emitted by the owner. */
15
+ export type Severity = "info" | "warn" | "critical";
16
+ /** Bounded git delta classification surfaced by `observe`. */
17
+ export type GitDelta = "clean" | "dirty" | "zero-delta" | "unknown";
18
+ /** Risk classification surfaced by `observe`. */
19
+ export type RiskKind = "normal" | "prompt-not-accepted" | "deleted-worktree" | "vanished-dirty";
20
+ /** Deterministic recovery classifications. */
21
+ export type RecoveryClassification = "continue" | "send-enter" | "reinject-prompt" | "restart-clean" | "restart-preserve-delta" | "fallback-codex-exec" | "human-check";
22
+ /** Receipt families persisted under the session storage dir. */
23
+ export type ReceiptFamily = "vanish" | "prompt-acceptance" | "validation" | "completion";
24
+ /** The CLI verbs / primitives exposed by `gjc harness <verb>`. */
25
+ export type HarnessVerb = "start" | "submit" | "observe" | "classify" | "recover" | "validate" | "finalize" | "retire" | "events" | "monitor" | "operate";
26
+ /** Submission transports. */
27
+ export type SubmitMode = "paste-buffer" | "stdin" | "file";
28
+ /** A single entry in the forcing-function `nextAllowedActions` list. */
29
+ export interface NextAllowedAction {
30
+ verb: HarnessVerb;
31
+ available: boolean;
32
+ /** Present when `available` is false; explains why the verb is currently disallowed. */
33
+ reason?: string;
34
+ }
35
+ /** Compact, model-facing view of session state included in every response. */
36
+ export interface SessionStateView {
37
+ sessionId: string;
38
+ lifecycle: HarnessLifecycle;
39
+ harness: Harness;
40
+ ownerLive: boolean;
41
+ blockers: string[];
42
+ }
43
+ /**
44
+ * The universal contract: EVERY primitive response carries `{state, evidence, nextAllowedActions}`.
45
+ * `ok` is a transport-level convenience; semantic blocking is expressed via state + nextAllowedActions.
46
+ */
47
+ export interface PrimitiveResponse<E = Record<string, unknown>> {
48
+ ok: boolean;
49
+ state: SessionStateView;
50
+ evidence: E;
51
+ nextAllowedActions: NextAllowedAction[];
52
+ }
53
+ /** Re-grabbable session handle returned by `start` / `operate`. */
54
+ export interface SessionHandle {
55
+ sessionId: string;
56
+ harness: Harness;
57
+ repo: string | null;
58
+ workspace: string;
59
+ branch: string | null;
60
+ base: string | null;
61
+ issueOrPr: string | null;
62
+ processHandle: {
63
+ kind: "runtime-owner";
64
+ ownerId: string | null;
65
+ pid: number | null;
66
+ };
67
+ rpcHandle: {
68
+ kind: "rpc-subprocess";
69
+ pid: number | null;
70
+ sessionDir: string;
71
+ };
72
+ ownerHandle: {
73
+ leasePath: string;
74
+ endpoint: string | null;
75
+ heartbeatAt: string | null;
76
+ };
77
+ routerHandle: {
78
+ kind: "default-in-owner";
79
+ policy: string;
80
+ eventsPath: string;
81
+ };
82
+ viewportHandle: {
83
+ kind: "event-monitor";
84
+ tmuxSessionName: string | null;
85
+ viewOnly: true;
86
+ };
87
+ startedAt: string;
88
+ updatedAt: string;
89
+ }
90
+ /** Persisted per-session record (state.json). */
91
+ export interface SessionState {
92
+ schemaVersion: number;
93
+ sessionId: string;
94
+ lifecycle: HarnessLifecycle;
95
+ harness: Harness;
96
+ handle: SessionHandle;
97
+ /** Per-classification retry counters consumed by the recovery policy. */
98
+ retries: Record<string, number>;
99
+ blockers: string[];
100
+ createdAt: string;
101
+ updatedAt: string;
102
+ }
103
+ /** Bounded observed-signal vocabulary surfaced by `observe` (the owner only ever emits these). */
104
+ export type ObservedSignal = "SessionStart" | "prompt-accepted" | "tool-call" | "test-running" | "commit-created" | "completed" | "error" | "streaming" | "idle";
105
+ export declare const OBSERVED_SIGNALS: readonly ObservedSignal[];
106
+ /** Bounded observation surfaced by `observe` — never a raw pane/transcript dump. */
107
+ export interface Observation {
108
+ lifecycle: HarnessLifecycle;
109
+ ownerLive: boolean;
110
+ cwd: string;
111
+ branch: string | null;
112
+ gitDelta: GitDelta;
113
+ lastActivityAt: string | null;
114
+ observedSignals: string[];
115
+ risk: RiskKind;
116
+ /** RPC subprocess liveness, distinct from owner-process/lease liveness. Optional for back-compat. */
117
+ rpcLive?: boolean;
118
+ /** ISO timestamp of the most recent RPC frame the owner observed, if any. */
119
+ rpcLastFrameAt?: string | null;
120
+ }
121
+ /** Input to the deterministic recovery classifier. */
122
+ export interface ClassifyInput {
123
+ observation: Observation;
124
+ /** Remaining retry budget per classification family. */
125
+ retryBudget: RetryBudget;
126
+ /** Whether an accepted prompt was in flight when the owner/RPC was last seen. */
127
+ acceptedPromptActive?: boolean;
128
+ }
129
+ /** Default and supplied retry budgets. */
130
+ export interface RetryBudget {
131
+ reinjectPrompt: number;
132
+ zeroDeltaVanish: number;
133
+ dirtyVanishPreserve: number;
134
+ validationRepair: number;
135
+ }
136
+ /** Result of the deterministic recovery classifier. */
137
+ export interface RecoveryDecision {
138
+ classification: RecoveryClassification;
139
+ reason: string;
140
+ severity: Severity;
141
+ /** Whether executing the recommended action requires a live owner. */
142
+ ownerRequired: boolean;
143
+ /** Receipt family that MUST be valid before the action may proceed (e.g. `vanish`). */
144
+ requiredReceiptFamily: ReceiptFamily | null;
145
+ }
146
+ /** Severity-tagged event envelope written exclusively by the owner. */
147
+ export interface EventEnvelope<E = Record<string, unknown>> {
148
+ eventId: string;
149
+ cursor: number;
150
+ createdAt: string;
151
+ severity: Severity;
152
+ kind: string;
153
+ state: SessionStateView;
154
+ evidence: E;
155
+ nextAllowedActions: NextAllowedAction[];
156
+ writer: {
157
+ ownerId: string;
158
+ leaseEpoch: number;
159
+ };
160
+ }
161
+ export declare const SESSION_SCHEMA_VERSION: 1;
162
+ export declare const DEFAULT_RETRY_BUDGET: RetryBudget;
@@ -1,3 +1,4 @@
1
+ import { type CanonicalGjcWorkflowSkill } from "../skill-state/active-state";
1
2
  export interface SkillKeywordDefinition {
2
3
  keyword: string;
3
4
  skill: GjcWorkflowSkill;
@@ -5,7 +6,7 @@ export interface SkillKeywordDefinition {
5
6
  guidance: string;
6
7
  }
7
8
  export declare const GJC_WORKFLOW_SKILLS: readonly ["deep-interview", "ralplan", "ultragoal", "team"];
8
- export type GjcWorkflowSkill = (typeof GJC_WORKFLOW_SKILLS)[number];
9
+ export type GjcWorkflowSkill = CanonicalGjcWorkflowSkill;
9
10
  export declare const GJC_SKILL_KEYWORD_DEFINITIONS: readonly SkillKeywordDefinition[];
10
11
  export declare function isGjcWorkflowSkill(value: string): value is GjcWorkflowSkill;
11
12
  export declare function compareSkillKeywordMatches(a: {
@@ -1,5 +1,5 @@
1
1
  import type { SkillDiscoverySettings } from "../config/skill-settings-defaults";
2
- import type { SkillActiveEntry as CanonicalSkillActiveEntry, WorkflowHudSummary } from "../skill-state/active-state";
2
+ import { type SkillActiveState } from "../skill-state/active-state";
3
3
  import { type GjcWorkflowSkill } from "./skill-keywords";
4
4
  export declare const GJC_STATE_DIR = ".gjc/state";
5
5
  export declare const SKILL_ACTIVE_STATE_FILE = "skill-active-state.json";
@@ -14,34 +14,7 @@ export interface SkillKeywordMatch {
14
14
  skill: GjcWorkflowSkill;
15
15
  priority: number;
16
16
  }
17
- export interface SkillActiveEntry extends Omit<CanonicalSkillActiveEntry, "skill"> {
18
- skill: GjcWorkflowSkill;
19
- phase?: string;
20
- active?: boolean;
21
- activated_at?: string;
22
- updated_at?: string;
23
- session_id?: string;
24
- thread_id?: string;
25
- turn_id?: string;
26
- hud?: WorkflowHudSummary;
27
- stale?: boolean;
28
- }
29
- export interface SkillActiveState {
30
- version: number;
31
- active: boolean;
32
- skill: GjcWorkflowSkill;
33
- keyword: string;
34
- phase: string;
35
- activated_at: string;
36
- updated_at: string;
37
- source: "gjc-skill-state-hook";
38
- session_id?: string;
39
- thread_id?: string;
40
- turn_id?: string;
41
- initialized_mode?: GjcWorkflowSkill;
42
- initialized_state_path?: string;
43
- active_skills: SkillActiveEntry[];
44
- }
17
+ export type { SkillActiveEntry, SkillActiveState } from "../skill-state/active-state";
45
18
  export interface ModeState {
46
19
  active?: boolean;
47
20
  current_phase?: string;
@@ -21,6 +21,7 @@ export interface HookSelectorOptions {
21
21
  * byte-identical to the previous implementation for all consumers.
22
22
  */
23
23
  wrapFocused?: boolean;
24
+ scrollTitleRows?: number;
24
25
  }
25
26
  export declare class HookSelectorComponent extends Container {
26
27
  #private;
@@ -86,6 +86,7 @@ export declare class InteractiveMode implements InteractiveModeContext {
86
86
  retryLoader: Loader | undefined;
87
87
  autoCompactionEscapeHandler?: () => void;
88
88
  retryEscapeHandler?: () => void;
89
+ retryCountdownTimer?: ReturnType<typeof setInterval>;
89
90
  unsubscribe?: () => void;
90
91
  onInputCallback?: (input: SubmittedUserInput) => void;
91
92
  optimisticUserMessageSignature: string | undefined;
@@ -93,6 +93,7 @@ export interface InteractiveModeContext {
93
93
  retryLoader: Loader | undefined;
94
94
  autoCompactionEscapeHandler?: () => void;
95
95
  retryEscapeHandler?: () => void;
96
+ retryCountdownTimer?: ReturnType<typeof setInterval>;
96
97
  unsubscribe?: () => void;
97
98
  onInputCallback?: (input: SubmittedUserInput) => void;
98
99
  optimisticUserMessageSignature: string | undefined;
@@ -127,6 +127,8 @@ export interface CreateAgentSessionOptions {
127
127
  forkContextSeed?: ForkContextSeed;
128
128
  /** Optional provider state override. Fork-context children should omit this by default. */
129
129
  providerSessionState?: Map<string, ProviderSessionState>;
130
+ /** Cooperative pause checkpoint passed through to Agent. */
131
+ shouldPause?: () => boolean;
130
132
  }
131
133
  /** Result from createAgentSession */
132
134
  export interface CreateAgentSessionResult {
@@ -90,6 +90,7 @@ export type AgentSessionEvent = AgentEvent | {
90
90
  maxAttempts: number;
91
91
  delayMs: number;
92
92
  errorMessage: string;
93
+ unbounded?: boolean;
93
94
  } | {
94
95
  type: "auto_retry_end";
95
96
  success: boolean;
@@ -604,6 +605,7 @@ export declare class AgentSession {
604
605
  abort(options?: {
605
606
  goalReason?: "interrupted" | "internal";
606
607
  timeoutMs?: number;
608
+ cause?: "user_interrupt" | "new_session" | "session_switch" | "compaction" | "handoff" | "tool_abort" | "internal";
607
609
  }): Promise<void>;
608
610
  /**
609
611
  * Start a new session, optionally with initial messages and parent tracking.
@@ -752,6 +754,12 @@ export declare class AgentSession {
752
754
  * Cancel in-progress retry.
753
755
  */
754
756
  abortRetry(): void;
757
+ /**
758
+ * Skip the current retry backoff and re-attempt immediately. Distinct from
759
+ * abortRetry(), which cancels the retry and returns to idle. No-op when no
760
+ * retry backoff is active.
761
+ */
762
+ retryNow(): void;
755
763
  /** Whether auto-retry is currently in progress */
756
764
  get isRetrying(): boolean;
757
765
  /** Whether auto-retry is enabled */
@@ -46,6 +46,8 @@ export interface SkillActiveState {
46
46
  session_id?: string;
47
47
  thread_id?: string;
48
48
  turn_id?: string;
49
+ initialized_mode?: CanonicalGjcWorkflowSkill;
50
+ initialized_state_path?: string;
49
51
  active_skills?: SkillActiveEntry[];
50
52
  [key: string]: unknown;
51
53
  }
@@ -1,6 +1,6 @@
1
1
  import type { AgentTool } from "@gajae-code/agent-core";
2
2
  export declare const DEEP_INTERVIEW_MUTATION_BLOCK_MESSAGE = "Deep-interview phase boundary: continue gathering context/questions/risks and emit a handoff/spec before code edits. Mutation tools and patch execution are blocked while deep-interview is active; finalize specs through `gjc deep-interview --write --stage final` or hand off to an execution phase.";
3
- export declare const WORKFLOW_STATE_MUTATION_BLOCK_MESSAGE = "Workflow state JSON is runtime-owned. Use `gjc state <skill> read|write --input '<json>'` for deep-interview, ralplan, ultragoal, and team. Planning artifacts under `.gjc/specs/` and `.gjc/plans/` remain allowed.";
3
+ export declare const WORKFLOW_STATE_MUTATION_BLOCK_MESSAGE = ".gjc workflow state and artifacts are runtime-owned. Agent mutation tools cannot edit `.gjc/**`; use the sanctioned `gjc` CLI instead.";
4
4
  type ToolWithEditMode = AgentTool & {
5
5
  mode?: unknown;
6
6
  customWireName?: unknown;
@@ -4,6 +4,12 @@ export declare const WORKFLOW_STATE_RECEIPT_VERSION = 1;
4
4
  export declare const WORKFLOW_STATE_RECEIPT_FRESH_MS: number;
5
5
  export type WorkflowStateMutationOwner = "gjc-state-cli" | "gjc-runtime" | "gjc-hook";
6
6
  export type WorkflowStateReceiptStatus = "fresh" | "stale";
7
+ export interface WorkflowStateContentChecksum {
8
+ algorithm: "sha256";
9
+ value: string;
10
+ covered_path: string;
11
+ computed_at: string;
12
+ }
7
13
  export interface WorkflowStateReceipt {
8
14
  version: 1;
9
15
  skill: CanonicalGjcWorkflowSkill;
@@ -15,6 +21,24 @@ export interface WorkflowStateReceipt {
15
21
  fresh_until: string;
16
22
  status: WorkflowStateReceiptStatus;
17
23
  mutation_id: string;
24
+ verb?: string;
25
+ from_phase?: string;
26
+ to_phase?: string;
27
+ forced?: boolean;
28
+ paths?: string[];
29
+ content_sha256?: WorkflowStateContentChecksum;
30
+ }
31
+ export interface AuditEntry {
32
+ ts: string;
33
+ skill?: string;
34
+ category: string;
35
+ verb: string;
36
+ owner: WorkflowStateMutationOwner;
37
+ mutation_id: string;
38
+ from_phase?: string;
39
+ to_phase?: string;
40
+ forced: boolean;
41
+ paths: string[];
18
42
  }
19
43
  export declare function workflowModeStateFileName(skill: CanonicalGjcWorkflowSkill): string;
20
44
  export declare function workflowStateStoragePath(cwd: string, skill: CanonicalGjcWorkflowSkill, sessionId?: string): string;
@@ -29,6 +29,9 @@ export interface ExecutorOptions {
29
29
  index: number;
30
30
  id: string;
31
31
  modelOverride?: string | string[];
32
+ runMode?: "initial" | "resume" | "message";
33
+ resumeMessage?: string;
34
+ subagentId?: string;
32
35
  /**
33
36
  * Active model selector of the parent session, used as an auth-aware fallback
34
37
  * if the resolved subagent model has no working credentials. See #985.
@@ -32,7 +32,7 @@ export interface SubagentLifecyclePayload {
32
32
  agent: string;
33
33
  agentSource: AgentSource;
34
34
  description?: string;
35
- status: "started" | "completed" | "failed" | "aborted";
35
+ status: "started" | "completed" | "failed" | "aborted" | "paused";
36
36
  sessionFile?: string;
37
37
  index: number;
38
38
  }
@@ -171,7 +171,7 @@ export interface AgentProgress {
171
171
  id: string;
172
172
  agent: string;
173
173
  agentSource: AgentSource;
174
- status: "pending" | "running" | "completed" | "failed" | "aborted";
174
+ status: "pending" | "running" | "completed" | "failed" | "aborted" | "paused";
175
175
  task: string;
176
176
  assignment?: string;
177
177
  description?: string;
@@ -213,6 +213,7 @@ export interface AgentProgress {
213
213
  retryState?: {
214
214
  attempt: number;
215
215
  maxAttempts: number;
216
+ unbounded?: boolean;
216
217
  delayMs: number;
217
218
  errorMessage: string;
218
219
  startedAtMs: number;
@@ -261,6 +262,7 @@ export interface SingleResult {
261
262
  error?: string;
262
263
  aborted?: boolean;
263
264
  abortReason?: string;
265
+ paused?: boolean;
264
266
  /** Aggregated usage from the subprocess, accumulated incrementally from message_end events. */
265
267
  usage?: Usage;
266
268
  /** Output path for the task result */
@@ -299,9 +301,59 @@ export interface TaskToolDetails {
299
301
  outputPaths?: string[];
300
302
  progress?: AgentProgress[];
301
303
  async?: {
302
- state: "running" | "completed" | "failed";
304
+ state: "running" | "paused" | "queued" | "completed" | "failed";
303
305
  jobId: string;
304
306
  type: "task";
305
307
  };
306
308
  }
309
+ /**
310
+ * Persisted per-turn / per-subagent token record (Phase 0 instrumentation).
311
+ *
312
+ * Additive: this does not alter any existing task result shape. It is the
313
+ * durable, model-independent unit the deterministic orchestration-token
314
+ * benchmark (`@gajae-code/orchestration-token-benchmark`) consumes to measure
315
+ * token efficiency without any live-model calls.
316
+ */
317
+ export interface TaskTokenLog {
318
+ /** Subagent id, or "root" for the orchestrator's own turn. */
319
+ subagentId: string;
320
+ /** Agent name for attribution, when known. */
321
+ agent?: string;
322
+ /** 1-based turn index within the subagent's session. */
323
+ turn: number;
324
+ /** ISO-8601 timestamp the turn completed. */
325
+ at: string;
326
+ /** Cost-bearing input tokens (excludes cache reads), mirrors `Usage.input`. */
327
+ input: number;
328
+ /** Total output tokens for the turn, mirrors `Usage.output`. */
329
+ output: number;
330
+ /** Tokens read from the prompt cache, mirrors `Usage.cacheRead`. */
331
+ cacheRead: number;
332
+ /** Tokens written to the prompt cache, mirrors `Usage.cacheWrite`. */
333
+ cacheWrite: number;
334
+ /** input + output + cacheRead + cacheWrite. */
335
+ totalTokens: number;
336
+ /** Latest per-turn context-window occupancy, when known. */
337
+ contextTokens?: number;
338
+ /** Estimated USD cost for the turn, when known. */
339
+ cost?: number;
340
+ /** Model id used for the turn, when known. */
341
+ model?: string;
342
+ }
343
+ /**
344
+ * Deterministic aggregate token metrics computed from a set of `TaskTokenLog`
345
+ * entries. The cache-hit-rate field is the primary prompt-cache signal called
346
+ * out by the prefix-stability invariant (see the approved plan).
347
+ */
348
+ export interface TaskTokenMetrics {
349
+ /** Number of token-log entries aggregated. */
350
+ turns: number;
351
+ inputTokens: number;
352
+ outputTokens: number;
353
+ cacheReadTokens: number;
354
+ cacheWriteTokens: number;
355
+ totalTokens: number;
356
+ /** cacheRead / (input + cacheRead); 0 when there is no input-class traffic. */
357
+ cacheHitRate: number;
358
+ }
307
359
  export {};
@@ -8,13 +8,18 @@ declare const subagentSchema: z.ZodObject<{
8
8
  cancel: "cancel";
9
9
  inspect: "inspect";
10
10
  list: "list";
11
+ pause: "pause";
12
+ resume: "resume";
13
+ steer: "steer";
11
14
  }>;
12
15
  ids: z.ZodOptional<z.ZodArray<z.ZodString>>;
16
+ message: z.ZodOptional<z.ZodString>;
17
+ pause: z.ZodOptional<z.ZodBoolean>;
13
18
  timeout_ms: z.ZodOptional<z.ZodNumber>;
14
19
  limit: z.ZodOptional<z.ZodNumber>;
15
20
  }, z.core.$strip>;
16
21
  type SubagentParams = z.infer<typeof subagentSchema>;
17
- type SubagentStatus = "running" | "completed" | "failed" | "cancelled" | "not_found" | "already_completed";
22
+ type SubagentStatus = "running" | "paused" | "queued" | "completed" | "failed" | "cancelled" | "not_found" | "already_completed";
18
23
  export interface SubagentSnapshot {
19
24
  id: string;
20
25
  jobId: string;
@@ -45,8 +50,13 @@ export declare class SubagentTool implements AgentTool<typeof subagentSchema, Su
45
50
  cancel: "cancel";
46
51
  inspect: "inspect";
47
52
  list: "list";
53
+ pause: "pause";
54
+ resume: "resume";
55
+ steer: "steer";
48
56
  }>;
49
57
  ids: z.ZodOptional<z.ZodArray<z.ZodString>>;
58
+ message: z.ZodOptional<z.ZodString>;
59
+ pause: z.ZodOptional<z.ZodBoolean>;
50
60
  timeout_ms: z.ZodOptional<z.ZodNumber>;
51
61
  limit: z.ZodOptional<z.ZodNumber>;
52
62
  }, z.core.$strip>;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@gajae-code/coding-agent",
4
- "version": "0.2.5",
4
+ "version": "0.3.0",
5
5
  "description": "Gajae Code CLI with read, bash, edit, write tools and session management",
6
6
  "homepage": "https://gaebal-gajae.dev",
7
7
  "author": "Yeachan-Heo",
@@ -48,12 +48,12 @@
48
48
  "@agentclientprotocol/sdk": "0.21.0",
49
49
  "@babel/parser": "^7.29.3",
50
50
  "@mozilla/readability": "^0.6.0",
51
- "@gajae-code/stats": "0.2.5",
52
- "@gajae-code/agent-core": "0.2.5",
53
- "@gajae-code/ai": "0.2.5",
54
- "@gajae-code/natives": "0.2.5",
55
- "@gajae-code/tui": "0.2.5",
56
- "@gajae-code/utils": "0.2.5",
51
+ "@gajae-code/stats": "0.3.0",
52
+ "@gajae-code/agent-core": "0.3.0",
53
+ "@gajae-code/ai": "0.3.0",
54
+ "@gajae-code/natives": "0.3.0",
55
+ "@gajae-code/tui": "0.3.0",
56
+ "@gajae-code/utils": "0.3.0",
57
57
  "@puppeteer/browsers": "^2.13.0",
58
58
  "@types/turndown": "5.0.6",
59
59
  "@xterm/headless": "^6.0.0",