@gajae-code/coding-agent 0.2.4 → 0.2.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 +17 -0
- package/README.md +1 -1
- package/dist/types/async/job-manager.d.ts +61 -0
- package/dist/types/config/settings-schema.d.ts +7 -3
- package/dist/types/config/settings.d.ts +1 -1
- package/dist/types/discovery/helpers.d.ts +1 -0
- package/dist/types/exec/bash-executor.d.ts +8 -1
- package/dist/types/gjc-runtime/restricted-role-agent-bash.d.ts +2 -0
- package/dist/types/modes/acp/acp-client-bridge.d.ts +1 -1
- package/dist/types/modes/components/skill-hud/render.d.ts +1 -1
- package/dist/types/modes/interactive-mode.d.ts +1 -0
- package/dist/types/modes/theme/defaults/index.d.ts +45 -9477
- package/dist/types/modes/theme/theme.d.ts +1 -5
- package/dist/types/modes/types.d.ts +1 -0
- package/dist/types/sdk.d.ts +2 -0
- package/dist/types/session/streaming-output.d.ts +11 -0
- package/dist/types/skill-state/active-state.d.ts +1 -0
- package/dist/types/task/types.d.ts +1 -0
- package/dist/types/tools/bash-allowed-prefixes.d.ts +5 -0
- package/dist/types/tools/bash.d.ts +24 -0
- package/dist/types/tools/cron.d.ts +110 -0
- package/dist/types/tools/index.d.ts +4 -0
- package/dist/types/tools/monitor.d.ts +54 -0
- package/dist/types/web/search/index.d.ts +1 -0
- package/dist/types/web/search/provider.d.ts +11 -4
- package/dist/types/web/search/providers/duckduckgo.d.ts +57 -0
- package/dist/types/web/search/types.d.ts +1 -1
- package/package.json +7 -7
- package/src/async/job-manager.ts +224 -0
- package/src/cli/agents-cli.ts +3 -0
- package/src/config/settings-schema.ts +8 -2
- package/src/config/settings.ts +44 -7
- package/src/defaults/gjc/skills/deep-interview/SKILL.md +9 -2
- package/src/defaults/gjc/skills/ralplan/SKILL.md +8 -4
- package/src/discovery/helpers.ts +5 -0
- package/src/eval/js/shared/rewrite-imports.ts +1 -2
- package/src/exec/bash-executor.ts +20 -9
- package/src/gjc-runtime/ralplan-runtime.ts +2 -0
- package/src/gjc-runtime/restricted-role-agent-bash.ts +5 -0
- package/src/hooks/skill-state.ts +1 -1
- package/src/internal-urls/docs-index.generated.ts +5 -3
- package/src/lsp/render.ts +1 -1
- package/src/modes/acp/acp-agent.ts +1 -1
- package/src/modes/acp/acp-client-bridge.ts +1 -1
- package/src/modes/components/agent-dashboard.ts +1 -1
- package/src/modes/components/diff.ts +2 -2
- package/src/modes/components/skill-hud/render.ts +7 -2
- package/src/modes/controllers/input-controller.ts +10 -2
- package/src/modes/controllers/selector-controller.ts +1 -1
- package/src/modes/interactive-mode.ts +20 -2
- package/src/modes/theme/defaults/index.ts +0 -196
- package/src/modes/theme/theme.ts +35 -35
- package/src/modes/types.ts +1 -0
- package/src/prompts/agents/architect.md +5 -1
- package/src/prompts/agents/critic.md +5 -1
- package/src/prompts/agents/frontmatter.md +1 -0
- package/src/prompts/agents/planner.md +5 -1
- package/src/prompts/tools/bash.md +9 -0
- package/src/prompts/tools/cron.md +25 -0
- package/src/prompts/tools/monitor.md +30 -0
- package/src/runtime-mcp/oauth-flow.ts +4 -2
- package/src/sdk.ts +3 -0
- package/src/session/agent-session.ts +16 -5
- package/src/session/streaming-output.ts +21 -0
- package/src/skill-state/active-state.ts +163 -12
- package/src/task/agents.ts +1 -0
- package/src/task/executor.ts +1 -0
- package/src/task/types.ts +1 -0
- package/src/tools/bash-allowed-prefixes.ts +169 -0
- package/src/tools/bash.ts +190 -29
- package/src/tools/browser/tab-worker.ts +1 -1
- package/src/tools/cron.ts +665 -0
- package/src/tools/index.ts +20 -2
- package/src/tools/monitor.ts +136 -0
- package/src/vim/engine.ts +3 -3
- package/src/web/search/index.ts +31 -18
- package/src/web/search/provider.ts +57 -12
- package/src/web/search/providers/duckduckgo.ts +279 -0
- package/src/web/search/types.ts +2 -0
- package/src/modes/theme/dark.json +0 -95
- package/src/modes/theme/defaults/alabaster.json +0 -93
- package/src/modes/theme/defaults/amethyst.json +0 -96
- package/src/modes/theme/defaults/anthracite.json +0 -93
- package/src/modes/theme/defaults/basalt.json +0 -91
- package/src/modes/theme/defaults/birch.json +0 -95
- package/src/modes/theme/defaults/dark-abyss.json +0 -91
- package/src/modes/theme/defaults/dark-arctic.json +0 -104
- package/src/modes/theme/defaults/dark-aurora.json +0 -95
- package/src/modes/theme/defaults/dark-catppuccin.json +0 -107
- package/src/modes/theme/defaults/dark-cavern.json +0 -91
- package/src/modes/theme/defaults/dark-copper.json +0 -95
- package/src/modes/theme/defaults/dark-cosmos.json +0 -90
- package/src/modes/theme/defaults/dark-cyberpunk.json +0 -102
- package/src/modes/theme/defaults/dark-dracula.json +0 -98
- package/src/modes/theme/defaults/dark-eclipse.json +0 -91
- package/src/modes/theme/defaults/dark-ember.json +0 -95
- package/src/modes/theme/defaults/dark-equinox.json +0 -90
- package/src/modes/theme/defaults/dark-forest.json +0 -96
- package/src/modes/theme/defaults/dark-github.json +0 -105
- package/src/modes/theme/defaults/dark-gruvbox.json +0 -112
- package/src/modes/theme/defaults/dark-lavender.json +0 -95
- package/src/modes/theme/defaults/dark-lunar.json +0 -89
- package/src/modes/theme/defaults/dark-midnight.json +0 -95
- package/src/modes/theme/defaults/dark-monochrome.json +0 -94
- package/src/modes/theme/defaults/dark-monokai.json +0 -98
- package/src/modes/theme/defaults/dark-nebula.json +0 -90
- package/src/modes/theme/defaults/dark-nord.json +0 -97
- package/src/modes/theme/defaults/dark-ocean.json +0 -101
- package/src/modes/theme/defaults/dark-one.json +0 -100
- package/src/modes/theme/defaults/dark-poimandres.json +0 -141
- package/src/modes/theme/defaults/dark-rainforest.json +0 -91
- package/src/modes/theme/defaults/dark-reef.json +0 -91
- package/src/modes/theme/defaults/dark-retro.json +0 -92
- package/src/modes/theme/defaults/dark-rose-pine.json +0 -96
- package/src/modes/theme/defaults/dark-sakura.json +0 -95
- package/src/modes/theme/defaults/dark-slate.json +0 -95
- package/src/modes/theme/defaults/dark-solarized.json +0 -97
- package/src/modes/theme/defaults/dark-solstice.json +0 -90
- package/src/modes/theme/defaults/dark-starfall.json +0 -91
- package/src/modes/theme/defaults/dark-sunset.json +0 -99
- package/src/modes/theme/defaults/dark-swamp.json +0 -90
- package/src/modes/theme/defaults/dark-synthwave.json +0 -103
- package/src/modes/theme/defaults/dark-taiga.json +0 -91
- package/src/modes/theme/defaults/dark-terminal.json +0 -95
- package/src/modes/theme/defaults/dark-tokyo-night.json +0 -101
- package/src/modes/theme/defaults/dark-tundra.json +0 -91
- package/src/modes/theme/defaults/dark-twilight.json +0 -91
- package/src/modes/theme/defaults/dark-volcanic.json +0 -91
- package/src/modes/theme/defaults/graphite.json +0 -92
- package/src/modes/theme/defaults/light-arctic.json +0 -107
- package/src/modes/theme/defaults/light-aurora-day.json +0 -91
- package/src/modes/theme/defaults/light-canyon.json +0 -91
- package/src/modes/theme/defaults/light-catppuccin.json +0 -106
- package/src/modes/theme/defaults/light-cirrus.json +0 -90
- package/src/modes/theme/defaults/light-coral.json +0 -95
- package/src/modes/theme/defaults/light-cyberpunk.json +0 -96
- package/src/modes/theme/defaults/light-dawn.json +0 -90
- package/src/modes/theme/defaults/light-dunes.json +0 -91
- package/src/modes/theme/defaults/light-eucalyptus.json +0 -95
- package/src/modes/theme/defaults/light-forest.json +0 -100
- package/src/modes/theme/defaults/light-frost.json +0 -95
- package/src/modes/theme/defaults/light-github.json +0 -115
- package/src/modes/theme/defaults/light-glacier.json +0 -91
- package/src/modes/theme/defaults/light-gruvbox.json +0 -108
- package/src/modes/theme/defaults/light-haze.json +0 -90
- package/src/modes/theme/defaults/light-honeycomb.json +0 -95
- package/src/modes/theme/defaults/light-lagoon.json +0 -91
- package/src/modes/theme/defaults/light-lavender.json +0 -95
- package/src/modes/theme/defaults/light-meadow.json +0 -91
- package/src/modes/theme/defaults/light-mint.json +0 -95
- package/src/modes/theme/defaults/light-monochrome.json +0 -101
- package/src/modes/theme/defaults/light-ocean.json +0 -99
- package/src/modes/theme/defaults/light-one.json +0 -99
- package/src/modes/theme/defaults/light-opal.json +0 -91
- package/src/modes/theme/defaults/light-orchard.json +0 -91
- package/src/modes/theme/defaults/light-paper.json +0 -95
- package/src/modes/theme/defaults/light-poimandres.json +0 -141
- package/src/modes/theme/defaults/light-prism.json +0 -90
- package/src/modes/theme/defaults/light-retro.json +0 -98
- package/src/modes/theme/defaults/light-sand.json +0 -95
- package/src/modes/theme/defaults/light-savanna.json +0 -91
- package/src/modes/theme/defaults/light-solarized.json +0 -102
- package/src/modes/theme/defaults/light-soleil.json +0 -90
- package/src/modes/theme/defaults/light-sunset.json +0 -99
- package/src/modes/theme/defaults/light-synthwave.json +0 -98
- package/src/modes/theme/defaults/light-tokyo-night.json +0 -111
- package/src/modes/theme/defaults/light-wetland.json +0 -91
- package/src/modes/theme/defaults/light-zenith.json +0 -89
- package/src/modes/theme/defaults/limestone.json +0 -94
- package/src/modes/theme/defaults/mahogany.json +0 -97
- package/src/modes/theme/defaults/marble.json +0 -93
- package/src/modes/theme/defaults/obsidian.json +0 -91
- package/src/modes/theme/defaults/onyx.json +0 -91
- package/src/modes/theme/defaults/pearl.json +0 -93
- package/src/modes/theme/defaults/porcelain.json +0 -91
- package/src/modes/theme/defaults/quartz.json +0 -96
- package/src/modes/theme/defaults/sandstone.json +0 -95
- package/src/modes/theme/defaults/titanium.json +0 -90
- package/src/modes/theme/light.json +0 -93
package/src/lsp/render.ts
CHANGED
|
@@ -103,7 +103,7 @@ export function renderResult(
|
|
|
103
103
|
args?: LspParams,
|
|
104
104
|
): Component {
|
|
105
105
|
const content = result.content?.[0];
|
|
106
|
-
if (
|
|
106
|
+
if (content?.type !== "text" || !("text" in content) || !content.text) {
|
|
107
107
|
const icon = formatStatusIcon("warning", theme, options.spinnerFrame);
|
|
108
108
|
const header = `${icon} LSP`;
|
|
109
109
|
return new Text([header, theme.fg("dim", "No result")].join("\n"), 0, 0);
|
|
@@ -272,7 +272,7 @@ async function elicitFromAcpClient(
|
|
|
272
272
|
finish(undefined);
|
|
273
273
|
});
|
|
274
274
|
const response = await promise;
|
|
275
|
-
if (
|
|
275
|
+
if (response?.action !== "accept" || !response.content) {
|
|
276
276
|
return undefined;
|
|
277
277
|
}
|
|
278
278
|
return response.content.value;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* ACP-side `ClientBridge` implementation. Wraps `AgentSideConnection` so the
|
|
3
|
-
* `read`/`write`/`bash`/`edit` tools (and the permission gate in
|
|
3
|
+
* `read`/`write`/`bash`/`monitor`/`edit` tools (and the permission gate in
|
|
4
4
|
* `AgentSession`) can route through the client when it advertises the
|
|
5
5
|
* relevant capabilities at `initialize` time.
|
|
6
6
|
*/
|
|
@@ -121,7 +121,7 @@ function matchAgent(agent: DashboardAgent, query: string): boolean {
|
|
|
121
121
|
function extractAssistantText(messages: AgentMessage[]): string | null {
|
|
122
122
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
123
123
|
const message = messages[i];
|
|
124
|
-
if (
|
|
124
|
+
if (message?.role !== "assistant") continue;
|
|
125
125
|
const blocks = message.content;
|
|
126
126
|
if (!Array.isArray(blocks)) continue;
|
|
127
127
|
const text = blocks
|
|
@@ -151,7 +151,7 @@ export function renderDiff(diffText: string, options: RenderDiffOptions = {}): s
|
|
|
151
151
|
const removedLines: { lineNum: string; content: string }[] = [];
|
|
152
152
|
while (i < lines.length) {
|
|
153
153
|
const p = parseDiffLine(lines[i]);
|
|
154
|
-
if (
|
|
154
|
+
if (p?.prefix !== "-") break;
|
|
155
155
|
removedLines.push({ lineNum: p.lineNum, content: p.content });
|
|
156
156
|
i++;
|
|
157
157
|
}
|
|
@@ -159,7 +159,7 @@ export function renderDiff(diffText: string, options: RenderDiffOptions = {}): s
|
|
|
159
159
|
const addedLines: { lineNum: string; content: string }[] = [];
|
|
160
160
|
while (i < lines.length) {
|
|
161
161
|
const p = parseDiffLine(lines[i]);
|
|
162
|
-
if (
|
|
162
|
+
if (p?.prefix !== "+") break;
|
|
163
163
|
addedLines.push({ lineNum: p.lineNum, content: p.content });
|
|
164
164
|
i++;
|
|
165
165
|
}
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import {
|
|
2
|
+
collapsePlanningPipeline,
|
|
3
|
+
type SkillActiveEntry,
|
|
4
|
+
type WorkflowHudChip,
|
|
5
|
+
} from "../../../skill-state/active-state";
|
|
2
6
|
import { workflowReceiptStatus } from "../../../skill-state/workflow-state-contract";
|
|
3
7
|
|
|
4
8
|
const ANSI_RESET_FG = "\x1b[39m";
|
|
@@ -69,7 +73,8 @@ function formatEntry(entry: SkillActiveEntry): string {
|
|
|
69
73
|
}
|
|
70
74
|
|
|
71
75
|
export function renderSkillHudBar(entries: readonly SkillActiveEntry[], width: number): string | null {
|
|
72
|
-
const
|
|
76
|
+
const visible = collapsePlanningPipeline(entries.filter(entry => entry.active !== false));
|
|
77
|
+
const active = visible.filter(entry => sanitizeHudPart(entry.skill)).sort(compareEntries);
|
|
73
78
|
if (active.length === 0 || width <= 0) return null;
|
|
74
79
|
const body = active.map(formatEntry).join(" + ");
|
|
75
80
|
const prefix = `${ANSI_BORDER}◆${ANSI_RESET_FG} ${ANSI_BOLD}${ANSI_ACCENT}hud${ANSI_RESET_FG}${ANSI_RESET_BOLD} `;
|
|
@@ -64,6 +64,7 @@ export class InputController {
|
|
|
64
64
|
} else if (this.ctx.isBashMode) {
|
|
65
65
|
this.ctx.editor.setText("");
|
|
66
66
|
this.ctx.isBashMode = false;
|
|
67
|
+
this.ctx.isBashNoContext = false;
|
|
67
68
|
this.ctx.updateEditorBorderColor();
|
|
68
69
|
} else if (this.ctx.session.isEvalRunning) {
|
|
69
70
|
this.ctx.session.abortEval();
|
|
@@ -172,11 +173,17 @@ export class InputController {
|
|
|
172
173
|
|
|
173
174
|
this.ctx.editor.onChange = (text: string) => {
|
|
174
175
|
const wasBashMode = this.ctx.isBashMode;
|
|
176
|
+
const wasBashNoContext = this.ctx.isBashNoContext;
|
|
175
177
|
const wasPythonMode = this.ctx.isPythonMode;
|
|
176
178
|
const trimmed = text.trimStart();
|
|
177
|
-
this.ctx.isBashMode =
|
|
179
|
+
this.ctx.isBashMode = trimmed.startsWith("!");
|
|
180
|
+
this.ctx.isBashNoContext = trimmed.startsWith("!!");
|
|
178
181
|
this.ctx.isPythonMode = trimmed.startsWith("$") && !trimmed.startsWith("${");
|
|
179
|
-
if (
|
|
182
|
+
if (
|
|
183
|
+
wasBashMode !== this.ctx.isBashMode ||
|
|
184
|
+
wasBashNoContext !== this.ctx.isBashNoContext ||
|
|
185
|
+
wasPythonMode !== this.ctx.isPythonMode
|
|
186
|
+
) {
|
|
180
187
|
this.ctx.updateEditorBorderColor();
|
|
181
188
|
}
|
|
182
189
|
};
|
|
@@ -260,6 +267,7 @@ export class InputController {
|
|
|
260
267
|
this.ctx.editor.addToHistory(text);
|
|
261
268
|
await this.ctx.handleBashCommand(command, isExcluded);
|
|
262
269
|
this.ctx.isBashMode = false;
|
|
270
|
+
this.ctx.isBashNoContext = false;
|
|
263
271
|
this.ctx.updateEditorBorderColor();
|
|
264
272
|
return;
|
|
265
273
|
}
|
|
@@ -112,12 +112,23 @@ const HINT_SHIMMER_PALETTE: ShimmerPalette = {
|
|
|
112
112
|
high: "borderAccent",
|
|
113
113
|
};
|
|
114
114
|
|
|
115
|
+
function getDefaultInputPrefix(): string {
|
|
116
|
+
return `${theme.fg("accent", ">")} `;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function getShellInputPrefix(isNoContext: boolean): string {
|
|
120
|
+
const shellLabel = isNoContext
|
|
121
|
+
? theme.fg("warning", theme.bold("shell no-context"))
|
|
122
|
+
: theme.fg("bashMode", theme.bold("shell"));
|
|
123
|
+
return `${shellLabel} ${getDefaultInputPrefix()}`;
|
|
124
|
+
}
|
|
125
|
+
|
|
115
126
|
function configureDefaultComposerChrome(editor: CustomEditor): void {
|
|
116
127
|
editor.setBorderVisible(true);
|
|
117
128
|
editor.setBorderStyle("sharp");
|
|
118
129
|
editor.setClosedBorderBox(true);
|
|
119
130
|
editor.setPromptGutter(undefined);
|
|
120
|
-
editor.setInputPrefix(
|
|
131
|
+
editor.setInputPrefix(getDefaultInputPrefix());
|
|
121
132
|
editor.setPlaceholder("Type your message...");
|
|
122
133
|
editor.setPaddingX(1);
|
|
123
134
|
editor.setTopBorder(undefined);
|
|
@@ -236,6 +247,7 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
236
247
|
isInitialized = false;
|
|
237
248
|
isBackgrounded = false;
|
|
238
249
|
isBashMode = false;
|
|
250
|
+
isBashNoContext = false;
|
|
239
251
|
toolOutputExpanded = false;
|
|
240
252
|
todoExpanded = false;
|
|
241
253
|
planModeEnabled = false;
|
|
@@ -808,7 +820,10 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
808
820
|
|
|
809
821
|
updateEditorChrome(): void {
|
|
810
822
|
if (this.isBashMode) {
|
|
811
|
-
this.editor.borderColor =
|
|
823
|
+
this.editor.borderColor = this.isBashNoContext
|
|
824
|
+
? (str: string) => theme.fg("warning", str)
|
|
825
|
+
: theme.getBashModeBorderColor();
|
|
826
|
+
this.editor.setInputPrefix(getShellInputPrefix(this.isBashNoContext));
|
|
812
827
|
} else if (this.isPythonMode) {
|
|
813
828
|
this.editor.borderColor = theme.getPythonModeBorderColor();
|
|
814
829
|
} else {
|
|
@@ -823,6 +838,9 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
823
838
|
this.editor.borderColor = theme.getThinkingBorderColor(level);
|
|
824
839
|
}
|
|
825
840
|
}
|
|
841
|
+
if (!this.isBashMode) {
|
|
842
|
+
this.editor.setInputPrefix(getDefaultInputPrefix());
|
|
843
|
+
}
|
|
826
844
|
this.#setComposerTopBorder();
|
|
827
845
|
this.ui.requestRender();
|
|
828
846
|
}
|
|
@@ -1,203 +1,7 @@
|
|
|
1
|
-
import alabaster from "./alabaster.json" with { type: "json" };
|
|
2
|
-
import amethyst from "./amethyst.json" with { type: "json" };
|
|
3
|
-
import anthracite from "./anthracite.json" with { type: "json" };
|
|
4
|
-
import basalt from "./basalt.json" with { type: "json" };
|
|
5
|
-
import birch from "./birch.json" with { type: "json" };
|
|
6
1
|
import blue_crab from "./blue-crab.json" with { type: "json" };
|
|
7
|
-
import dark_abyss from "./dark-abyss.json" with { type: "json" };
|
|
8
|
-
import dark_arctic from "./dark-arctic.json" with { type: "json" };
|
|
9
|
-
import dark_aurora from "./dark-aurora.json" with { type: "json" };
|
|
10
|
-
import dark_catppuccin from "./dark-catppuccin.json" with { type: "json" };
|
|
11
|
-
import dark_cavern from "./dark-cavern.json" with { type: "json" };
|
|
12
|
-
import dark_copper from "./dark-copper.json" with { type: "json" };
|
|
13
|
-
import dark_cosmos from "./dark-cosmos.json" with { type: "json" };
|
|
14
|
-
import dark_cyberpunk from "./dark-cyberpunk.json" with { type: "json" };
|
|
15
|
-
import dark_dracula from "./dark-dracula.json" with { type: "json" };
|
|
16
|
-
import dark_eclipse from "./dark-eclipse.json" with { type: "json" };
|
|
17
|
-
import dark_ember from "./dark-ember.json" with { type: "json" };
|
|
18
|
-
import dark_equinox from "./dark-equinox.json" with { type: "json" };
|
|
19
|
-
import dark_forest from "./dark-forest.json" with { type: "json" };
|
|
20
|
-
import dark_github from "./dark-github.json" with { type: "json" };
|
|
21
|
-
import dark_gruvbox from "./dark-gruvbox.json" with { type: "json" };
|
|
22
|
-
import dark_lavender from "./dark-lavender.json" with { type: "json" };
|
|
23
|
-
import dark_lunar from "./dark-lunar.json" with { type: "json" };
|
|
24
|
-
import dark_midnight from "./dark-midnight.json" with { type: "json" };
|
|
25
|
-
import dark_monochrome from "./dark-monochrome.json" with { type: "json" };
|
|
26
|
-
import dark_monokai from "./dark-monokai.json" with { type: "json" };
|
|
27
|
-
import dark_nebula from "./dark-nebula.json" with { type: "json" };
|
|
28
|
-
import dark_nord from "./dark-nord.json" with { type: "json" };
|
|
29
|
-
import dark_ocean from "./dark-ocean.json" with { type: "json" };
|
|
30
|
-
import dark_one from "./dark-one.json" with { type: "json" };
|
|
31
|
-
import dark_poimandres from "./dark-poimandres.json" with { type: "json" };
|
|
32
|
-
import dark_rainforest from "./dark-rainforest.json" with { type: "json" };
|
|
33
|
-
import dark_reef from "./dark-reef.json" with { type: "json" };
|
|
34
|
-
import dark_retro from "./dark-retro.json" with { type: "json" };
|
|
35
|
-
import dark_rose_pine from "./dark-rose-pine.json" with { type: "json" };
|
|
36
|
-
import dark_sakura from "./dark-sakura.json" with { type: "json" };
|
|
37
|
-
import dark_slate from "./dark-slate.json" with { type: "json" };
|
|
38
|
-
import dark_solarized from "./dark-solarized.json" with { type: "json" };
|
|
39
|
-
import dark_solstice from "./dark-solstice.json" with { type: "json" };
|
|
40
|
-
import dark_starfall from "./dark-starfall.json" with { type: "json" };
|
|
41
|
-
import dark_sunset from "./dark-sunset.json" with { type: "json" };
|
|
42
|
-
import dark_swamp from "./dark-swamp.json" with { type: "json" };
|
|
43
|
-
import dark_synthwave from "./dark-synthwave.json" with { type: "json" };
|
|
44
|
-
import dark_taiga from "./dark-taiga.json" with { type: "json" };
|
|
45
|
-
import dark_terminal from "./dark-terminal.json" with { type: "json" };
|
|
46
|
-
import dark_tokyo_night from "./dark-tokyo-night.json" with { type: "json" };
|
|
47
|
-
import dark_tundra from "./dark-tundra.json" with { type: "json" };
|
|
48
|
-
import dark_twilight from "./dark-twilight.json" with { type: "json" };
|
|
49
|
-
import dark_volcanic from "./dark-volcanic.json" with { type: "json" };
|
|
50
|
-
import graphite from "./graphite.json" with { type: "json" };
|
|
51
|
-
import light_arctic from "./light-arctic.json" with { type: "json" };
|
|
52
|
-
import light_aurora_day from "./light-aurora-day.json" with { type: "json" };
|
|
53
|
-
import light_canyon from "./light-canyon.json" with { type: "json" };
|
|
54
|
-
import light_catppuccin from "./light-catppuccin.json" with { type: "json" };
|
|
55
|
-
import light_cirrus from "./light-cirrus.json" with { type: "json" };
|
|
56
|
-
import light_coral from "./light-coral.json" with { type: "json" };
|
|
57
|
-
import light_cyberpunk from "./light-cyberpunk.json" with { type: "json" };
|
|
58
|
-
import light_dawn from "./light-dawn.json" with { type: "json" };
|
|
59
|
-
import light_dunes from "./light-dunes.json" with { type: "json" };
|
|
60
|
-
import light_eucalyptus from "./light-eucalyptus.json" with { type: "json" };
|
|
61
|
-
import light_forest from "./light-forest.json" with { type: "json" };
|
|
62
|
-
import light_frost from "./light-frost.json" with { type: "json" };
|
|
63
|
-
import light_github from "./light-github.json" with { type: "json" };
|
|
64
|
-
import light_glacier from "./light-glacier.json" with { type: "json" };
|
|
65
|
-
import light_gruvbox from "./light-gruvbox.json" with { type: "json" };
|
|
66
|
-
import light_haze from "./light-haze.json" with { type: "json" };
|
|
67
|
-
import light_honeycomb from "./light-honeycomb.json" with { type: "json" };
|
|
68
|
-
import light_lagoon from "./light-lagoon.json" with { type: "json" };
|
|
69
|
-
import light_lavender from "./light-lavender.json" with { type: "json" };
|
|
70
|
-
import light_meadow from "./light-meadow.json" with { type: "json" };
|
|
71
|
-
import light_mint from "./light-mint.json" with { type: "json" };
|
|
72
|
-
import light_monochrome from "./light-monochrome.json" with { type: "json" };
|
|
73
|
-
import light_ocean from "./light-ocean.json" with { type: "json" };
|
|
74
|
-
import light_one from "./light-one.json" with { type: "json" };
|
|
75
|
-
import light_opal from "./light-opal.json" with { type: "json" };
|
|
76
|
-
import light_orchard from "./light-orchard.json" with { type: "json" };
|
|
77
|
-
import light_paper from "./light-paper.json" with { type: "json" };
|
|
78
|
-
import light_poimandres from "./light-poimandres.json" with { type: "json" };
|
|
79
|
-
import light_prism from "./light-prism.json" with { type: "json" };
|
|
80
|
-
import light_retro from "./light-retro.json" with { type: "json" };
|
|
81
|
-
import light_sand from "./light-sand.json" with { type: "json" };
|
|
82
|
-
import light_savanna from "./light-savanna.json" with { type: "json" };
|
|
83
|
-
import light_solarized from "./light-solarized.json" with { type: "json" };
|
|
84
|
-
import light_soleil from "./light-soleil.json" with { type: "json" };
|
|
85
|
-
import light_sunset from "./light-sunset.json" with { type: "json" };
|
|
86
|
-
import light_synthwave from "./light-synthwave.json" with { type: "json" };
|
|
87
|
-
import light_tokyo_night from "./light-tokyo-night.json" with { type: "json" };
|
|
88
|
-
import light_wetland from "./light-wetland.json" with { type: "json" };
|
|
89
|
-
import light_zenith from "./light-zenith.json" with { type: "json" };
|
|
90
|
-
import limestone from "./limestone.json" with { type: "json" };
|
|
91
|
-
import mahogany from "./mahogany.json" with { type: "json" };
|
|
92
|
-
import marble from "./marble.json" with { type: "json" };
|
|
93
|
-
import obsidian from "./obsidian.json" with { type: "json" };
|
|
94
|
-
import onyx from "./onyx.json" with { type: "json" };
|
|
95
|
-
import pearl from "./pearl.json" with { type: "json" };
|
|
96
|
-
import porcelain from "./porcelain.json" with { type: "json" };
|
|
97
|
-
import quartz from "./quartz.json" with { type: "json" };
|
|
98
2
|
import red_claw from "./red-claw.json" with { type: "json" };
|
|
99
|
-
import sandstone from "./sandstone.json" with { type: "json" };
|
|
100
|
-
import titanium from "./titanium.json" with { type: "json" };
|
|
101
3
|
|
|
102
4
|
export const defaultThemes = {
|
|
103
|
-
alabaster: alabaster,
|
|
104
|
-
amethyst: amethyst,
|
|
105
|
-
anthracite: anthracite,
|
|
106
|
-
basalt: basalt,
|
|
107
|
-
birch: birch,
|
|
108
5
|
"blue-crab": blue_crab,
|
|
109
|
-
"dark-abyss": dark_abyss,
|
|
110
|
-
"dark-arctic": dark_arctic,
|
|
111
|
-
"dark-aurora": dark_aurora,
|
|
112
|
-
"dark-catppuccin": dark_catppuccin,
|
|
113
|
-
"dark-cavern": dark_cavern,
|
|
114
|
-
"dark-copper": dark_copper,
|
|
115
|
-
"dark-cosmos": dark_cosmos,
|
|
116
|
-
"dark-cyberpunk": dark_cyberpunk,
|
|
117
|
-
"dark-dracula": dark_dracula,
|
|
118
|
-
"dark-eclipse": dark_eclipse,
|
|
119
|
-
"dark-ember": dark_ember,
|
|
120
|
-
"dark-equinox": dark_equinox,
|
|
121
|
-
"dark-forest": dark_forest,
|
|
122
|
-
"dark-github": dark_github,
|
|
123
|
-
"dark-gruvbox": dark_gruvbox,
|
|
124
|
-
"dark-lavender": dark_lavender,
|
|
125
|
-
"dark-lunar": dark_lunar,
|
|
126
|
-
"dark-midnight": dark_midnight,
|
|
127
|
-
"dark-monochrome": dark_monochrome,
|
|
128
|
-
"dark-monokai": dark_monokai,
|
|
129
|
-
"dark-nebula": dark_nebula,
|
|
130
|
-
"dark-nord": dark_nord,
|
|
131
|
-
"dark-ocean": dark_ocean,
|
|
132
|
-
"dark-one": dark_one,
|
|
133
|
-
"dark-poimandres": dark_poimandres,
|
|
134
|
-
"dark-rainforest": dark_rainforest,
|
|
135
|
-
"dark-reef": dark_reef,
|
|
136
|
-
"dark-retro": dark_retro,
|
|
137
|
-
"dark-rose-pine": dark_rose_pine,
|
|
138
|
-
"dark-sakura": dark_sakura,
|
|
139
|
-
"dark-slate": dark_slate,
|
|
140
|
-
"dark-solarized": dark_solarized,
|
|
141
|
-
"dark-solstice": dark_solstice,
|
|
142
|
-
"dark-starfall": dark_starfall,
|
|
143
|
-
"dark-sunset": dark_sunset,
|
|
144
|
-
"dark-swamp": dark_swamp,
|
|
145
|
-
"dark-synthwave": dark_synthwave,
|
|
146
|
-
"dark-taiga": dark_taiga,
|
|
147
|
-
"dark-terminal": dark_terminal,
|
|
148
|
-
"dark-tokyo-night": dark_tokyo_night,
|
|
149
|
-
"dark-tundra": dark_tundra,
|
|
150
|
-
"dark-twilight": dark_twilight,
|
|
151
|
-
"dark-volcanic": dark_volcanic,
|
|
152
|
-
graphite: graphite,
|
|
153
|
-
"light-arctic": light_arctic,
|
|
154
|
-
"light-aurora-day": light_aurora_day,
|
|
155
|
-
"light-canyon": light_canyon,
|
|
156
|
-
"light-catppuccin": light_catppuccin,
|
|
157
|
-
"light-cirrus": light_cirrus,
|
|
158
|
-
"light-coral": light_coral,
|
|
159
|
-
"light-cyberpunk": light_cyberpunk,
|
|
160
|
-
"light-dawn": light_dawn,
|
|
161
|
-
"light-dunes": light_dunes,
|
|
162
|
-
"light-eucalyptus": light_eucalyptus,
|
|
163
|
-
"light-forest": light_forest,
|
|
164
|
-
"light-frost": light_frost,
|
|
165
|
-
"light-github": light_github,
|
|
166
|
-
"light-glacier": light_glacier,
|
|
167
|
-
"light-gruvbox": light_gruvbox,
|
|
168
|
-
"light-haze": light_haze,
|
|
169
|
-
"light-honeycomb": light_honeycomb,
|
|
170
|
-
"light-lagoon": light_lagoon,
|
|
171
|
-
"light-lavender": light_lavender,
|
|
172
|
-
"light-meadow": light_meadow,
|
|
173
|
-
"light-mint": light_mint,
|
|
174
|
-
"light-monochrome": light_monochrome,
|
|
175
|
-
"light-ocean": light_ocean,
|
|
176
|
-
"light-one": light_one,
|
|
177
|
-
"light-opal": light_opal,
|
|
178
|
-
"light-orchard": light_orchard,
|
|
179
|
-
"light-paper": light_paper,
|
|
180
|
-
"light-poimandres": light_poimandres,
|
|
181
|
-
"light-prism": light_prism,
|
|
182
|
-
"light-retro": light_retro,
|
|
183
|
-
"light-sand": light_sand,
|
|
184
|
-
"light-savanna": light_savanna,
|
|
185
|
-
"light-solarized": light_solarized,
|
|
186
|
-
"light-soleil": light_soleil,
|
|
187
|
-
"light-sunset": light_sunset,
|
|
188
|
-
"light-synthwave": light_synthwave,
|
|
189
|
-
"light-tokyo-night": light_tokyo_night,
|
|
190
|
-
"light-wetland": light_wetland,
|
|
191
|
-
"light-zenith": light_zenith,
|
|
192
|
-
limestone: limestone,
|
|
193
|
-
mahogany: mahogany,
|
|
194
|
-
marble: marble,
|
|
195
|
-
obsidian: obsidian,
|
|
196
|
-
onyx: onyx,
|
|
197
|
-
pearl: pearl,
|
|
198
|
-
porcelain: porcelain,
|
|
199
|
-
quartz: quartz,
|
|
200
6
|
"red-claw": red_claw,
|
|
201
|
-
sandstone: sandstone,
|
|
202
|
-
titanium: titanium,
|
|
203
7
|
};
|
package/src/modes/theme/theme.ts
CHANGED
|
@@ -14,9 +14,7 @@ import { adjustHsv, getCustomThemesDir, isEnoent, logger } from "@gajae-code/uti
|
|
|
14
14
|
import chalk from "chalk";
|
|
15
15
|
import * as z from "zod/v4";
|
|
16
16
|
// Embed theme JSON files at build time
|
|
17
|
-
import darkThemeJson from "./dark.json" with { type: "json" };
|
|
18
17
|
import { defaultThemes } from "./defaults";
|
|
19
|
-
import lightThemeJson from "./light.json" with { type: "json" };
|
|
20
18
|
import { resolveMermaidAscii } from "./mermaid-cache";
|
|
21
19
|
|
|
22
20
|
export { getLanguageFromPath } from "../../utils/lang-from-path";
|
|
@@ -1547,8 +1545,6 @@ export class Theme {
|
|
|
1547
1545
|
// ============================================================================
|
|
1548
1546
|
|
|
1549
1547
|
const BUILTIN_THEMES: Record<string, ThemeJson> = {
|
|
1550
|
-
dark: darkThemeJson as ThemeJson,
|
|
1551
|
-
light: lightThemeJson as ThemeJson,
|
|
1552
1548
|
...(defaultThemes as Record<string, ThemeJson>),
|
|
1553
1549
|
};
|
|
1554
1550
|
|
|
@@ -1646,7 +1642,7 @@ async function loadThemeJson(name: string): Promise<ThemeJson> {
|
|
|
1646
1642
|
errorMessage += `\nMissing required color tokens:\n`;
|
|
1647
1643
|
errorMessage += missingColors.map(c => ` - ${c}`).join("\n");
|
|
1648
1644
|
errorMessage += `\n\nPlease add these colors to your theme's "colors" object.`;
|
|
1649
|
-
errorMessage += `\nSee the built-in themes (
|
|
1645
|
+
errorMessage += `\nSee the built-in themes (red-claw.json, blue-crab.json) for reference values.`;
|
|
1650
1646
|
}
|
|
1651
1647
|
if (otherErrors.length > 0) {
|
|
1652
1648
|
errorMessage += `\n\nOther errors:\n${otherErrors.join("\n")}`;
|
|
@@ -1780,7 +1776,7 @@ var themeReloadTimer: NodeJS.Timeout | undefined;
|
|
|
1780
1776
|
var sigwinchHandler: (() => void) | undefined;
|
|
1781
1777
|
var autoDetectedTheme: boolean = false;
|
|
1782
1778
|
var autoDarkTheme: string = "red-claw";
|
|
1783
|
-
var autoLightTheme: string = "
|
|
1779
|
+
var autoLightTheme: string = "blue-crab";
|
|
1784
1780
|
var onThemeChangeCallback: (() => void) | undefined;
|
|
1785
1781
|
var themeLoadRequestId: number = 0;
|
|
1786
1782
|
var previewThemeActive: boolean = false;
|
|
@@ -1801,7 +1797,7 @@ export async function initTheme(
|
|
|
1801
1797
|
): Promise<void> {
|
|
1802
1798
|
autoDetectedTheme = true;
|
|
1803
1799
|
autoDarkTheme = darkTheme ?? "red-claw";
|
|
1804
|
-
autoLightTheme = lightTheme ?? "
|
|
1800
|
+
autoLightTheme = lightTheme ?? "blue-crab";
|
|
1805
1801
|
const name = getDefaultTheme();
|
|
1806
1802
|
previewThemeActive = false;
|
|
1807
1803
|
currentThemeName = name;
|
|
@@ -1814,9 +1810,9 @@ export async function initTheme(
|
|
|
1814
1810
|
startSigwinchListener();
|
|
1815
1811
|
}
|
|
1816
1812
|
} catch (err) {
|
|
1817
|
-
logger.debug("Theme loading failed, falling back to
|
|
1818
|
-
currentThemeName = "
|
|
1819
|
-
theme = await loadTheme("
|
|
1813
|
+
logger.debug("Theme loading failed, falling back to red-claw theme", { error: String(err) });
|
|
1814
|
+
currentThemeName = "red-claw";
|
|
1815
|
+
theme = await loadTheme("red-claw", getCurrentThemeOptions());
|
|
1820
1816
|
// Don't start watcher for fallback theme
|
|
1821
1817
|
}
|
|
1822
1818
|
}
|
|
@@ -1846,9 +1842,9 @@ export async function setTheme(
|
|
|
1846
1842
|
if (requestId !== themeLoadRequestId) {
|
|
1847
1843
|
return { success: false, error: "Theme change superseded by a newer request" };
|
|
1848
1844
|
}
|
|
1849
|
-
// Theme is invalid - fall back to
|
|
1850
|
-
currentThemeName = "
|
|
1851
|
-
theme = await loadTheme("
|
|
1845
|
+
// Theme is invalid - fall back to red-claw theme
|
|
1846
|
+
currentThemeName = "red-claw";
|
|
1847
|
+
theme = await loadTheme("red-claw", getCurrentThemeOptions());
|
|
1852
1848
|
// Don't start watcher for fallback theme
|
|
1853
1849
|
return {
|
|
1854
1850
|
success: false,
|
|
@@ -1956,8 +1952,8 @@ export async function setSymbolPreset(preset: SymbolPreset): Promise<void> {
|
|
|
1956
1952
|
try {
|
|
1957
1953
|
theme = await loadTheme(currentThemeName, getCurrentThemeOptions());
|
|
1958
1954
|
} catch {
|
|
1959
|
-
// Fall back to
|
|
1960
|
-
theme = await loadTheme("
|
|
1955
|
+
// Fall back to red-claw theme with new preset
|
|
1956
|
+
theme = await loadTheme("red-claw", getCurrentThemeOptions());
|
|
1961
1957
|
}
|
|
1962
1958
|
if (onThemeChangeCallback) {
|
|
1963
1959
|
onThemeChangeCallback();
|
|
@@ -1982,8 +1978,8 @@ export async function setColorBlindMode(enabled: boolean): Promise<void> {
|
|
|
1982
1978
|
try {
|
|
1983
1979
|
theme = await loadTheme(currentThemeName, getCurrentThemeOptions());
|
|
1984
1980
|
} catch {
|
|
1985
|
-
// Fall back to
|
|
1986
|
-
theme = await loadTheme("
|
|
1981
|
+
// Fall back to red-claw theme
|
|
1982
|
+
theme = await loadTheme("red-claw", getCurrentThemeOptions());
|
|
1987
1983
|
}
|
|
1988
1984
|
if (onThemeChangeCallback) {
|
|
1989
1985
|
onThemeChangeCallback();
|
|
@@ -2019,8 +2015,8 @@ export function isValidSymbolPreset(preset: string): preset is SymbolPreset {
|
|
|
2019
2015
|
async function startThemeWatcher(): Promise<void> {
|
|
2020
2016
|
stopThemeWatcher();
|
|
2021
2017
|
|
|
2022
|
-
// Only watch
|
|
2023
|
-
if (!currentThemeName || currentThemeName
|
|
2018
|
+
// Only watch custom themes (not built-ins)
|
|
2019
|
+
if (!currentThemeName || currentThemeName in getBuiltinThemes()) {
|
|
2024
2020
|
return;
|
|
2025
2021
|
}
|
|
2026
2022
|
|
|
@@ -2230,8 +2226,8 @@ function ansi256ToHex(index: number): string {
|
|
|
2230
2226
|
*/
|
|
2231
2227
|
export async function getResolvedThemeColors(themeName?: string): Promise<Record<string, string>> {
|
|
2232
2228
|
const name = themeName ?? getDefaultTheme();
|
|
2233
|
-
const isLight = name === "light";
|
|
2234
2229
|
const themeJson = await loadThemeJson(name);
|
|
2230
|
+
const isLight = isThemeJsonLight(themeJson);
|
|
2235
2231
|
const resolved = resolveThemeColors(themeJson.colors, themeJson.vars);
|
|
2236
2232
|
|
|
2237
2233
|
// Default text color for empty values (terminal uses default fg color)
|
|
@@ -2255,21 +2251,7 @@ export async function getResolvedThemeColors(themeName?: string): Promise<Record
|
|
|
2255
2251
|
* Check if a theme is a "light" theme by analyzing its background color luminance.
|
|
2256
2252
|
* Loads theme JSON synchronously (built-in or custom file) and resolves userMessageBg.
|
|
2257
2253
|
*/
|
|
2258
|
-
|
|
2259
|
-
const name = themeName ?? "dark";
|
|
2260
|
-
const builtinThemes = getBuiltinThemes();
|
|
2261
|
-
let themeJson: ThemeJson | undefined;
|
|
2262
|
-
if (name in builtinThemes) {
|
|
2263
|
-
themeJson = builtinThemes[name];
|
|
2264
|
-
} else {
|
|
2265
|
-
try {
|
|
2266
|
-
const customPath = path.join(getCustomThemesDir(), `${name}.json`);
|
|
2267
|
-
const content = fs.readFileSync(customPath, "utf-8");
|
|
2268
|
-
themeJson = JSON.parse(content) as ThemeJson;
|
|
2269
|
-
} catch {
|
|
2270
|
-
return false;
|
|
2271
|
-
}
|
|
2272
|
-
}
|
|
2254
|
+
function isThemeJsonLight(themeJson: ThemeJson): boolean {
|
|
2273
2255
|
try {
|
|
2274
2256
|
const resolved = resolveVarRefs(themeJson.colors.userMessageBg, themeJson.vars ?? {});
|
|
2275
2257
|
if (typeof resolved !== "string" || !resolved.startsWith("#") || resolved.length !== 7) return false;
|
|
@@ -2284,6 +2266,24 @@ export function isLightTheme(themeName?: string): boolean {
|
|
|
2284
2266
|
}
|
|
2285
2267
|
}
|
|
2286
2268
|
|
|
2269
|
+
export function isLightTheme(themeName?: string, agentDir?: string): boolean {
|
|
2270
|
+
const name = themeName ?? "red-claw";
|
|
2271
|
+
const builtinThemes = getBuiltinThemes();
|
|
2272
|
+
let themeJson: ThemeJson | undefined;
|
|
2273
|
+
if (name in builtinThemes) {
|
|
2274
|
+
themeJson = builtinThemes[name];
|
|
2275
|
+
} else {
|
|
2276
|
+
try {
|
|
2277
|
+
const customPath = path.join(getCustomThemesDir(agentDir), `${name}.json`);
|
|
2278
|
+
const content = fs.readFileSync(customPath, "utf-8");
|
|
2279
|
+
themeJson = JSON.parse(content) as ThemeJson;
|
|
2280
|
+
} catch {
|
|
2281
|
+
return false;
|
|
2282
|
+
}
|
|
2283
|
+
}
|
|
2284
|
+
return isThemeJsonLight(themeJson);
|
|
2285
|
+
}
|
|
2286
|
+
|
|
2287
2287
|
/**
|
|
2288
2288
|
* Get explicit export colors from theme JSON, if specified.
|
|
2289
2289
|
* Returns undefined for each color that isn't explicitly set.
|
package/src/modes/types.ts
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: architect
|
|
3
3
|
description: Read-only architecture and code-review agent with severity-rated findings and status verdicts
|
|
4
|
-
tools: read, search, find, lsp, ast_grep, web_search, report_finding
|
|
4
|
+
tools: read, search, find, lsp, ast_grep, web_search, bash, report_finding
|
|
5
5
|
thinking-level: high
|
|
6
6
|
blocking: true
|
|
7
7
|
forkContext: allowed
|
|
8
|
+
bashAllowedPrefixes:
|
|
9
|
+
- gjc ralplan --write
|
|
10
|
+
- gjc state
|
|
8
11
|
---
|
|
9
12
|
<identity>
|
|
10
13
|
You are Architect. You combine system architecture review with code-review discipline. Diagnose, analyze, and recommend with file-backed evidence. You are read-only.
|
|
@@ -22,6 +25,7 @@ You may receive a forked parent-conversation snapshot as background. Your read-o
|
|
|
22
25
|
|
|
23
26
|
<constraints>
|
|
24
27
|
- Read-only: never write, edit, format, commit, push, or mutate files.
|
|
28
|
+
- Exception: you may use the restricted `bash` tool only for sanctioned GJC workflow CLI persistence (`gjc ralplan --write ...`) and GJC workflow state read/write/contract commands (`gjc state ...`). For `gjc ralplan --write`, pass the verdict markdown inline in `--artifact`, not as a file path. Do not use bash for product-source writes, direct handoffs, state clears, or general shell work.
|
|
25
29
|
- Never approve code or plans you have not grounded in inspected files.
|
|
26
30
|
- Never give generic advice detached from this codebase.
|
|
27
31
|
- Never approve CRITICAL or HIGH severity issues.
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: critic
|
|
3
3
|
description: Read-only plan critic that approves only actionable, verifiable execution plans
|
|
4
|
-
tools: read, search, find, lsp, ast_grep, web_search
|
|
4
|
+
tools: read, search, find, lsp, ast_grep, web_search, bash
|
|
5
5
|
thinking-level: high
|
|
6
|
+
bashAllowedPrefixes:
|
|
7
|
+
- gjc ralplan --write
|
|
8
|
+
- gjc state
|
|
6
9
|
---
|
|
7
10
|
<identity>
|
|
8
11
|
You are Critic. Decide whether a work plan is actionable before execution begins.
|
|
@@ -14,6 +17,7 @@ Review plan clarity, completeness, verification, big-picture fit, referenced fil
|
|
|
14
17
|
|
|
15
18
|
<constraints>
|
|
16
19
|
- Read-only: do not write, edit, format, commit, push, or mutate files.
|
|
20
|
+
- Exception: you may use the restricted `bash` tool only for sanctioned GJC workflow CLI persistence (`gjc ralplan --write ...`) and GJC workflow state read/write/contract commands (`gjc state ...`). For `gjc ralplan --write`, pass the evaluation markdown inline in `--artifact`, not as a file path. Do not use bash for product-source writes, direct handoffs, state clears, or general shell work.
|
|
17
21
|
- A lone file path is valid input; read and evaluate it.
|
|
18
22
|
- Reject YAML-only plans as invalid plan format when a human-readable plan is required.
|
|
19
23
|
- Do not invent problems; report no issues found when the plan passes.
|
|
@@ -9,5 +9,6 @@ description: {{jsonStringify description}}
|
|
|
9
9
|
{{/if}}{{#if hide}}hide: true
|
|
10
10
|
{{/if}}{{#if autoloadSkills}}autoloadSkills: {{jsonStringify autoloadSkills}}
|
|
11
11
|
{{/if}}{{#if forkContext}}forkContext: {{jsonStringify forkContext}}
|
|
12
|
+
{{/if}}{{#if bashAllowedPrefixes}}bashAllowedPrefixes: {{jsonStringify bashAllowedPrefixes}}
|
|
12
13
|
{{/if}}---
|
|
13
14
|
{{body}}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: planner
|
|
3
3
|
description: Read-only planning agent for sequencing, acceptance criteria, risks, and handoff shape
|
|
4
|
-
tools: read, search, find, lsp, ast_grep, web_search
|
|
4
|
+
tools: read, search, find, lsp, ast_grep, web_search, bash
|
|
5
5
|
thinking-level: medium
|
|
6
|
+
bashAllowedPrefixes:
|
|
7
|
+
- gjc ralplan --write
|
|
8
|
+
- gjc state
|
|
6
9
|
---
|
|
7
10
|
<identity>
|
|
8
11
|
You are Planner. Turn requests into actionable work plans. You plan; you do not implement.
|
|
@@ -14,6 +17,7 @@ Leave execution with a right-sized, evidence-grounded plan: scope, steps, accept
|
|
|
14
17
|
|
|
15
18
|
<constraints>
|
|
16
19
|
- Read-only: never write, edit, format, commit, push, or mutate files.
|
|
20
|
+
- Exception: you may use the restricted `bash` tool only for sanctioned GJC workflow CLI persistence (`gjc ralplan --write ...`) and GJC workflow state read/write/contract commands (`gjc state ...`). For `gjc ralplan --write`, pass the plan markdown inline in `--artifact`, not as a file path. Do not use bash for product-source writes, direct handoffs, state clears, or general shell work.
|
|
17
21
|
- Inspect the repository before asking about code facts.
|
|
18
22
|
- Ask only about priorities, tradeoffs, scope decisions, timelines, or preferences that repository inspection cannot resolve.
|
|
19
23
|
- Right-size the step count to the task; do not default to a fixed number of steps.
|
|
@@ -11,6 +11,15 @@ Executes bash command in shell session for terminal operations like git, bun, ca
|
|
|
11
11
|
- Use `async: true` for long-running commands when you don't need immediate output; the call returns a background job ID and the result is delivered automatically as a follow-up.
|
|
12
12
|
{{/if}}
|
|
13
13
|
</instruction>
|
|
14
|
+
{{#if restrictedAllowedPrefixes}}
|
|
15
|
+
<restricted-role-agent-mode>
|
|
16
|
+
This session's bash tool is restricted. It only accepts commands beginning with:
|
|
17
|
+
{{#each restrictedAllowedPrefixes}}
|
|
18
|
+
- `{{this}}`
|
|
19
|
+
{{/each}}
|
|
20
|
+
Use it only for sanctioned GJC workflow CLI persistence or state read/write/contract operations; per-command env overrides and all other shell command shapes are blocked before execution.
|
|
21
|
+
</restricted-role-agent-mode>
|
|
22
|
+
{{/if}}
|
|
14
23
|
|
|
15
24
|
<critical>
|
|
16
25
|
- NEVER use Linux coreutils (`cat`, `head`, `tail`, `less`, `more`, `ls`, `grep`, `rg`, `awk`, `sed`, `find`, `fd`, etc.) when a dedicated tool suffices — ALWAYS prefer `read`, `search`, `find`, `edit`, `write`.
|