opencode-codegraph 0.1.19 → 0.1.21

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 CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.21 - 2026-03-20
4
+
5
+ - append workflow guidance to the `codegraph_review` custom tool so tool results stay aligned with current dogfooding state
6
+ - add `/continue` as a safe guided execution command for refresh/review workflow steps
7
+
8
+ ## 0.1.20 - 2026-03-20
9
+
10
+ - append workflow guidance to the `codegraph_review` custom tool so tool results stay aligned with current dogfooding state
11
+
3
12
  ## 0.1.19 - 2026-03-20
4
13
 
5
14
  - add workflow guidance directly to `git status` and `git diff` command output inside OpenCode
package/README.md CHANGED
@@ -117,6 +117,7 @@ Place in `.opencode/commands/`:
117
117
  | `tool.execute.after` on test commands | Add after-test workflow guidance and detect failed test runs before suggesting the next command |
118
118
  | `tool.execute.after` on `git status` / `git diff` | Add current workflow guidance directly to common git inspection commands |
119
119
  | `tool.execute.after` | Trigger CPG update after git commit and append structured post-commit review summary |
120
+ | `codegraph_review` tool | Returns review results together with current workflow guidance and suggested follow-up command |
120
121
  | `experimental.session.compacting` | Preserve current dogfooding status when OpenCode compacts long sessions |
121
122
  | `command.execute.before` | Inject current dogfooding status into `/review`, `/audit`, `/update`, `/status`, and `/next` |
122
123
  | `permission.ask` | Auto-allow `codegraph_*` tools |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-codegraph",
3
- "version": "0.1.19",
3
+ "version": "0.1.21",
4
4
  "description": "OpenCode plugin for CodeGraph CPG-powered code analysis",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
package/src/index.ts CHANGED
@@ -22,6 +22,8 @@ import {
22
22
  formatDogfoodStatusSummary,
23
23
  formatPendingReviewTraceSummary,
24
24
  formatReviewTraceSummary,
25
+ formatReviewTraceUpdateSummary,
26
+ formatWorkflowGuidanceBlock,
25
27
  getHeadCommit,
26
28
  isGitCommit,
27
29
  isGitStatusLikeCommand,
@@ -43,8 +45,20 @@ const codegraphPlugin: Plugin = async (input) => {
43
45
  const apiUrl = process.env.CODEGRAPH_API_URL || "http://localhost:8000"
44
46
  const api = new CodeGraphAPI(apiUrl)
45
47
 
46
- // Detect project ID from environment or opencode.json
47
- const projectId = process.env.CODEGRAPH_PROJECT || ""
48
+ // Detect project ID from environment or opencode.json
49
+ const projectId = process.env.CODEGRAPH_PROJECT || ""
50
+ let pendingReviewCommit: string | null = null
51
+
52
+ const consumePendingReviewTraceUpdate = async (): Promise<string | null> => {
53
+ if (!pendingReviewCommit) return null
54
+ const commit = pendingReviewCommit
55
+ const traceSnapshot = await readReviewTraceSnapshot(directory, commit, 1, 0)
56
+ if (!traceSnapshot) return null
57
+ const workflowState = traceSnapshot.workflow_state || workflowStateFromReviewTrace(traceSnapshot)
58
+ if (workflowState === "trace_pending") return null
59
+ pendingReviewCommit = null
60
+ return formatReviewTraceUpdateSummary(traceSnapshot)
61
+ }
48
62
 
49
63
  return {
50
64
  // -----------------------------------------------------------------
@@ -95,6 +109,14 @@ const codegraphPlugin: Plugin = async (input) => {
95
109
  }
96
110
 
97
111
  try {
112
+ const pendingUpdate = await consumePendingReviewTraceUpdate()
113
+ if (pendingUpdate) {
114
+ output.parts.push({
115
+ type: "text",
116
+ text: pendingUpdate,
117
+ } as any)
118
+ }
119
+
98
120
  const rawStatus = await $`python -m src.cli.import_commands dogfood status --json`.quiet().text()
99
121
  const statusSummary = formatDogfoodStatusSummary(JSON.parse(rawStatus))
100
122
  if (statusSummary) {
@@ -119,6 +141,14 @@ const codegraphPlugin: Plugin = async (input) => {
119
141
  if (!files.length && !workflowIntent) return
120
142
 
121
143
  try {
144
+ const pendingUpdate = await consumePendingReviewTraceUpdate()
145
+ if (pendingUpdate) {
146
+ output.parts.push({
147
+ type: "text",
148
+ text: pendingUpdate,
149
+ } as any)
150
+ }
151
+
122
152
  if (workflowIntent) {
123
153
  try {
124
154
  const rawStatus = await $`python -m src.cli.import_commands dogfood status --json`.quiet().text()
@@ -244,6 +274,7 @@ const codegraphPlugin: Plugin = async (input) => {
244
274
  }
245
275
  } else {
246
276
  traceSummary = formatPendingReviewTraceSummary(commit)
277
+ pendingReviewCommit = commit
247
278
  output.metadata = {
248
279
  ...output.metadata,
249
280
  codegraph_review_trace_status: "pending_or_missing",
@@ -295,17 +326,22 @@ const codegraphPlugin: Plugin = async (input) => {
295
326
  .optional()
296
327
  .describe("Base git ref to compare against (default: HEAD~1)"),
297
328
  },
298
- async execute(args) {
299
- const baseRef = args.base_ref || "HEAD~1"
300
- const diff = await $`git diff ${baseRef}`.quiet().text()
301
- if (!diff.trim()) {
302
- return "No changes found."
303
- }
304
-
305
- const result = await api.reviewChanges(projectId, diff, baseRef)
306
- return result
307
- },
308
- }),
329
+ async execute(args) {
330
+ const baseRef = args.base_ref || "HEAD~1"
331
+ const diff = await $`git diff ${baseRef}`.quiet().text()
332
+ const rawStatus = await $`python -m src.cli.import_commands dogfood status --json`.quiet().text()
333
+ const status = JSON.parse(rawStatus)
334
+ const guidance = formatWorkflowGuidanceBlock(status)
335
+ if (!diff.trim()) {
336
+ return guidance ? `No changes found.\n\n${guidance}` : "No changes found."
337
+ }
338
+
339
+ const result = await api.reviewChanges(projectId, diff, baseRef)
340
+ return guidance
341
+ ? `${result}\n\n${guidance}\n\nUse the suggested command if the review result and session state disagree.`
342
+ : result
343
+ },
344
+ }),
309
345
 
310
346
  codegraph_explain_function: tool({
311
347
  description:
package/src/util.ts CHANGED
@@ -257,6 +257,12 @@ export function formatReviewTraceSummary(snapshot: ReviewTraceSnapshot): string
257
257
  return lines.join("\n")
258
258
  }
259
259
 
260
+ export function formatReviewTraceUpdateSummary(snapshot: ReviewTraceSnapshot): string | null {
261
+ const base = formatReviewTraceSummary(snapshot)
262
+ if (!base) return null
263
+ return base.replace("## CodeGraph Post-Commit Summary", "## CodeGraph Review Trace Update")
264
+ }
265
+
260
266
  export function whatChangedFromReviewTrace(snapshot: ReviewTraceSnapshot): string[] {
261
267
  const items: string[] = []
262
268
  const status = snapshot.status || "unknown"
@@ -417,6 +423,28 @@ export function formatDogfoodStatusSummary(snapshot: DogfoodStatusSnapshot): str
417
423
  return lines.join("\n")
418
424
  }
419
425
 
426
+ export function formatWorkflowGuidanceBlock(snapshot: DogfoodStatusSnapshot): string | null {
427
+ const workflowState = snapshot.workflow_state
428
+ const nextAction = snapshot.recommended_next_action
429
+ const nextCommand = snapshot.recommended_command
430
+
431
+ if (!workflowState && !nextAction && !nextCommand) {
432
+ return null
433
+ }
434
+
435
+ const lines = ["## CodeGraph Workflow Guidance", ""]
436
+ if (workflowState) {
437
+ lines.push(`- Workflow state: ${workflowState}`)
438
+ }
439
+ if (nextAction) {
440
+ lines.push(`- Next action: ${nextAction}`)
441
+ }
442
+ if (nextCommand) {
443
+ lines.push(`- Suggested command: ${nextCommand}`)
444
+ }
445
+ return lines.join("\n")
446
+ }
447
+
420
448
  export function formatAfterTestGuidance(
421
449
  snapshot: DogfoodStatusSnapshot,
422
450
  testFailed = false,