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 +4 -0
- package/README.md +1 -0
- package/package.json +1 -1
- package/src/index.ts +55 -6
- package/src/util.ts +25 -0
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
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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,
|