@gajae-code/coding-agent 0.6.3 → 0.6.5
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 +50 -0
- package/README.md +73 -1
- package/dist/types/cli/migrate-cli.d.ts +20 -0
- package/dist/types/commands/migrate.d.ts +33 -0
- package/dist/types/config/keybindings.d.ts +4 -0
- package/dist/types/config/settings-schema.d.ts +27 -0
- package/dist/types/gjc-runtime/deep-interview-recorder.d.ts +2 -0
- package/dist/types/gjc-runtime/deep-interview-runtime.d.ts +2 -2
- package/dist/types/gjc-runtime/goal-mode-request.d.ts +1 -1
- package/dist/types/gjc-runtime/session-layout.d.ts +59 -0
- package/dist/types/gjc-runtime/session-resolution.d.ts +47 -0
- package/dist/types/gjc-runtime/state-graph.d.ts +1 -1
- package/dist/types/gjc-runtime/state-runtime.d.ts +5 -4
- package/dist/types/gjc-runtime/state-schema.d.ts +2 -0
- package/dist/types/gjc-runtime/state-writer.d.ts +36 -7
- package/dist/types/gjc-runtime/tmux-sessions.d.ts +2 -0
- package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +7 -4
- package/dist/types/gjc-runtime/workflow-command-ref.d.ts +1 -1
- package/dist/types/gjc-runtime/workflow-manifest.d.ts +1 -1
- package/dist/types/harness-control-plane/storage.d.ts +2 -1
- package/dist/types/hooks/skill-state.d.ts +12 -4
- package/dist/types/migrate/action-planner.d.ts +11 -0
- package/dist/types/migrate/adapters/claude-code.d.ts +2 -0
- package/dist/types/migrate/adapters/codex.d.ts +5 -0
- package/dist/types/migrate/adapters/index.d.ts +45 -0
- package/dist/types/migrate/adapters/opencode.d.ts +2 -0
- package/dist/types/migrate/executor.d.ts +2 -0
- package/dist/types/migrate/mcp-mapper.d.ts +20 -0
- package/dist/types/migrate/report.d.ts +18 -0
- package/dist/types/migrate/skill-normalizer.d.ts +27 -0
- package/dist/types/migrate/types.d.ts +126 -0
- package/dist/types/modes/components/custom-editor.d.ts +1 -1
- package/dist/types/modes/components/welcome.d.ts +3 -1
- package/dist/types/modes/interactive-mode.d.ts +3 -0
- package/dist/types/modes/prompt-action-autocomplete.d.ts +1 -0
- package/dist/types/modes/shared/agent-wire/unattended-audit.d.ts +1 -1
- package/dist/types/research-plan/index.d.ts +1 -0
- package/dist/types/research-plan/ledger.d.ts +33 -0
- package/dist/types/rlm/artifacts.d.ts +1 -1
- package/dist/types/runtime-mcp/config-writer.d.ts +26 -0
- package/dist/types/skill-state/active-state.d.ts +6 -11
- package/dist/types/skill-state/canonical-skills.d.ts +3 -0
- package/dist/types/skill-state/workflow-hud.d.ts +2 -0
- package/dist/types/task/spawn-gate.d.ts +1 -10
- package/package.json +7 -7
- package/src/cli/migrate-cli.ts +106 -0
- package/src/cli/setup-cli.ts +14 -1
- package/src/cli.ts +1 -0
- package/src/commands/deep-interview.ts +2 -2
- package/src/commands/launch.ts +1 -1
- package/src/commands/migrate.ts +46 -0
- package/src/commands/state.ts +2 -1
- package/src/commands/team.ts +7 -3
- package/src/config/model-registry.ts +9 -2
- package/src/config/model-resolver.ts +13 -2
- package/src/config/settings-schema.ts +17 -0
- package/src/coordinator-mcp/policy.ts +10 -2
- package/src/defaults/gjc/extensions/grok-cli-vendor/biome.json +0 -1
- package/src/defaults/gjc/skills/deep-interview/SKILL.md +28 -24
- package/src/defaults/gjc/skills/ralplan/SKILL.md +8 -4
- package/src/defaults/gjc/skills/team/SKILL.md +51 -47
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +17 -13
- package/src/exec/bash-executor.ts +3 -1
- package/src/extensibility/custom-commands/loader.ts +0 -7
- package/src/extensibility/gjc-plugins/injection.ts +23 -4
- package/src/extensibility/gjc-plugins/state.ts +16 -1
- package/src/gjc-runtime/deep-interview-recorder.ts +43 -18
- package/src/gjc-runtime/deep-interview-runtime.ts +49 -23
- package/src/gjc-runtime/goal-mode-request.ts +26 -11
- package/src/gjc-runtime/launch-tmux.ts +68 -15
- package/src/gjc-runtime/ralplan-runtime.ts +79 -50
- package/src/gjc-runtime/session-layout.ts +180 -0
- package/src/gjc-runtime/session-resolution.ts +217 -0
- package/src/gjc-runtime/state-graph.ts +1 -2
- package/src/gjc-runtime/state-migrations.ts +1 -0
- package/src/gjc-runtime/state-runtime.ts +230 -121
- package/src/gjc-runtime/state-schema.ts +2 -0
- package/src/gjc-runtime/state-writer.ts +289 -41
- package/src/gjc-runtime/team-runtime.ts +43 -19
- package/src/gjc-runtime/tmux-sessions.ts +43 -2
- package/src/gjc-runtime/ultragoal-guard.ts +45 -2
- package/src/gjc-runtime/ultragoal-runtime.ts +121 -41
- package/src/gjc-runtime/workflow-command-ref.ts +1 -2
- package/src/gjc-runtime/workflow-manifest.ts +1 -2
- package/src/harness-control-plane/storage.ts +14 -4
- package/src/hooks/native-skill-hook.ts +38 -12
- package/src/hooks/skill-state.ts +178 -83
- package/src/internal-urls/docs-index.generated.ts +9 -6
- package/src/migrate/action-planner.ts +318 -0
- package/src/migrate/adapters/claude-code.ts +39 -0
- package/src/migrate/adapters/codex.ts +70 -0
- package/src/migrate/adapters/index.ts +277 -0
- package/src/migrate/adapters/opencode.ts +52 -0
- package/src/migrate/executor.ts +81 -0
- package/src/migrate/mcp-mapper.ts +152 -0
- package/src/migrate/report.ts +104 -0
- package/src/migrate/skill-normalizer.ts +80 -0
- package/src/migrate/types.ts +163 -0
- package/src/modes/bridge/bridge-mode.ts +2 -2
- package/src/modes/components/custom-editor.ts +30 -20
- package/src/modes/components/welcome.ts +42 -9
- package/src/modes/controllers/input-controller.ts +21 -3
- package/src/modes/interactive-mode.ts +22 -1
- package/src/modes/prompt-action-autocomplete.ts +11 -1
- package/src/modes/rpc/rpc-mode.ts +2 -2
- package/src/modes/shared/agent-wire/unattended-audit.ts +3 -2
- package/src/prompts/agents/init.md +1 -1
- package/src/prompts/system/plan-mode-active.md +1 -1
- package/src/prompts/tools/ast-grep.md +1 -1
- package/src/prompts/tools/search.md +1 -1
- package/src/prompts/tools/task.md +1 -2
- package/src/research-plan/index.ts +1 -0
- package/src/research-plan/ledger.ts +177 -0
- package/src/rlm/artifacts.ts +12 -3
- package/src/rlm/index.ts +7 -0
- package/src/runtime-mcp/config-writer.ts +46 -0
- package/src/session/agent-session.ts +15 -21
- package/src/session/session-manager.ts +19 -2
- package/src/setup/hermes/templates/operator-instructions.v1.md +8 -0
- package/src/setup/hermes-setup.ts +1 -1
- package/src/skill-state/active-state.ts +72 -108
- package/src/skill-state/canonical-skills.ts +4 -0
- package/src/skill-state/deep-interview-mutation-guard.ts +28 -109
- package/src/skill-state/workflow-hud.ts +4 -2
- package/src/skill-state/workflow-state-contract.ts +3 -3
- package/src/slash-commands/builtin-registry.ts +8 -4
- package/src/system-prompt.ts +11 -9
- package/src/task/agents.ts +1 -22
- package/src/task/index.ts +1 -41
- package/src/task/spawn-gate.ts +1 -38
- package/src/task/types.ts +1 -1
- package/src/tools/ask.ts +34 -12
- package/src/tools/computer.ts +58 -4
- package/dist/types/extensibility/custom-commands/bundled/review/index.d.ts +0 -10
- package/src/extensibility/custom-commands/bundled/review/index.ts +0 -456
- package/src/prompts/agents/explore.md +0 -58
- package/src/prompts/agents/plan.md +0 -49
- package/src/prompts/agents/reviewer.md +0 -141
- package/src/prompts/agents/task.md +0 -16
- package/src/prompts/review-request.md +0 -70
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Boundary session resolution for GJC workflow state.
|
|
3
|
+
*
|
|
4
|
+
* This is the impure companion to the pure `session-layout.ts`. Only CLI /
|
|
5
|
+
* runtime entrypoints call these resolvers; low-level readers and writers
|
|
6
|
+
* receive an explicit `gjcSessionId` (or a path produced by the pure helper) so
|
|
7
|
+
* no module silently picks a session.
|
|
8
|
+
*
|
|
9
|
+
* Resolution order:
|
|
10
|
+
* 1. explicit `--session-id` flag (blank is invalid, never suppressed)
|
|
11
|
+
* 2. payload `session_id`
|
|
12
|
+
* 3. `GJC_SESSION_ID` env var
|
|
13
|
+
* 4. latest-activity-marker auto-detect (READ/STATUS/CLEAR only)
|
|
14
|
+
*
|
|
15
|
+
* Writes require one of (1)-(3). Auto-detect fails closed on zero candidates or
|
|
16
|
+
* ambiguous ties.
|
|
17
|
+
*/
|
|
18
|
+
import * as fs from "node:fs/promises";
|
|
19
|
+
import * as path from "node:path";
|
|
20
|
+
import {
|
|
21
|
+
GJC_SESSION_ACTIVITY_FILE,
|
|
22
|
+
type GjcSessionContext,
|
|
23
|
+
type GjcSessionSource,
|
|
24
|
+
gjcRoot,
|
|
25
|
+
sessionIdFromDirName,
|
|
26
|
+
sessionRoot,
|
|
27
|
+
} from "./session-layout";
|
|
28
|
+
|
|
29
|
+
/** Window within which two activity timestamps are treated as an ambiguous tie. */
|
|
30
|
+
export const LATEST_SESSION_TIE_WINDOW_MS = 1000;
|
|
31
|
+
|
|
32
|
+
export interface SessionIdSources {
|
|
33
|
+
/** Raw `--session-id` value: `undefined` = flag absent; `""` = present-but-blank (invalid). */
|
|
34
|
+
flagValue?: string | undefined;
|
|
35
|
+
payloadSessionId?: unknown;
|
|
36
|
+
envSessionId?: string | undefined;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export class SessionResolutionError extends Error {
|
|
40
|
+
constructor(
|
|
41
|
+
message: string,
|
|
42
|
+
readonly code: "blank_flag" | "no_session" | "ambiguous" | "missing_for_write",
|
|
43
|
+
) {
|
|
44
|
+
super(message);
|
|
45
|
+
this.name = "SessionResolutionError";
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
interface ResolvedFromSources {
|
|
50
|
+
gjcSessionId: string;
|
|
51
|
+
source: GjcSessionSource;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Resolve a session id from explicit sources only (flag -> payload -> env).
|
|
56
|
+
* Returns `undefined` when none is present. A blank explicit flag throws.
|
|
57
|
+
*/
|
|
58
|
+
export function resolveSessionIdFromSources(sources: SessionIdSources): ResolvedFromSources | undefined {
|
|
59
|
+
const { flagValue, payloadSessionId, envSessionId } = sources;
|
|
60
|
+
if (flagValue !== undefined) {
|
|
61
|
+
const trimmed = flagValue.trim();
|
|
62
|
+
if (trimmed === "") {
|
|
63
|
+
throw new SessionResolutionError(
|
|
64
|
+
"--session-id was provided but blank; pass a non-empty session id or omit the flag",
|
|
65
|
+
"blank_flag",
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
return { gjcSessionId: trimmed, source: "flag" };
|
|
69
|
+
}
|
|
70
|
+
if (typeof payloadSessionId === "string" && payloadSessionId.trim() !== "") {
|
|
71
|
+
return { gjcSessionId: payloadSessionId.trim(), source: "payload" };
|
|
72
|
+
}
|
|
73
|
+
if (typeof envSessionId === "string" && envSessionId.trim() !== "") {
|
|
74
|
+
return { gjcSessionId: envSessionId.trim(), source: "env" };
|
|
75
|
+
}
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Resolve session context for a WRITE command. Errors when no explicit id is present. */
|
|
80
|
+
export function resolveGjcSessionForWrite(cwd: string, sources: SessionIdSources): GjcSessionContext {
|
|
81
|
+
const resolved = resolveSessionIdFromSources(sources);
|
|
82
|
+
if (!resolved) {
|
|
83
|
+
throw new SessionResolutionError(
|
|
84
|
+
"a session id is required to write state: pass --session-id, payload session_id, or set GJC_SESSION_ID",
|
|
85
|
+
"missing_for_write",
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
gjcSessionId: resolved.gjcSessionId,
|
|
90
|
+
sessionRoot: sessionRoot(cwd, resolved.gjcSessionId),
|
|
91
|
+
source: resolved.source,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Resolve session context for a READ/STATUS/CLEAR command. Falls back to the
|
|
97
|
+
* latest active session by activity marker when no explicit id is present.
|
|
98
|
+
*/
|
|
99
|
+
export async function resolveGjcSessionForRead(cwd: string, sources: SessionIdSources): Promise<GjcSessionContext> {
|
|
100
|
+
const resolved = resolveSessionIdFromSources(sources);
|
|
101
|
+
if (resolved) {
|
|
102
|
+
return {
|
|
103
|
+
gjcSessionId: resolved.gjcSessionId,
|
|
104
|
+
sessionRoot: sessionRoot(cwd, resolved.gjcSessionId),
|
|
105
|
+
source: resolved.source,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
const latest = await detectLatestSession(cwd);
|
|
109
|
+
return { gjcSessionId: latest.gjcSessionId, sessionRoot: latest.sessionRoot, source: "latest" };
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
interface SessionCandidate {
|
|
113
|
+
gjcSessionId: string;
|
|
114
|
+
sessionRoot: string;
|
|
115
|
+
activityMs: number;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Scan `.gjc/_session-*` directories and select the most-recently-active one by
|
|
120
|
+
* its activity marker. Never uses raw directory mtime. Throws on zero candidates
|
|
121
|
+
* or an ambiguous tie.
|
|
122
|
+
*/
|
|
123
|
+
export async function detectLatestSession(cwd: string): Promise<GjcSessionContext> {
|
|
124
|
+
const candidates = await collectActiveSessionCandidates(cwd);
|
|
125
|
+
if (candidates.length === 0) {
|
|
126
|
+
throw new SessionResolutionError(
|
|
127
|
+
"no active GJC session found: pass --session-id or set GJC_SESSION_ID",
|
|
128
|
+
"no_session",
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
candidates.sort((a, b) => b.activityMs - a.activityMs);
|
|
132
|
+
const [first, second] = candidates;
|
|
133
|
+
if (second && first.activityMs - second.activityMs <= LATEST_SESSION_TIE_WINDOW_MS) {
|
|
134
|
+
const tied = candidates
|
|
135
|
+
.filter(c => first.activityMs - c.activityMs <= LATEST_SESSION_TIE_WINDOW_MS)
|
|
136
|
+
.map(c => c.gjcSessionId);
|
|
137
|
+
throw new SessionResolutionError(
|
|
138
|
+
`ambiguous latest session among [${tied.join(", ")}]: pass --session-id or set GJC_SESSION_ID`,
|
|
139
|
+
"ambiguous",
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
return { gjcSessionId: first.gjcSessionId, sessionRoot: first.sessionRoot, source: "latest" };
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
async function collectActiveSessionCandidates(cwd: string): Promise<SessionCandidate[]> {
|
|
146
|
+
const root = gjcRoot(cwd);
|
|
147
|
+
let entries: import("node:fs").Dirent[];
|
|
148
|
+
try {
|
|
149
|
+
entries = await fs.readdir(root, { withFileTypes: true });
|
|
150
|
+
} catch {
|
|
151
|
+
return [];
|
|
152
|
+
}
|
|
153
|
+
const candidates: SessionCandidate[] = [];
|
|
154
|
+
for (const entry of entries) {
|
|
155
|
+
if (!entry.isDirectory()) continue;
|
|
156
|
+
const gjcSessionId = sessionIdFromDirName(entry.name);
|
|
157
|
+
if (!gjcSessionId) continue;
|
|
158
|
+
const dir = path.join(root, entry.name);
|
|
159
|
+
const activityMs = await readActivityMs(path.join(dir, GJC_SESSION_ACTIVITY_FILE));
|
|
160
|
+
// Sessions with no readable activity marker are considered inactive and
|
|
161
|
+
// are not selected for auto-detect.
|
|
162
|
+
if (activityMs === undefined) continue;
|
|
163
|
+
candidates.push({ gjcSessionId, sessionRoot: dir, activityMs });
|
|
164
|
+
}
|
|
165
|
+
return candidates;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
async function readActivityMs(markerPath: string): Promise<number | undefined> {
|
|
169
|
+
let raw: string;
|
|
170
|
+
try {
|
|
171
|
+
raw = await fs.readFile(markerPath, "utf-8");
|
|
172
|
+
} catch {
|
|
173
|
+
return undefined;
|
|
174
|
+
}
|
|
175
|
+
try {
|
|
176
|
+
const parsed = JSON.parse(raw) as { updated_at?: unknown };
|
|
177
|
+
if (typeof parsed.updated_at === "string") {
|
|
178
|
+
const ms = Date.parse(parsed.updated_at);
|
|
179
|
+
if (!Number.isNaN(ms)) return ms;
|
|
180
|
+
}
|
|
181
|
+
} catch {
|
|
182
|
+
// fall through to mtime
|
|
183
|
+
}
|
|
184
|
+
try {
|
|
185
|
+
const stat = await fs.stat(markerPath);
|
|
186
|
+
return stat.mtimeMs;
|
|
187
|
+
} catch {
|
|
188
|
+
return undefined;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export interface ActivityMarkerInfo {
|
|
193
|
+
writer: string;
|
|
194
|
+
/** Relative generated path that was just written, for diagnostics. */
|
|
195
|
+
path?: string;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Best-effort write of the per-session activity marker. State-command callers
|
|
200
|
+
* MUST treat a thrown error as a command failure (auto-detect depends on it);
|
|
201
|
+
* non-critical writers may swallow it.
|
|
202
|
+
*/
|
|
203
|
+
export async function writeSessionActivityMarker(
|
|
204
|
+
cwd: string,
|
|
205
|
+
gjcSessionId: string,
|
|
206
|
+
info: ActivityMarkerInfo,
|
|
207
|
+
): Promise<void> {
|
|
208
|
+
const markerPath = path.join(sessionRoot(cwd, gjcSessionId), GJC_SESSION_ACTIVITY_FILE);
|
|
209
|
+
await fs.mkdir(path.dirname(markerPath), { recursive: true });
|
|
210
|
+
const payload = {
|
|
211
|
+
session_id: gjcSessionId,
|
|
212
|
+
updated_at: new Date().toISOString(),
|
|
213
|
+
writer: info.writer,
|
|
214
|
+
...(info.path ? { path: info.path } : {}),
|
|
215
|
+
};
|
|
216
|
+
await fs.writeFile(markerPath, `${JSON.stringify(payload, null, 2)}\n`, "utf-8");
|
|
217
|
+
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import { CANONICAL_GJC_WORKFLOW_SKILLS } from "../skill-state/active-state";
|
|
1
|
+
import { CANONICAL_GJC_WORKFLOW_SKILLS, type CanonicalGjcWorkflowSkill } from "../skill-state/canonical-skills";
|
|
3
2
|
import { getSkillManifest } from "./workflow-manifest";
|
|
4
3
|
|
|
5
4
|
export type StateGraphSkill = CanonicalGjcWorkflowSkill | "all";
|