opencode-codegraph 0.1.6 → 0.1.7

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,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.7 - 2026-03-20
4
+
5
+ - add command-oriented next-step guidance (`/status`, `/update`, `/review`) to review-trace and dogfooding status flows
6
+ - unify `/review`, `/audit`, and `/update` around the shared `dogfood status --json` backend
7
+ - keep session-start and post-commit guidance aligned on the same recommended command semantics
8
+
3
9
  ## 0.1.6 - 2026-03-20
4
10
 
5
11
  - add explicit pending post-commit summary when durable review trace is not yet available
package/README.md CHANGED
@@ -39,9 +39,13 @@ Plugin injects:
39
39
 
40
40
  If the message also suggests an edit intent (`refactor`, `fix`, `modify`, `update`, etc.), the plugin appends a pre-edit warning block with complexity, fan-out, dead-code, and security hints for the referenced file.
41
41
 
42
- ### System Prompt
43
-
44
- Every conversation includes a project summary with file count, top complexity hotspots, and open security findings.
42
+ ### System Prompt
43
+
44
+ Every conversation includes:
45
+
46
+ - a project summary with file count, top complexity hotspots, and open security findings;
47
+ - a lightweight dogfooding status block when available, including freshness, current `HEAD`, review-trace state, and recommended next action.
48
+ - a recommended command (`/status`, `/update`, or `/review`) when the workflow can point to a deterministic next step.
45
49
 
46
50
  ### Post-Commit Updates
47
51
 
@@ -51,6 +55,7 @@ After `git commit`, the plugin triggers incremental CPG re-parsing via GoCPG and
51
55
  - why it matters
52
56
  - top recommendations
53
57
  - one clear next action
58
+ - one suggested command to run next
54
59
 
55
60
  If the durable review trace is not available yet, the plugin still appends a pending summary telling the developer to check `/status` instead of leaving the post-commit state ambiguous.
56
61
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-codegraph",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
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
@@ -17,11 +17,13 @@ import { CodeGraphAPI } from "./api"
17
17
  import {
18
18
  extractFileRefs,
19
19
  fileNeedsRegistrationCheck,
20
+ formatDogfoodStatusSummary,
20
21
  formatPendingReviewTraceSummary,
21
22
  formatReviewTraceSummary,
22
23
  getHeadCommit,
23
24
  isGitCommit,
24
25
  messageSuggestsEditing,
26
+ recommendedCommandFromReviewTrace,
25
27
  recommendedNextActionFromReviewTrace,
26
28
  readReviewTraceSnapshot,
27
29
  whatChangedFromReviewTrace,
@@ -42,16 +44,26 @@ const codegraphPlugin: Plugin = async (input) => {
42
44
  // -----------------------------------------------------------------
43
45
  // 1. System prompt: inject CPG project summary
44
46
  // -----------------------------------------------------------------
45
- "experimental.chat.system.transform": async (_inp, output) => {
46
- try {
47
- const summary = await api.getProjectSummary(projectId)
48
- if (summary) {
49
- output.system.push(summary)
50
- }
51
- } catch {
52
- // CodeGraph API not available — skip silently
53
- }
54
- },
47
+ "experimental.chat.system.transform": async (_inp, output) => {
48
+ try {
49
+ const rawStatus = await $`python -m src.cli.import_commands dogfood status --json`.quiet().text()
50
+ const statusSummary = formatDogfoodStatusSummary(JSON.parse(rawStatus))
51
+ if (statusSummary) {
52
+ output.system.push(statusSummary)
53
+ }
54
+ } catch {
55
+ // Dogfooding status unavailable — keep session startup lightweight
56
+ }
57
+
58
+ try {
59
+ const summary = await api.getProjectSummary(projectId)
60
+ if (summary) {
61
+ output.system.push(summary)
62
+ }
63
+ } catch {
64
+ // CodeGraph API not available — skip silently
65
+ }
66
+ },
55
67
 
56
68
  // -----------------------------------------------------------------
57
69
  // 2. Chat message: auto-enrich with CPG context for mentioned files
@@ -117,6 +129,8 @@ const codegraphPlugin: Plugin = async (input) => {
117
129
  codegraph_review_trace_recommendations:
118
130
  traceSnapshot.review_recommendations?.slice(0, 3) || [],
119
131
  codegraph_review_trace_next_action: recommendedNextActionFromReviewTrace(traceSnapshot),
132
+ codegraph_review_trace_recommended_command:
133
+ traceSnapshot.recommended_command || recommendedCommandFromReviewTrace(traceSnapshot),
120
134
  codegraph_review_trace_what_changed: whatChangedFromReviewTrace(traceSnapshot),
121
135
  codegraph_review_trace_why_it_matters: whyItMattersFromReviewTrace(traceSnapshot),
122
136
  }
@@ -130,6 +144,7 @@ const codegraphPlugin: Plugin = async (input) => {
130
144
  codegraph_review_trace_recommendations: [],
131
145
  codegraph_review_trace_next_action:
132
146
  "Wait briefly for review trace completion, then run /status to check the latest result.",
147
+ codegraph_review_trace_recommended_command: "/status",
133
148
  codegraph_review_trace_what_changed: [
134
149
  `Incremental CPG update was triggered for ${commit.slice(0, 12)}.`,
135
150
  "Durable review trace is not available yet or has not been written.",
package/src/util.ts CHANGED
@@ -14,6 +14,19 @@ export type ReviewTraceSnapshot = {
14
14
  review_severity_counts?: Record<string, number>
15
15
  review_recommendations?: string[]
16
16
  error?: string | null
17
+ recommended_command?: string
18
+ }
19
+
20
+ export type DogfoodStatusSnapshot = {
21
+ cpg_status?: {
22
+ is_fresh?: boolean
23
+ freshness_reason?: string
24
+ commits_behind?: number
25
+ db_exists?: boolean
26
+ }
27
+ head_commit?: string
28
+ review_trace?: ReviewTraceSnapshot | null
29
+ recommended_next_action?: string
17
30
  }
18
31
 
19
32
  /**
@@ -146,6 +159,7 @@ export function formatPendingReviewTraceSummary(commit: string | null): string {
146
159
  "### What to do now",
147
160
  "",
148
161
  "- Wait briefly for review trace completion, then run `/status` to check the latest result.",
162
+ "- Suggested command: `/status`",
149
163
  ].join("\n")
150
164
  }
151
165
 
@@ -156,6 +170,7 @@ export function formatReviewTraceSummary(snapshot: ReviewTraceSnapshot): string
156
170
  const whatChanged = whatChangedFromReviewTrace(snapshot)
157
171
  const whyItMatters = whyItMattersFromReviewTrace(snapshot)
158
172
  const nextAction = recommendedNextActionFromReviewTrace(snapshot)
173
+ const nextCommand = recommendedCommandFromReviewTrace(snapshot)
159
174
 
160
175
  const lines = ["## CodeGraph Post-Commit Summary", ""]
161
176
 
@@ -176,6 +191,7 @@ export function formatReviewTraceSummary(snapshot: ReviewTraceSnapshot): string
176
191
  }
177
192
 
178
193
  lines.push("### What to do now", "", `- ${nextAction}`)
194
+ lines.push(`- Suggested command: \`${nextCommand}\``)
179
195
 
180
196
  return lines.join("\n")
181
197
  }
@@ -254,6 +270,59 @@ export function recommendedNextActionFromReviewTrace(snapshot: ReviewTraceSnapsh
254
270
  return "No review findings recorded; continue with /review or push once the rest of your checks are green."
255
271
  }
256
272
 
273
+ export function recommendedCommandFromReviewTrace(snapshot: ReviewTraceSnapshot): string {
274
+ const status = (snapshot.status || "").toLowerCase()
275
+ const findingsCount = snapshot.review_findings_count
276
+
277
+ if (snapshot.error) {
278
+ return "/review"
279
+ }
280
+ if (status === "running") {
281
+ return "/status"
282
+ }
283
+ if (status && status !== "completed") {
284
+ return "/review"
285
+ }
286
+ if (typeof findingsCount === "number" && findingsCount > 0) {
287
+ return "/review"
288
+ }
289
+ return "/review"
290
+ }
291
+
292
+ export function formatDogfoodStatusSummary(snapshot: DogfoodStatusSnapshot): string | null {
293
+ const cpg = snapshot.cpg_status || {}
294
+ const isFresh = cpg.is_fresh
295
+ const freshnessReason = cpg.freshness_reason || "unknown"
296
+ const commitsBehind = cpg.commits_behind
297
+ const headCommit = snapshot.head_commit ? snapshot.head_commit.slice(0, 12) : null
298
+ const reviewTrace = snapshot.review_trace || null
299
+ const traceStatus = reviewTrace?.status || "missing"
300
+ const nextAction = snapshot.recommended_next_action
301
+ const nextCommand = (snapshot as { recommended_command?: string }).recommended_command
302
+
303
+ if (typeof isFresh === "undefined" && !headCommit && !nextAction) {
304
+ return null
305
+ }
306
+
307
+ const lines = ["## CodeGraph Dogfooding Status", ""]
308
+ if (typeof isFresh !== "undefined") {
309
+ const freshness = isFresh ? "fresh" : "stale"
310
+ const behind = typeof commitsBehind === "number" ? `, commits behind: ${commitsBehind}` : ""
311
+ lines.push(`- CPG freshness: ${freshness} (reason: ${freshnessReason}${behind})`)
312
+ }
313
+ if (headCommit) {
314
+ lines.push(`- HEAD: ${headCommit}`)
315
+ }
316
+ lines.push(`- Review trace: ${traceStatus}`)
317
+ if (nextAction) {
318
+ lines.push(`- Next action: ${nextAction}`)
319
+ }
320
+ if (nextCommand) {
321
+ lines.push(`- Suggested command: ${nextCommand}`)
322
+ }
323
+ return lines.join("\n")
324
+ }
325
+
257
326
  // File extensions recognized as source code
258
327
  const SOURCE_EXTENSIONS = new Set([
259
328
  "py",