opencode-codegraph 0.1.22 → 0.1.23

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,9 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.23 - 2026-03-20
4
+
5
+ - surface workflow-state transitions on later interactions so async status changes become visible without waiting for a fresh session
6
+
3
7
  ## 0.1.22 - 2026-03-20
4
8
 
5
9
  - add DuckDB maintenance guidance and `/maintain-db` workflow command for local database compaction
package/README.md CHANGED
@@ -120,6 +120,7 @@ Place in `.opencode/commands/`:
120
120
  | `codegraph_review` tool | Returns review results together with current workflow guidance and suggested follow-up command |
121
121
  | `experimental.session.compacting` | Preserve current dogfooding status when OpenCode compacts long sessions |
122
122
  | `command.execute.before` | Inject current dogfooding status into `/review`, `/audit`, `/update`, `/status`, and `/next` |
123
+ | `db_locked` recovery path | Surface lock-holder-aware recovery guidance when DuckDB is blocked by another process |
123
124
  | `permission.ask` | Auto-allow `codegraph_*` tools |
124
125
 
125
126
  ## License
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-codegraph",
3
- "version": "0.1.22",
3
+ "version": "0.1.23",
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
@@ -23,6 +23,7 @@ import {
23
23
  formatPendingReviewTraceSummary,
24
24
  formatReviewTraceSummary,
25
25
  formatReviewTraceUpdateSummary,
26
+ formatWorkflowStateTransition,
26
27
  formatWorkflowGuidanceBlock,
27
28
  getHeadCommit,
28
29
  isGitCommit,
@@ -48,6 +49,32 @@ const codegraphPlugin: Plugin = async (input) => {
48
49
  // Detect project ID from environment or opencode.json
49
50
  const projectId = process.env.CODEGRAPH_PROJECT || ""
50
51
  let pendingReviewCommit: string | null = null
52
+ let lastWorkflowState: string | null = null
53
+
54
+ const workflowFields = (status: Record<string, unknown>) => {
55
+ const workflowState = typeof status.workflow_state === "string" ? status.workflow_state : null
56
+ const nextAction =
57
+ typeof status.recommended_next_action === "string" ? status.recommended_next_action : undefined
58
+ const nextCommand =
59
+ typeof status.recommended_command === "string" ? status.recommended_command : undefined
60
+ return { workflowState, nextAction, nextCommand }
61
+ }
62
+
63
+ const captureWorkflowState = (status: Record<string, unknown>) => {
64
+ const { workflowState } = workflowFields(status)
65
+ if (workflowState) {
66
+ lastWorkflowState = workflowState
67
+ }
68
+ }
69
+
70
+ const workflowTransition = (status: Record<string, unknown>) => {
71
+ const { workflowState, nextAction, nextCommand } = workflowFields(status)
72
+ const message = formatWorkflowStateTransition(lastWorkflowState, workflowState, nextAction, nextCommand)
73
+ if (workflowState) {
74
+ lastWorkflowState = workflowState
75
+ }
76
+ return message
77
+ }
51
78
 
52
79
  const consumePendingReviewTraceUpdate = async (): Promise<string | null> => {
53
80
  if (!pendingReviewCommit) return null
@@ -67,10 +94,12 @@ const codegraphPlugin: Plugin = async (input) => {
67
94
  "experimental.chat.system.transform": async (_inp, output) => {
68
95
  try {
69
96
  const rawStatus = await $`python -m src.cli.import_commands dogfood status --json`.quiet().text()
70
- const statusSummary = formatDogfoodStatusSummary(JSON.parse(rawStatus))
97
+ const status = JSON.parse(rawStatus)
98
+ const statusSummary = formatDogfoodStatusSummary(status)
71
99
  if (statusSummary) {
72
100
  output.system.push(statusSummary)
73
101
  }
102
+ captureWorkflowState(status)
74
103
  } catch {
75
104
  // Dogfooding status unavailable — keep session startup lightweight
76
105
  }
@@ -91,10 +120,12 @@ const codegraphPlugin: Plugin = async (input) => {
91
120
  "experimental.session.compacting": async (_inp, output) => {
92
121
  try {
93
122
  const rawStatus = await $`python -m src.cli.import_commands dogfood status --json`.quiet().text()
94
- const statusSummary = formatDogfoodStatusSummary(JSON.parse(rawStatus))
123
+ const status = JSON.parse(rawStatus)
124
+ const statusSummary = formatDogfoodStatusSummary(status)
95
125
  if (statusSummary) {
96
126
  output.context.push(statusSummary)
97
127
  }
128
+ captureWorkflowState(status)
98
129
  } catch {
99
130
  // Keep compaction resilient if status lookup fails
100
131
  }
@@ -118,7 +149,15 @@ const codegraphPlugin: Plugin = async (input) => {
118
149
  }
119
150
 
120
151
  const rawStatus = await $`python -m src.cli.import_commands dogfood status --json`.quiet().text()
121
- const statusSummary = formatDogfoodStatusSummary(JSON.parse(rawStatus))
152
+ const status = JSON.parse(rawStatus)
153
+ const transition = workflowTransition(status)
154
+ if (transition) {
155
+ output.parts.push({
156
+ type: "text",
157
+ text: transition,
158
+ } as any)
159
+ }
160
+ const statusSummary = formatDogfoodStatusSummary(status)
122
161
  if (statusSummary) {
123
162
  output.parts.push({
124
163
  type: "text",
@@ -152,7 +191,15 @@ const codegraphPlugin: Plugin = async (input) => {
152
191
  if (workflowIntent) {
153
192
  try {
154
193
  const rawStatus = await $`python -m src.cli.import_commands dogfood status --json`.quiet().text()
155
- const statusSummary = formatDogfoodStatusSummary(JSON.parse(rawStatus))
194
+ const status = JSON.parse(rawStatus)
195
+ const transition = workflowTransition(status)
196
+ if (transition) {
197
+ output.parts.push({
198
+ type: "text",
199
+ text: transition,
200
+ } as any)
201
+ }
202
+ const statusSummary = formatDogfoodStatusSummary(status)
156
203
  if (statusSummary) {
157
204
  output.parts.push({
158
205
  type: "text",
@@ -206,12 +253,13 @@ const codegraphPlugin: Plugin = async (input) => {
206
253
  try {
207
254
  const rawStatus = await $`python -m src.cli.import_commands dogfood status --json`.quiet().text()
208
255
  const status = JSON.parse(rawStatus)
256
+ const transition = workflowTransition(status)
209
257
  const testFailed = didTestCommandFail(output.output)
210
258
  const guidance = formatAfterTestGuidance(status, testFailed)
211
259
  if (guidance) {
212
260
  output.title = "CodeGraph: after-test guidance ready"
213
261
  const existingOutput = output.output?.trimEnd() || ""
214
- output.output = existingOutput ? `${existingOutput}\n\n${guidance}` : guidance
262
+ output.output = [existingOutput, transition || "", guidance].filter(Boolean).join("\n\n")
215
263
  output.metadata = {
216
264
  ...output.metadata,
217
265
  codegraph_after_test_result: testFailed ? "failed" : "passed_or_unknown",
@@ -229,11 +277,12 @@ const codegraphPlugin: Plugin = async (input) => {
229
277
  try {
230
278
  const rawStatus = await $`python -m src.cli.import_commands dogfood status --json`.quiet().text()
231
279
  const status = JSON.parse(rawStatus)
280
+ const transition = workflowTransition(status)
232
281
  const guidance = formatDogfoodStatusSummary(status)
233
282
  if (guidance) {
234
283
  output.title = "CodeGraph: git workflow guidance ready"
235
284
  const existingOutput = output.output?.trimEnd() || ""
236
- output.output = existingOutput ? `${existingOutput}\n\n${guidance}` : guidance
285
+ output.output = [existingOutput, transition || "", guidance].filter(Boolean).join("\n\n")
237
286
  output.metadata = {
238
287
  ...output.metadata,
239
288
  codegraph_git_workflow_state: status.workflow_state || null,
package/src/util.ts CHANGED
@@ -457,6 +457,31 @@ export function formatWorkflowGuidanceBlock(snapshot: DogfoodStatusSnapshot): st
457
457
  return lines.join("\n")
458
458
  }
459
459
 
460
+ export function formatWorkflowStateTransition(
461
+ previousState: string | null,
462
+ currentState: string | null,
463
+ nextAction: string | undefined,
464
+ nextCommand: string | undefined,
465
+ ): string | null {
466
+ if (!previousState || !currentState || previousState === currentState) {
467
+ return null
468
+ }
469
+
470
+ const lines = [
471
+ "## CodeGraph Workflow Update",
472
+ "",
473
+ `- Workflow state changed: ${previousState} -> ${currentState}`,
474
+ ]
475
+
476
+ if (nextAction) {
477
+ lines.push(`- Next action: ${nextAction}`)
478
+ }
479
+ if (nextCommand) {
480
+ lines.push(`- Suggested command: ${nextCommand}`)
481
+ }
482
+ return lines.join("\n")
483
+ }
484
+
460
485
  export function formatAfterTestGuidance(
461
486
  snapshot: DogfoodStatusSnapshot,
462
487
  testFailed = false,