@frenchtoastman/oh-my-groundcontrol 0.0.16 → 0.0.18

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/dist/cli/index.js CHANGED
@@ -15689,10 +15689,6 @@ function buildDynamicModelPlan(catalog, config2, externalSignals, options) {
15689
15689
  }
15690
15690
  };
15691
15691
  }
15692
- // src/utils/logger.ts
15693
- import * as os from "os";
15694
- import * as path from "path";
15695
- var logFile = path.join(os.tmpdir(), "oh-my-groundcontrol.log");
15696
15692
  // src/utils/env.ts
15697
15693
  function getEnv(name) {
15698
15694
  const bunValue = globalThis.Bun?.env?.[name];
@@ -15945,8 +15941,8 @@ async function getOpenCodeVersion() {
15945
15941
  return null;
15946
15942
  }
15947
15943
  function getOpenCodePath() {
15948
- const path2 = resolveOpenCodePath();
15949
- return path2 === "opencode" ? null : path2;
15944
+ const path = resolveOpenCodePath();
15945
+ return path === "opencode" ? null : path;
15950
15946
  }
15951
15947
 
15952
15948
  // src/cli/opencode-models.ts
@@ -16184,9 +16180,9 @@ async function checkOpenCodeInstalled() {
16184
16180
  return { ok: false };
16185
16181
  }
16186
16182
  const version2 = await getOpenCodeVersion();
16187
- const path2 = getOpenCodePath();
16188
- printSuccess(`OpenCode ${version2 ?? ""} detected${path2 ? ` (${DIM}${path2}${RESET})` : ""}`);
16189
- return { ok: true, version: version2 ?? undefined, path: path2 ?? undefined };
16183
+ const path = getOpenCodePath();
16184
+ printSuccess(`OpenCode ${version2 ?? ""} detected${path ? ` (${DIM}${path}${RESET})` : ""}`);
16185
+ return { ok: true, version: version2 ?? undefined, path: path ?? undefined };
16190
16186
  }
16191
16187
  function handleStepResult(result, successMsg) {
16192
16188
  if (!result.success) {
@@ -0,0 +1,10 @@
1
+ import type { Part } from '@opencode-ai/sdk';
2
+ export declare function createAnalyzeCommandHook(): {
3
+ 'command.execute.before': (input: {
4
+ command: string;
5
+ sessionID: string;
6
+ arguments: string;
7
+ }, output: {
8
+ parts: Part[];
9
+ }) => Promise<void>;
10
+ };
@@ -1,3 +1,4 @@
1
+ export { createAnalyzeCommandHook } from './analyze-command';
1
2
  export type { AutoUpdateCheckerOptions } from './auto-update-checker';
2
3
  export { createAutoUpdateCheckerHook } from './auto-update-checker';
3
4
  export { createDelegateTaskRetryHook } from './delegate-task-retry';
package/dist/index.js CHANGED
@@ -21294,13 +21294,13 @@ function getAgentConfigs(config2) {
21294
21294
  import * as fs2 from "fs";
21295
21295
  import * as os2 from "os";
21296
21296
  import * as path2 from "path";
21297
- var logFile = path2.join(os2.tmpdir(), "oh-my-groundcontrol.log");
21297
+ var getLogFile = () => process.env.GROUNDCONTROL_LOG_FILE || path2.join(os2.tmpdir(), "oh-my-groundcontrol.log");
21298
21298
  function log(message, data) {
21299
21299
  try {
21300
21300
  const timestamp = new Date().toISOString();
21301
21301
  const logEntry = `[${timestamp}] ${message} ${data ? JSON.stringify(data) : ""}
21302
21302
  `;
21303
- fs2.appendFileSync(logFile, logEntry);
21303
+ fs2.appendFileSync(getLogFile(), logEntry);
21304
21304
  } catch {}
21305
21305
  }
21306
21306
 
@@ -22226,6 +22226,170 @@ function validateAllowedProviders(allowedProviders, enabledProviders) {
22226
22226
  return null;
22227
22227
  }
22228
22228
 
22229
+ // src/hooks/analyze-command/template/analyze.txt
22230
+ var analyze_default = `You are a code reviewer. Your job is to review code changes and provide actionable feedback.
22231
+
22232
+ ---
22233
+
22234
+ $REVIEW_TARGET
22235
+
22236
+ ---
22237
+
22238
+ ## Gathering Context
22239
+
22240
+ **Diffs alone are not enough.** After getting the diff, read the entire file(s) being modified to understand the full context. Code that looks wrong in isolation may be correct given surrounding logic\u2014and vice versa.
22241
+
22242
+ - Use the diff to identify which files changed
22243
+ - Use \`git status --short\` to identify untracked files, then read their full contents
22244
+ - Read the full file to understand existing patterns, control flow, and error handling
22245
+ - Check for existing style guide or conventions files (CONVENTIONS.md, AGENTS.md, .editorconfig, etc.)
22246
+
22247
+ ---
22248
+
22249
+ ## What to Look For
22250
+
22251
+ **Bugs** - Your primary focus.
22252
+ - Logic errors, off-by-one mistakes, incorrect conditionals
22253
+ - If-else guards: missing guards, incorrect branching, unreachable code paths
22254
+ - Edge cases: null/empty/undefined inputs, error conditions, race conditions
22255
+ - Security issues: injection, auth bypass, data exposure
22256
+ - Broken error handling that swallows failures, throws unexpectedly or returns error types that are not caught.
22257
+
22258
+ **Structure** - Does the code fit the codebase?
22259
+ - Does it follow existing patterns and conventions?
22260
+ - Are there established abstractions it should use but doesn't?
22261
+ - Excessive nesting that could be flattened with early returns or extraction
22262
+
22263
+ **Performance** - Only flag if obviously problematic.
22264
+ - O(n\xB2) on unbounded data, N+1 queries, blocking I/O on hot paths
22265
+
22266
+ **Behavior Changes** - If a behavioral change is introduced, raise it (especially if it's possibly unintentional).
22267
+
22268
+ ---
22269
+
22270
+ ## Before You Flag Something
22271
+
22272
+ **Be certain.** If you're going to call something a bug, you need to be confident it actually is one.
22273
+
22274
+ - Only review the changes - do not review pre-existing code that wasn't modified
22275
+ - Don't flag something as a bug if you're unsure - investigate first
22276
+ - Don't invent hypothetical problems - if an edge case matters, explain the realistic scenario where it breaks
22277
+ - If you need more context to be sure, use the tools below to get it
22278
+
22279
+ **Don't be a zealot about style.** When checking code against conventions:
22280
+
22281
+ - Verify the code is *actually* in violation. Don't complain about else statements if early returns are already being used correctly.
22282
+ - Some "violations" are acceptable when they're the simplest option. A \`let\` statement is fine if the alternative is convoluted.
22283
+ - Excessive nesting is a legitimate concern regardless of other style choices.
22284
+ - Don't flag style preferences as issues unless they clearly violate established project conventions.
22285
+
22286
+ ---
22287
+
22288
+ ## Tools
22289
+
22290
+ Use these to inform your review:
22291
+
22292
+ - **@explorer** - Find how existing code handles similar problems. Check patterns, conventions, and prior art before claiming something doesn't fit.
22293
+ - **@librarian** - Verify correct usage of libraries/APIs before flagging something as wrong. Research best practices if you're unsure about a pattern.
22294
+ - **@oracle** - Consult on complex architectural decisions, design pattern trade-offs, or systemic concerns that go beyond the immediate diff.
22295
+
22296
+ If you're uncertain about something and can't verify it with these tools, say "I'm not sure about X" rather than flagging it as a definite issue.
22297
+
22298
+ ---
22299
+
22300
+ ## Output
22301
+
22302
+ 1. If there is a bug, be direct and clear about why it is a bug.
22303
+ 2. Clearly communicate severity of issues. Do not overstate severity.
22304
+ 3. Critiques should clearly and explicitly communicate the scenarios, environments, or inputs that are necessary for the bug to arise. The comment should immediately indicate that the issue's severity depends on these factors.
22305
+ 4. Your tone should be matter-of-fact and not accusatory or overly positive. It should read as a helpful AI assistant suggestion without sounding too much like a human reviewer.
22306
+ 5. Write so the reader can quickly understand the issue without reading too closely.
22307
+ 6. AVOID flattery, do not give any comments that are not helpful to the reader. Avoid phrasing like "Great job ...", "Thanks for ...".`;
22308
+
22309
+ // src/hooks/analyze-command/index.ts
22310
+ function detectReviewType(args) {
22311
+ if (!args)
22312
+ return "uncommitted";
22313
+ if (args.includes("github.com") || args.includes("gitlab.com") || args.includes("/pull/") || args.includes("/merge_requests/")) {
22314
+ return "pr";
22315
+ }
22316
+ if (/^#?\d+$/.test(args.trim()))
22317
+ return "pr";
22318
+ if (/^[0-9a-f]{7,40}$/i.test(args.trim()))
22319
+ return "commit";
22320
+ if (/\.\w+$/.test(args.trim()) || args.trim().startsWith("./") || args.trim().startsWith("/")) {
22321
+ return "file";
22322
+ }
22323
+ return "branch";
22324
+ }
22325
+ function buildReviewTarget(type, args) {
22326
+ switch (type) {
22327
+ case "uncommitted":
22328
+ return `## Review Target: Uncommitted Changes
22329
+
22330
+ Review all uncommitted changes in the current working directory.
22331
+
22332
+ - Run: \`git diff\` for unstaged changes
22333
+ - Run: \`git diff --cached\` for staged changes
22334
+ - Run: \`git status --short\` to identify untracked (net new) files`;
22335
+ case "commit":
22336
+ return `## Review Target: Commit \`${args}\`
22337
+
22338
+ Review the specified commit.
22339
+
22340
+ - Run: \`git show ${args}\``;
22341
+ case "branch":
22342
+ return `## Review Target: Branch \`${args}\`
22343
+
22344
+ Compare the current branch against the specified branch.
22345
+
22346
+ - Run: \`git diff ${args}...HEAD\``;
22347
+ case "pr":
22348
+ return `## Review Target: Pull Request \`${args}\`
22349
+
22350
+ Review the specified pull request.
22351
+
22352
+ - Run: \`gh pr view ${args}\` to get PR context
22353
+ - Run: \`gh pr diff ${args}\` to get the diff`;
22354
+ case "file":
22355
+ return `## Review Target: File \`${args}\`
22356
+
22357
+ Review a specific file and its recent changes.
22358
+
22359
+ - Verify the file exists and is a regular file (not a directory or binary)
22360
+ - Read the full file contents
22361
+ - Run: \`git log --oneline -10 "${args}"\` to see recent history
22362
+ - Run: \`git diff HEAD~5 -- "${args}"\` to get recent changes (adjust range based on log output)
22363
+ - Review the recent changes in context of the full file
22364
+
22365
+ If the file does not exist: "File not found: \`${args}\`. Please check the path and try again."
22366
+ If a directory was provided: "Cannot review a directory. Please provide a specific file path."`;
22367
+ }
22368
+ }
22369
+ function createAnalyzeCommandHook() {
22370
+ return {
22371
+ "command.execute.before": async (input, output) => {
22372
+ if (input.command === "analyze") {
22373
+ const args = input.arguments?.trim() || "";
22374
+ const reviewType = detectReviewType(args);
22375
+ log("[analyze-command] Intercepted /analyze command", {
22376
+ arguments: args,
22377
+ reviewType
22378
+ });
22379
+ const reviewTarget = buildReviewTarget(reviewType, args);
22380
+ const template = analyze_default.replace("$REVIEW_TARGET", reviewTarget);
22381
+ output.parts.push({
22382
+ type: "text",
22383
+ text: template
22384
+ });
22385
+ output.parts.push({
22386
+ type: "agent",
22387
+ name: "oracle"
22388
+ });
22389
+ }
22390
+ }
22391
+ };
22392
+ }
22229
22393
  // src/hooks/auto-update-checker/cache.ts
22230
22394
  import * as fs3 from "fs";
22231
22395
  import * as path4 from "path";
@@ -39189,6 +39353,7 @@ var OhMyOpenCodeLite = async (ctx) => {
39189
39353
  const phaseReminderHook = createPhaseReminderHook();
39190
39354
  const postReadNudgeHook = createPostReadNudgeHook();
39191
39355
  const questionRouterHook = createQuestionRouterHook(ctx);
39356
+ const analyzeCommandHook = createAnalyzeCommandHook();
39192
39357
  const delegateTaskRetryHook = createDelegateTaskRetryHook(ctx);
39193
39358
  const jsonErrorRecoveryHook = createJsonErrorRecoveryHook(ctx);
39194
39359
  const hashlineReadEnhancerHook = createHashlineReadEnhancerHook(config3.hashline_edit);
@@ -39297,6 +39462,7 @@ var OhMyOpenCodeLite = async (ctx) => {
39297
39462
  },
39298
39463
  "experimental.chat.messages.transform": phaseReminderHook["experimental.chat.messages.transform"],
39299
39464
  "chat.message": questionRouterHook["chat.message"],
39465
+ "command.execute.before": analyzeCommandHook["command.execute.before"],
39300
39466
  "tool.execute.after": async (input, output) => {
39301
39467
  await delegateTaskRetryHook["tool.execute.after"](input, output);
39302
39468
  await jsonErrorRecoveryHook["tool.execute.after"](input, output);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frenchtoastman/oh-my-groundcontrol",
3
- "version": "0.0.16",
3
+ "version": "0.0.18",
4
4
  "description": "An OpenCode plugin for multi-agent orchestration for structured planning with NASA-style guardrails.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",