@gajae-code/coding-agent 0.2.0 → 0.2.2

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 (114) hide show
  1. package/CHANGELOG.md +38 -1
  2. package/dist/types/cli/skills-cli.d.ts +9 -0
  3. package/dist/types/commands/contribution-prep.d.ts +18 -0
  4. package/dist/types/commands/session.d.ts +24 -0
  5. package/dist/types/commands/skills.d.ts +26 -0
  6. package/dist/types/config/model-registry.d.ts +33 -4
  7. package/dist/types/config/models-config-schema.d.ts +52 -5
  8. package/dist/types/config/settings-schema.d.ts +1 -24
  9. package/dist/types/gjc-runtime/deep-interview-runtime.d.ts +15 -0
  10. package/dist/types/gjc-runtime/goal-mode-request.d.ts +1 -1
  11. package/dist/types/gjc-runtime/launch-tmux.d.ts +12 -11
  12. package/dist/types/gjc-runtime/ralplan-runtime.d.ts +25 -0
  13. package/dist/types/gjc-runtime/state-runtime.d.ts +13 -0
  14. package/dist/types/gjc-runtime/team-runtime.d.ts +37 -5
  15. package/dist/types/gjc-runtime/tmux-common.d.ts +41 -0
  16. package/dist/types/gjc-runtime/tmux-sessions.d.ts +17 -0
  17. package/dist/types/goals/runtime.d.ts +3 -9
  18. package/dist/types/goals/state.d.ts +3 -6
  19. package/dist/types/goals/tools/goal-tool.d.ts +1 -69
  20. package/dist/types/modes/components/model-selector.d.ts +21 -1
  21. package/dist/types/modes/components/status-line/types.d.ts +0 -3
  22. package/dist/types/modes/components/status-line.d.ts +0 -3
  23. package/dist/types/modes/controllers/command-controller.d.ts +1 -0
  24. package/dist/types/modes/interactive-mode.d.ts +1 -12
  25. package/dist/types/modes/theme/defaults/index.d.ts +0 -2
  26. package/dist/types/modes/theme/theme.d.ts +1 -2
  27. package/dist/types/modes/types.d.ts +1 -7
  28. package/dist/types/session/agent-session.d.ts +2 -0
  29. package/dist/types/session/contribution-prep.d.ts +47 -0
  30. package/dist/types/skill-state/active-state.d.ts +4 -0
  31. package/dist/types/skill-state/deep-interview-mutation-guard.d.ts +6 -1
  32. package/dist/types/skill-state/workflow-hud.d.ts +9 -4
  33. package/dist/types/skill-state/workflow-state-contract.d.ts +34 -0
  34. package/dist/types/slash-commands/builtin-registry.d.ts +1 -0
  35. package/package.json +7 -7
  36. package/src/cli/args.ts +17 -2
  37. package/src/cli/skills-cli.ts +88 -0
  38. package/src/cli.ts +7 -1
  39. package/src/commands/contribution-prep.ts +41 -0
  40. package/src/commands/deep-interview.ts +6 -22
  41. package/src/commands/launch.ts +10 -1
  42. package/src/commands/ralplan.ts +10 -22
  43. package/src/commands/session.ts +150 -0
  44. package/src/commands/skills.ts +48 -0
  45. package/src/commands/state.ts +14 -4
  46. package/src/commands/team.ts +23 -3
  47. package/src/commit/agentic/index.ts +1 -0
  48. package/src/commit/pipeline.ts +1 -0
  49. package/src/config/model-registry.ts +269 -10
  50. package/src/config/models-config-schema.ts +124 -88
  51. package/src/config/settings-schema.ts +1 -25
  52. package/src/config.ts +1 -1
  53. package/src/defaults/gjc/skills/deep-interview/SKILL.md +14 -13
  54. package/src/defaults/gjc/skills/ralplan/SKILL.md +14 -2
  55. package/src/defaults/gjc/skills/team/SKILL.md +29 -7
  56. package/src/defaults/gjc/skills/ultragoal/SKILL.md +23 -25
  57. package/src/eval/py/prelude.py +1 -1
  58. package/src/gjc-runtime/deep-interview-runtime.ts +279 -0
  59. package/src/gjc-runtime/goal-mode-request.ts +2 -19
  60. package/src/gjc-runtime/launch-tmux.ts +83 -43
  61. package/src/gjc-runtime/ralplan-runtime.ts +460 -0
  62. package/src/gjc-runtime/state-runtime.ts +562 -0
  63. package/src/gjc-runtime/team-runtime.ts +708 -52
  64. package/src/gjc-runtime/tmux-common.ts +119 -0
  65. package/src/gjc-runtime/tmux-sessions.ts +165 -0
  66. package/src/gjc-runtime/ultragoal-guard.ts +6 -3
  67. package/src/gjc-runtime/ultragoal-runtime.ts +5 -4
  68. package/src/goals/runtime.ts +38 -144
  69. package/src/goals/state.ts +36 -7
  70. package/src/goals/tools/goal-tool.ts +15 -172
  71. package/src/hooks/skill-state.ts +31 -12
  72. package/src/internal-urls/docs-index.generated.ts +4 -3
  73. package/src/main.ts +10 -1
  74. package/src/modes/components/model-selector.ts +109 -28
  75. package/src/modes/components/skill-hud/render.ts +4 -0
  76. package/src/modes/components/status-line/segments.ts +5 -16
  77. package/src/modes/components/status-line/types.ts +0 -3
  78. package/src/modes/components/status-line.ts +0 -6
  79. package/src/modes/controllers/command-controller.ts +25 -1
  80. package/src/modes/controllers/input-controller.ts +0 -15
  81. package/src/modes/controllers/selector-controller.ts +42 -2
  82. package/src/modes/interactive-mode.ts +18 -219
  83. package/src/modes/theme/defaults/dark-poimandres.json +0 -1
  84. package/src/modes/theme/defaults/light-poimandres.json +0 -1
  85. package/src/modes/theme/theme.ts +0 -6
  86. package/src/modes/types.ts +1 -7
  87. package/src/prompts/goals/goal-continuation.md +1 -4
  88. package/src/prompts/goals/goal-mode-active.md +3 -5
  89. package/src/prompts/system/system-prompt.md +5 -7
  90. package/src/prompts/tools/goal.md +4 -4
  91. package/src/sdk.ts +2 -1
  92. package/src/session/agent-session.ts +18 -0
  93. package/src/session/contribution-prep.ts +320 -0
  94. package/src/setup/provider-onboarding.ts +2 -0
  95. package/src/skill-state/active-state.ts +38 -0
  96. package/src/skill-state/deep-interview-mutation-guard.ts +88 -24
  97. package/src/skill-state/workflow-hud.ts +23 -5
  98. package/src/skill-state/workflow-state-contract.ts +121 -0
  99. package/src/slash-commands/acp-builtins.ts +11 -2
  100. package/src/slash-commands/builtin-registry.ts +40 -13
  101. package/src/task/commands.ts +1 -5
  102. package/src/tools/gh.ts +212 -2
  103. package/src/tools/index.ts +2 -5
  104. package/dist/types/commands/gjc-runtime-bridge.d.ts +0 -30
  105. package/dist/types/commands/question.d.ts +0 -7
  106. package/dist/types/modes/loop-limit.d.ts +0 -22
  107. package/src/commands/gjc-runtime-bridge.ts +0 -227
  108. package/src/commands/question.ts +0 -12
  109. package/src/modes/loop-limit.ts +0 -140
  110. package/src/prompts/commands/orchestrate.md +0 -49
  111. package/src/prompts/goals/goal-budget-limit.md +0 -16
  112. package/src/prompts/tools/create-goal.md +0 -3
  113. package/src/prompts/tools/get-goal.md +0 -3
  114. package/src/prompts/tools/update-goal.md +0 -3
package/src/cli/args.ts CHANGED
@@ -55,6 +55,15 @@ export interface Args {
55
55
  unknownFlags: Map<string, boolean | string>;
56
56
  }
57
57
 
58
+ function isStartupSlashCommandArg(arg: string | undefined): boolean {
59
+ return (
60
+ arg === "/provider" ||
61
+ arg?.startsWith("/provider:") === true ||
62
+ arg === "/provicer" ||
63
+ arg?.startsWith("/provicer:") === true
64
+ );
65
+ }
66
+
58
67
  export function parseArgs(args: string[]): Args {
59
68
  const result: Args = {
60
69
  messages: [],
@@ -65,6 +74,11 @@ export function parseArgs(args: string[]): Args {
65
74
  for (let i = 0; i < args.length; i++) {
66
75
  let arg = args[i];
67
76
 
77
+ if (isStartupSlashCommandArg(arg)) {
78
+ result.messages.push(args.slice(i).join(" "));
79
+ break;
80
+ }
81
+
68
82
  // Support --flag=value syntax (e.g. --tools=ask,read)
69
83
  if (arg.startsWith("--") && arg.includes("=")) {
70
84
  const eqIdx = arg.indexOf("=");
@@ -231,9 +245,10 @@ export function getExtraHelpText(): string {
231
245
  GJC_SLOW_MODEL - Override slow/reasoning model (see --slow)
232
246
  GJC_PLAN_MODEL - Override planning model (see --plan)
233
247
  GJC_NO_PTY - Disable PTY-based interactive bash execution
234
- --tmux - Launch interactive startup inside tmux
248
+ --tmux - Launch interactive startup inside a new tmux session
249
+ gjc session - List, inspect, create, remove, or attach tagged GJC-managed tmux sessions
235
250
  GJC_LAUNCH_POLICY - Launch policy for --tmux startup: tmux or direct
236
- GJC_TMUX_SESSION - tmux session name for default interactive startup (default: gajae_code)
251
+ GJC_TMUX_SESSION - Explicit tmux session name override for --tmux startup
237
252
 
238
253
  For complete environment variable reference, see:
239
254
  ${chalk.dim("docs/environment-variables.md")}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Handles `gjc skills` for inspecting bundled workflow skill definitions.
3
+ */
4
+ import {
5
+ DEFAULT_GJC_DEFINITION_NAMES,
6
+ type EmbeddedDefaultGjcSkill,
7
+ getEmbeddedDefaultGjcSkills,
8
+ } from "../defaults/gjc-defaults";
9
+
10
+ export type SkillsAction = "list" | "read";
11
+
12
+ export interface SkillsCommandArgs {
13
+ action: SkillsAction;
14
+ name?: string;
15
+ flags?: {
16
+ json?: boolean;
17
+ };
18
+ }
19
+
20
+ interface SkillsListEntry {
21
+ name: string;
22
+ description: string;
23
+ path: string;
24
+ source: string;
25
+ }
26
+
27
+ interface SkillsReadEntry extends SkillsListEntry {
28
+ content: string;
29
+ }
30
+
31
+ function getEmbeddedSkill(name: string): EmbeddedDefaultGjcSkill | undefined {
32
+ return getEmbeddedDefaultGjcSkills().find(skill => skill.name === name);
33
+ }
34
+
35
+ function listEmbeddedSkills(): SkillsListEntry[] {
36
+ return getEmbeddedDefaultGjcSkills().map(skill => ({
37
+ name: skill.name,
38
+ description: skill.description,
39
+ path: skill.filePath,
40
+ source: skill.source,
41
+ }));
42
+ }
43
+
44
+ function writeJson(value: unknown): void {
45
+ process.stdout.write(`${JSON.stringify(value, null, 2)}\n`);
46
+ }
47
+
48
+ export async function runSkillsCommand(cmd: SkillsCommandArgs): Promise<void> {
49
+ if (cmd.action === "list") {
50
+ const skills = listEmbeddedSkills();
51
+ if (cmd.flags?.json) {
52
+ writeJson({ skills });
53
+ return;
54
+ }
55
+ for (const skill of skills) {
56
+ process.stdout.write(`${skill.name}\t${skill.description}\t${skill.path}\n`);
57
+ }
58
+ return;
59
+ }
60
+
61
+ const name = cmd.name?.trim();
62
+ if (!name) {
63
+ process.stderr.write(`error: skill name is required for read (${DEFAULT_GJC_DEFINITION_NAMES.join(", ")})\n`);
64
+ process.exitCode = 1;
65
+ return;
66
+ }
67
+
68
+ const skill = getEmbeddedSkill(name);
69
+ if (!skill) {
70
+ process.stderr.write(`error: unknown embedded skill "${name}" (${DEFAULT_GJC_DEFINITION_NAMES.join(", ")})\n`);
71
+ process.exitCode = 1;
72
+ return;
73
+ }
74
+
75
+ const entry: SkillsReadEntry = {
76
+ name: skill.name,
77
+ description: skill.description,
78
+ path: skill.filePath,
79
+ source: skill.source,
80
+ content: skill.content,
81
+ };
82
+ if (cmd.flags?.json) {
83
+ writeJson(entry);
84
+ return;
85
+ }
86
+ process.stdout.write(skill.content);
87
+ if (!skill.content.endsWith("\n")) process.stdout.write("\n");
88
+ }
package/src/cli.ts CHANGED
@@ -31,12 +31,18 @@ process.title = APP_NAME;
31
31
 
32
32
  const commands: CommandEntry[] = [
33
33
  { name: "codex-native-hook", load: () => import("./commands/codex-native-hook").then(m => m.default) },
34
- { name: "question", load: () => import("./commands/question").then(m => m.default) },
35
34
  { name: "state", load: () => import("./commands/state").then(m => m.default) },
36
35
  { name: "setup", load: () => import("./commands/setup").then(m => m.default) },
36
+ { name: "skills", load: () => import("./commands/skills").then(m => m.default) },
37
+ { name: "session", load: () => import("./commands/session").then(m => m.default) },
37
38
  { name: "team", load: () => import("./commands/team").then(m => m.default) },
38
39
  { name: "ultragoal", load: () => import("./commands/ultragoal").then(m => m.default) },
39
40
  { name: "ralplan", load: () => import("./commands/ralplan").then(m => m.default) },
41
+ {
42
+ name: "contribute-pr",
43
+ aliases: ["contribution-prep"],
44
+ load: () => import("./commands/contribution-prep").then(m => m.default),
45
+ },
40
46
  { name: "deep-interview", load: () => import("./commands/deep-interview").then(m => m.default) },
41
47
  { name: "launch", load: () => import("./commands/launch").then(m => m.default) },
42
48
  ];
@@ -0,0 +1,41 @@
1
+ import { Command, Flags } from "@gajae-code/utils/cli";
2
+ import { prepareContributionPrep } from "../session/contribution-prep";
3
+
4
+ function writeText(lines: string[]): void {
5
+ process.stdout.write(`${lines.join("\n")}\n`);
6
+ }
7
+
8
+ export default class ContributionPrep extends Command {
9
+ static description = "Dump redacted context and prepare a fresh contribute-pr worker prompt";
10
+ static strict = false;
11
+
12
+ static flags = {
13
+ "no-spawn": Flags.boolean({ description: "Only write artifacts; do not spawn a fresh GJC worker" }),
14
+ "source-session-id": Flags.string({ description: "Source session id to record in the manifest" }),
15
+ "artifact-root": Flags.string({ description: "Directory where contribute-pr artifacts are written" }),
16
+ };
17
+
18
+ static examples = ["gjc contribute-pr", "gjc contribute-pr --no-spawn"];
19
+
20
+ async run(): Promise<void> {
21
+ const { flags } = await this.parse(ContributionPrep);
22
+ const cwd = process.cwd();
23
+ const result = await prepareContributionPrep(
24
+ {
25
+ sessionId: flags["source-session-id"] ?? "cli",
26
+ cwd,
27
+ messages: [],
28
+ },
29
+ {
30
+ spawnWorker: !flags["no-spawn"],
31
+ artifactRoot: flags["artifact-root"],
32
+ },
33
+ );
34
+ writeText([
35
+ "Contribution prep artifacts written.",
36
+ `Manifest: ${result.manifestPath}`,
37
+ `Worker prompt: ${result.workerPromptPath}`,
38
+ `Spawned worker: ${result.spawned ? "yes" : "no"}`,
39
+ ]);
40
+ }
41
+ }
@@ -1,31 +1,15 @@
1
1
  import { Command } from "@gajae-code/utils/cli";
2
- import { syncSkillActiveState } from "../skill-state/active-state";
3
- import { runGjcRuntimeBridgeWithHudSidecar } from "./gjc-runtime-bridge";
2
+ import { runNativeDeepInterviewCommand } from "../gjc-runtime/deep-interview-runtime";
4
3
 
5
4
  export default class DeepInterview extends Command {
6
- static description = "Run private GJC deep-interview workflow commands";
5
+ static description = "Run native GJC deep-interview workflow";
7
6
  static strict = false;
8
- static examples = ["$ gjc deep-interview --help"];
7
+ static examples = ['$ gjc deep-interview --standard "<idea>"'];
9
8
 
10
9
  async run(): Promise<void> {
11
- const cwd = process.cwd();
12
- const result = await runGjcRuntimeBridgeWithHudSidecar("deep-interview", this.argv, {
13
- cwd,
14
- sidecarSkill: "deep-interview",
15
- onHudPayload: payload =>
16
- syncSkillActiveState({
17
- cwd,
18
- skill: "deep-interview",
19
- active: payload.active ?? true,
20
- phase: payload.phase,
21
- sessionId: payload.session_id,
22
- threadId: payload.thread_id,
23
- turnId: payload.turn_id,
24
- hud: payload.hud,
25
- source: "gjc-runtime-bridge",
26
- }),
27
- });
28
- if (result.error) process.stderr.write(`${result.error}\n`);
10
+ const result = await runNativeDeepInterviewCommand(this.argv, process.cwd());
11
+ if (result.stdout) process.stdout.write(result.stdout);
12
+ if (result.stderr) process.stderr.write(result.stderr);
29
13
  process.exitCode = result.status;
30
14
  }
31
15
  }
@@ -155,7 +155,16 @@ export default class Index extends Command {
155
155
  setProjectDir(launch.cwd);
156
156
  }
157
157
  const launchParsed = parseArgs(launch.args);
158
- if (launchDefaultTmuxIfNeeded({ parsed: launchParsed, rawArgs: launch.args, cwd: launch.cwd })) return;
158
+ if (
159
+ launchDefaultTmuxIfNeeded({
160
+ parsed: launchParsed,
161
+ rawArgs: launch.args,
162
+ cwd: launch.cwd,
163
+ worktreeBranch: launch.worktree.enabled && !launch.worktree.detached ? launch.worktree.branchName : null,
164
+ project: launch.worktree.enabled ? launch.worktree.repoRoot : launch.cwd,
165
+ })
166
+ )
167
+ return;
159
168
  await runRootCommand(launchParsed, launch.args);
160
169
  }
161
170
  }
@@ -1,31 +1,19 @@
1
1
  import { Command } from "@gajae-code/utils/cli";
2
- import { syncSkillActiveState } from "../skill-state/active-state";
3
- import { runGjcRuntimeBridgeWithHudSidecar } from "./gjc-runtime-bridge";
2
+ import { runNativeRalplanCommand } from "../gjc-runtime/ralplan-runtime";
4
3
 
5
4
  export default class Ralplan extends Command {
6
- static description = "Run private GJC RALPLAN workflow commands";
5
+ static description = "Run native GJC RALPLAN consensus planning workflow";
7
6
  static strict = false;
8
- static examples = ["$ gjc ralplan --help"];
7
+ static examples = [
8
+ '$ gjc ralplan "<task description>"',
9
+ '$ gjc ralplan --interactive --deliberate "<task description>"',
10
+ '$ gjc ralplan --write --stage planner --stage_n 1 --artifact "<markdown or path>"',
11
+ ];
9
12
 
10
13
  async run(): Promise<void> {
11
- const cwd = process.cwd();
12
- const result = await runGjcRuntimeBridgeWithHudSidecar("ralplan", this.argv, {
13
- cwd,
14
- sidecarSkill: "ralplan",
15
- onHudPayload: payload =>
16
- syncSkillActiveState({
17
- cwd,
18
- skill: "ralplan",
19
- active: payload.active ?? true,
20
- phase: payload.phase,
21
- sessionId: payload.session_id,
22
- threadId: payload.thread_id,
23
- turnId: payload.turn_id,
24
- hud: payload.hud,
25
- source: "gjc-runtime-bridge",
26
- }),
27
- });
28
- if (result.error) process.stderr.write(`${result.error}\n`);
14
+ const result = await runNativeRalplanCommand(this.argv, process.cwd());
15
+ if (result.stdout) process.stdout.write(result.stdout);
16
+ if (result.stderr) process.stderr.write(result.stderr);
29
17
  process.exitCode = result.status;
30
18
  }
31
19
  }
@@ -0,0 +1,150 @@
1
+ import { Args, Command, Flags } from "@gajae-code/utils/cli";
2
+ import {
3
+ attachGjcTmuxSession,
4
+ createGjcTmuxSession,
5
+ listGjcTmuxSessions,
6
+ removeGjcTmuxSession,
7
+ statusGjcTmuxSession,
8
+ } from "../gjc-runtime/tmux-sessions";
9
+
10
+ function writeJson(value: unknown): void {
11
+ process.stdout.write(`${JSON.stringify(value, null, 2)}\n`);
12
+ }
13
+
14
+ function writeText(lines: string[]): void {
15
+ process.stdout.write(`${lines.join("\n")}\n`);
16
+ }
17
+
18
+ function writeJsonFailure(error: unknown): void {
19
+ const message = error instanceof Error ? error.message : String(error);
20
+ const [reason = "session_error"] = message.split(":");
21
+ writeJson({ ok: false, reason });
22
+ }
23
+
24
+ interface SessionJsonDto {
25
+ name: string;
26
+ attached: boolean;
27
+ windows: number;
28
+ panes: number;
29
+ bindings: string;
30
+ createdAt: string;
31
+ }
32
+
33
+ function sessionJson(session: SessionJsonDto): SessionJsonDto {
34
+ return {
35
+ name: session.name,
36
+ attached: session.attached,
37
+ windows: session.windows,
38
+ panes: session.panes,
39
+ bindings: session.bindings,
40
+ createdAt: session.createdAt,
41
+ };
42
+ }
43
+
44
+ export default class Session extends Command {
45
+ static description = "List, inspect, attach, and remove tagged GJC-managed tmux sessions";
46
+ static strict = false;
47
+
48
+ static args = {
49
+ action: Args.string({
50
+ description: "list (default), status, create, attach, or remove",
51
+ required: false,
52
+ }),
53
+ session: Args.string({
54
+ description: "Session name for status, attach, or remove",
55
+ required: false,
56
+ }),
57
+ };
58
+
59
+ static flags = {
60
+ json: Flags.boolean({ char: "j", description: "Emit machine-readable JSON", default: false }),
61
+ };
62
+
63
+ static examples = [
64
+ "gjc session list",
65
+ "gjc session create",
66
+ "gjc session status <session>",
67
+ "gjc session attach <session>",
68
+ "gjc session remove <session>",
69
+ ];
70
+
71
+ async run(): Promise<void> {
72
+ const { args, flags } = await this.parse(Session);
73
+ const action = args.action ?? "list";
74
+ const sessionName = args.session;
75
+ const json = flags.json ?? false;
76
+ try {
77
+ if (action === "list") {
78
+ const sessions = listGjcTmuxSessions();
79
+ if (json) {
80
+ writeJson({ ok: true, sessions: sessions.map(sessionJson) });
81
+ return;
82
+ }
83
+ writeText(
84
+ sessions.map(session =>
85
+ [
86
+ session.name,
87
+ `windows=${session.windows}`,
88
+ `attached=${session.attached}`,
89
+ `createdAt=${session.createdAt}`,
90
+ `panes=${session.panes}`,
91
+ `bindings=${session.bindings || "none"}`,
92
+ ].join("\t"),
93
+ ),
94
+ );
95
+ return;
96
+ }
97
+
98
+ if (action === "create") {
99
+ const session = createGjcTmuxSession();
100
+ if (json) {
101
+ writeJson({ ok: true, session: sessionJson(session) });
102
+ return;
103
+ }
104
+ writeText([`created: ${session.name}`]);
105
+ return;
106
+ }
107
+
108
+ if (!sessionName) throw new Error("missing_session_name");
109
+
110
+ if (action === "status") {
111
+ const session = statusGjcTmuxSession(sessionName);
112
+ if (json) {
113
+ writeJson({ ok: true, session: sessionJson(session) });
114
+ return;
115
+ }
116
+ writeText([
117
+ `session: ${session.name}`,
118
+ `windows: ${session.windows}`,
119
+ `attached: ${session.attached}`,
120
+ `createdAt: ${session.createdAt}`,
121
+ `panes: ${session.panes}`,
122
+ `bindings: ${session.bindings || "none"}`,
123
+ ]);
124
+ return;
125
+ }
126
+
127
+ if (action === "remove" || action === "rm" || action === "delete") {
128
+ const removed = removeGjcTmuxSession(sessionName);
129
+ if (json) {
130
+ writeJson({ ok: true, session: sessionJson(removed) });
131
+ return;
132
+ }
133
+ writeText([`removed: ${removed.name}`]);
134
+ return;
135
+ }
136
+
137
+ if (action === "attach") {
138
+ attachGjcTmuxSession(sessionName);
139
+ return;
140
+ }
141
+ throw new Error(`unknown_session_action:${action}`);
142
+ } catch (error) {
143
+ if (json) {
144
+ writeJsonFailure(error);
145
+ return;
146
+ }
147
+ throw error;
148
+ }
149
+ }
150
+ }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Inspect bundled workflow skills.
3
+ */
4
+ import { Args, Command, Flags, renderCommandHelp } from "@gajae-code/utils/cli";
5
+ import { runSkillsCommand, type SkillsAction, type SkillsCommandArgs } from "../cli/skills-cli";
6
+
7
+ const ACTIONS: SkillsAction[] = ["list", "read"];
8
+
9
+ export default class Skills extends Command {
10
+ static description = "Inspect bundled GJC workflow skills";
11
+
12
+ static args = {
13
+ action: Args.string({
14
+ description: "Skills action",
15
+ required: false,
16
+ options: ACTIONS,
17
+ }),
18
+ name: Args.string({
19
+ description: "Bundled skill name to read",
20
+ required: false,
21
+ }),
22
+ };
23
+
24
+ static flags = {
25
+ json: Flags.boolean({ description: "Output JSON" }),
26
+ };
27
+
28
+ static examples = [
29
+ "# List bundled workflow skills\n gjc skills list",
30
+ "# Read an embedded workflow skill without requiring .gjc files\n gjc skills read ultragoal",
31
+ "# Machine-readable embedded skill content\n gjc skills read ralplan --json",
32
+ ];
33
+
34
+ async run(): Promise<void> {
35
+ const { args, flags } = await this.parse(Skills);
36
+ if (!args.action) {
37
+ renderCommandHelp("gjc", "skills", Skills);
38
+ return;
39
+ }
40
+
41
+ const cmd: SkillsCommandArgs = {
42
+ action: args.action as SkillsAction,
43
+ name: args.name,
44
+ flags: { json: flags.json },
45
+ };
46
+ await runSkillsCommand(cmd);
47
+ }
48
+ }
@@ -1,12 +1,22 @@
1
1
  import { Command } from "@gajae-code/utils/cli";
2
- import { runBridgedRuntimeEndpoint } from "./gjc-runtime-bridge";
2
+ import { runNativeStateCommand } from "../gjc-runtime/state-runtime";
3
3
 
4
4
  export default class State extends Command {
5
- static description = "Read or update private GJC workflow state";
5
+ static description = "Read or update GJC workflow state receipts under .gjc/state";
6
6
  static strict = false;
7
- static examples = ['$ gjc state read --input \'{"mode":"team"}\' --json'];
7
+ static examples = [
8
+ '$ gjc state read --input \'{"mode":"deep-interview"}\' --json',
9
+ '$ gjc state write --input \'{"state":{"interview_id":"abc"}}\' --mode deep-interview --json',
10
+ "$ gjc state clear --mode deep-interview",
11
+ "$ gjc state deep-interview read --json",
12
+ '$ gjc state ralplan write --input \'{"phase":"approval","active":true}\' --json',
13
+ "$ gjc state team contract",
14
+ ];
8
15
 
9
16
  async run(): Promise<void> {
10
- await runBridgedRuntimeEndpoint("state", this.argv);
17
+ const result = await runNativeStateCommand(this.argv);
18
+ if (result.stdout) process.stdout.write(result.stdout);
19
+ if (result.stderr) process.stderr.write(result.stderr);
20
+ process.exitCode = result.status;
11
21
  }
12
22
  }
@@ -42,6 +42,18 @@ function formatTaskCounts(counts: Record<string, number>): string {
42
42
  .join(" ");
43
43
  }
44
44
 
45
+ function formatNotificationSummary(snapshot: GjcTeamSnapshot): string {
46
+ const summary = snapshot.notification_summary;
47
+ return `notifications: total=${summary.total} replay_eligible=${summary.replay_eligible} pending=${summary.by_state.pending} queued=${summary.by_state.queued} deferred=${summary.by_state.deferred} failed=${summary.by_state.failed}`;
48
+ }
49
+
50
+ function formatAwaitingIntegrationNextStep(snapshot: GjcTeamSnapshot): string[] {
51
+ if (snapshot.phase !== "awaiting_integration") return [];
52
+ return [
53
+ "next: worker tasks are completed, but integration still needs leader attention before the team is complete",
54
+ ];
55
+ }
56
+
45
57
  function formatIntegrationSummary(snapshot: {
46
58
  integration_by_worker?: Record<string, { status?: string; conflict_files?: string[] }>;
47
59
  }): string[] {
@@ -64,7 +76,7 @@ function parseInputFlag(argv: string[]): Record<string, unknown> {
64
76
  }
65
77
 
66
78
  export default class Team extends Command {
67
- static description = "Run native GJC tmux team orchestration commands";
79
+ static description = "Run native GJC tmux team orchestration; --dry-run writes ephemeral .gjc/state/team state only";
68
80
  static strict = false;
69
81
 
70
82
  static args = {
@@ -76,13 +88,18 @@ export default class Team extends Command {
76
88
 
77
89
  static flags = {
78
90
  json: Flags.boolean({ char: "j", description: "Emit machine-readable JSON", default: false }),
79
- "dry-run": Flags.boolean({ description: "Create team state without starting tmux panes", default: false }),
91
+ "dry-run": Flags.boolean({
92
+ description:
93
+ "Create ephemeral .gjc/state/team state without starting tmux panes; do not commit generated state",
94
+ default: false,
95
+ }),
80
96
  };
81
97
 
82
98
  static examples = [
83
99
  'gjc team 3:executor "Implement the approved plan"',
84
100
  "gjc team status <team-name> --json",
85
101
  'gjc team api claim-task --input \'{"team_name":"demo","worker_id":"worker-1"}\' --json',
102
+ 'gjc team 2:executor --dry-run --json "Preview state only"',
86
103
  "gjc team shutdown <team-name>",
87
104
  ];
88
105
 
@@ -118,6 +135,8 @@ export default class Team extends Command {
118
135
  `state: ${snapshot.state_dir}`,
119
136
  `tasks: ${snapshot.task_total} (${formatTaskCounts(snapshot.task_counts)})`,
120
137
  `workers: ${snapshot.workers.map(worker => `${worker.id}:${worker.status}`).join(" ")}`,
138
+ formatNotificationSummary(snapshot),
139
+ ...formatAwaitingIntegrationNextStep(snapshot),
121
140
  ...formatIntegrationSummary(snapshot),
122
141
  ]);
123
142
  return;
@@ -141,7 +160,7 @@ export default class Team extends Command {
141
160
  if (!operation || operation === "--help" || operation === "help") {
142
161
  writeText([
143
162
  "Supported operations:",
144
- "send-message broadcast mailbox-list mailbox-mark-delivered mailbox-mark-notified",
163
+ "send-message broadcast mailbox-list mailbox-mark-delivered mailbox-mark-notified notification-list notification-read notification-replay notification-mark-pane-attempt worker-startup-ack",
145
164
  "create-task read-task list-tasks update-task claim-task transition-task-status release-task-claim",
146
165
  "read-config read-manifest read-worker-status read-worker-heartbeat update-worker-heartbeat write-worker-inbox write-worker-identity",
147
166
  "append-event read-events await-event write-shutdown-request read-shutdown-ack read-monitor-snapshot write-monitor-snapshot read-task-approval write-task-approval",
@@ -176,6 +195,7 @@ export default class Team extends Command {
176
195
  `tmux: ${snapshot.tmux_session}`,
177
196
  `state: ${snapshot.state_dir}`,
178
197
  `workers: ${snapshot.workers.length}`,
198
+ ...(dryRun ? ["dry-run: wrote ephemeral .gjc/state/team state only; do not commit generated .gjc state"] : []),
179
199
  ]);
180
200
  }
181
201
  }
@@ -31,6 +31,7 @@ export async function runAgenticCommit(args: CommitCommandArgs): Promise<void> {
31
31
  process.stdout.write("● Resolving model...\n");
32
32
  const modelRegistry = new ModelRegistry(authStorage);
33
33
  await modelRegistry.refresh();
34
+ modelRegistry.applyConfiguredModelBindings(settings);
34
35
  const stagedFilesPromise = (async () => {
35
36
  let stagedFiles = await git.diff.changedFiles(cwd, { cached: true });
36
37
  if (stagedFiles.length === 0) {
@@ -45,6 +45,7 @@ async function runLegacyCommitCommand(args: CommitCommandArgs): Promise<void> {
45
45
  const authStorage = await discoverAuthStorage();
46
46
  const modelRegistry = new ModelRegistry(authStorage);
47
47
  await modelRegistry.refresh();
48
+ modelRegistry.applyConfiguredModelBindings(settings);
48
49
 
49
50
  const {
50
51
  model: primaryModel,