@kodrunhq/opencode-autopilot 1.15.2 → 1.16.0

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.
Files changed (61) hide show
  1. package/bin/cli.ts +5 -0
  2. package/bin/inspect.ts +337 -0
  3. package/package.json +1 -1
  4. package/src/agents/autopilot.ts +7 -15
  5. package/src/health/checks.ts +29 -4
  6. package/src/index.ts +103 -11
  7. package/src/inspect/formatters.ts +225 -0
  8. package/src/inspect/repository.ts +882 -0
  9. package/src/kernel/database.ts +45 -0
  10. package/src/kernel/migrations.ts +62 -0
  11. package/src/kernel/repository.ts +571 -0
  12. package/src/kernel/schema.ts +122 -0
  13. package/src/kernel/types.ts +66 -0
  14. package/src/memory/capture.ts +221 -25
  15. package/src/memory/database.ts +74 -12
  16. package/src/memory/index.ts +17 -1
  17. package/src/memory/project-key.ts +6 -0
  18. package/src/memory/repository.ts +833 -42
  19. package/src/memory/retrieval.ts +83 -169
  20. package/src/memory/schemas.ts +39 -7
  21. package/src/memory/types.ts +4 -0
  22. package/src/observability/event-handlers.ts +28 -17
  23. package/src/observability/event-store.ts +29 -1
  24. package/src/observability/forensic-log.ts +159 -0
  25. package/src/observability/forensic-schemas.ts +69 -0
  26. package/src/observability/forensic-types.ts +10 -0
  27. package/src/observability/index.ts +21 -27
  28. package/src/observability/log-reader.ts +142 -111
  29. package/src/observability/log-writer.ts +41 -83
  30. package/src/observability/retention.ts +2 -2
  31. package/src/observability/session-logger.ts +36 -57
  32. package/src/observability/summary-generator.ts +31 -19
  33. package/src/observability/types.ts +12 -24
  34. package/src/orchestrator/contracts/invariants.ts +14 -0
  35. package/src/orchestrator/contracts/legacy-result-adapter.ts +8 -20
  36. package/src/orchestrator/fallback/event-handler.ts +47 -3
  37. package/src/orchestrator/handlers/architect.ts +2 -1
  38. package/src/orchestrator/handlers/build.ts +55 -97
  39. package/src/orchestrator/handlers/retrospective.ts +2 -1
  40. package/src/orchestrator/handlers/types.ts +0 -1
  41. package/src/orchestrator/lesson-memory.ts +29 -9
  42. package/src/orchestrator/orchestration-logger.ts +37 -23
  43. package/src/orchestrator/phase.ts +8 -4
  44. package/src/orchestrator/state.ts +79 -17
  45. package/src/projects/database.ts +47 -0
  46. package/src/projects/repository.ts +264 -0
  47. package/src/projects/resolve.ts +301 -0
  48. package/src/projects/schemas.ts +30 -0
  49. package/src/projects/types.ts +12 -0
  50. package/src/review/memory.ts +29 -9
  51. package/src/tools/doctor.ts +26 -2
  52. package/src/tools/forensics.ts +7 -12
  53. package/src/tools/logs.ts +6 -5
  54. package/src/tools/memory-preferences.ts +157 -0
  55. package/src/tools/memory-status.ts +17 -96
  56. package/src/tools/orchestrate.ts +97 -81
  57. package/src/tools/pipeline-report.ts +3 -2
  58. package/src/tools/quick.ts +2 -2
  59. package/src/tools/review.ts +39 -6
  60. package/src/tools/session-stats.ts +3 -2
  61. package/src/utils/paths.ts +20 -1
@@ -0,0 +1,225 @@
1
+ import type {
2
+ InspectEventSummary,
3
+ InspectLessonSummary,
4
+ InspectMemoryOverview,
5
+ InspectPreferenceSummary,
6
+ InspectProjectDetails,
7
+ InspectProjectSummary,
8
+ InspectRunSummary,
9
+ } from "./repository";
10
+
11
+ function sanitizeCell(value: string | number | boolean | null): string {
12
+ return String(value ?? "")
13
+ .replace(/\|/g, "\\|")
14
+ .replace(/\n/g, " ");
15
+ }
16
+
17
+ function formatTimestamp(value: string | null): string {
18
+ return value ?? "-";
19
+ }
20
+
21
+ export function formatProjects(projects: readonly InspectProjectSummary[]): string {
22
+ if (projects.length === 0) {
23
+ return "No projects found.";
24
+ }
25
+
26
+ const lines = [
27
+ "Projects",
28
+ "",
29
+ "| Project | Current Path | Updated | Runs | Events | Lessons |",
30
+ "|---------|--------------|---------|------|--------|---------|",
31
+ ];
32
+
33
+ for (const project of projects) {
34
+ lines.push(
35
+ `| ${sanitizeCell(project.name)} | ${sanitizeCell(project.path)} | ${sanitizeCell(project.lastUpdated)} | ${project.runCount} | ${project.eventCount} | ${project.lessonCount} |`,
36
+ );
37
+ }
38
+
39
+ return lines.join("\n");
40
+ }
41
+
42
+ export function formatProjectDetails(details: InspectProjectDetails): string {
43
+ const { project, paths, gitFingerprints } = details;
44
+ const lines = [
45
+ `Project: ${project.name}`,
46
+ "",
47
+ `ID: ${project.id}`,
48
+ `Current Path: ${project.path}`,
49
+ `First Seen: ${project.firstSeenAt}`,
50
+ `Last Updated: ${project.lastUpdated}`,
51
+ `Runs: ${project.runCount}`,
52
+ `Events: ${project.eventCount}`,
53
+ `Lessons: ${project.lessonCount}`,
54
+ `Observations: ${project.observationCount}`,
55
+ "",
56
+ "Paths:",
57
+ ];
58
+
59
+ if (paths.length === 0) {
60
+ lines.push("- none");
61
+ } else {
62
+ for (const path of paths) {
63
+ lines.push(`- ${path.path}${path.isCurrent ? " [current]" : ""}`);
64
+ }
65
+ }
66
+
67
+ lines.push("", "Git Fingerprints:");
68
+ if (gitFingerprints.length === 0) {
69
+ lines.push("- none");
70
+ } else {
71
+ for (const fingerprint of gitFingerprints) {
72
+ lines.push(
73
+ `- ${fingerprint.normalizedRemoteUrl}${fingerprint.defaultBranch ? ` (${fingerprint.defaultBranch})` : ""}`,
74
+ );
75
+ }
76
+ }
77
+
78
+ return lines.join("\n");
79
+ }
80
+
81
+ export function formatRuns(runs: readonly InspectRunSummary[]): string {
82
+ if (runs.length === 0) {
83
+ return "No runs found.";
84
+ }
85
+
86
+ const lines = [
87
+ "Runs",
88
+ "",
89
+ "| Project | Run ID | Status | Phase | Revision | Updated |",
90
+ "|---------|--------|--------|-------|----------|---------|",
91
+ ];
92
+
93
+ for (const run of runs) {
94
+ lines.push(
95
+ `| ${sanitizeCell(run.projectName)} | ${sanitizeCell(run.runId)} | ${sanitizeCell(run.status)} | ${sanitizeCell(run.currentPhase ?? "-")} | ${run.stateRevision} | ${sanitizeCell(run.lastUpdatedAt)} |`,
96
+ );
97
+ }
98
+
99
+ return lines.join("\n");
100
+ }
101
+
102
+ export function formatEvents(events: readonly InspectEventSummary[]): string {
103
+ if (events.length === 0) {
104
+ return "No events found.";
105
+ }
106
+
107
+ const lines = [
108
+ "Events",
109
+ "",
110
+ "| Timestamp | Project | Domain | Type | Phase | Agent | Code | Message |",
111
+ "|-----------|---------|--------|------|-------|-------|------|---------|",
112
+ ];
113
+
114
+ for (const event of events) {
115
+ lines.push(
116
+ `| ${sanitizeCell(event.timestamp)} | ${sanitizeCell(event.projectName)} | ${sanitizeCell(event.domain)} | ${sanitizeCell(event.type)} | ${sanitizeCell(event.phase ?? "-")} | ${sanitizeCell(event.agent ?? "-")} | ${sanitizeCell(event.code ?? "-")} | ${sanitizeCell(event.message ?? "")} |`,
117
+ );
118
+ }
119
+
120
+ return lines.join("\n");
121
+ }
122
+
123
+ export function formatLessons(lessons: readonly InspectLessonSummary[]): string {
124
+ if (lessons.length === 0) {
125
+ return "No lessons found.";
126
+ }
127
+
128
+ const lines = [
129
+ "Lessons",
130
+ "",
131
+ "| Extracted | Project | Domain | Source Phase | Content |",
132
+ "|-----------|---------|--------|--------------|---------|",
133
+ ];
134
+
135
+ for (const lesson of lessons) {
136
+ lines.push(
137
+ `| ${sanitizeCell(lesson.extractedAt)} | ${sanitizeCell(lesson.projectName)} | ${sanitizeCell(lesson.domain)} | ${sanitizeCell(lesson.sourcePhase)} | ${sanitizeCell(lesson.content)} |`,
138
+ );
139
+ }
140
+
141
+ return lines.join("\n");
142
+ }
143
+
144
+ export function formatPreferences(preferences: readonly InspectPreferenceSummary[]): string {
145
+ if (preferences.length === 0) {
146
+ return "No preferences found.";
147
+ }
148
+
149
+ const lines = [
150
+ "Preferences",
151
+ "",
152
+ "| Key | Scope | Value | Confidence | Evidence | Updated |",
153
+ "|-----|-------|-------|------------|----------|---------|",
154
+ ];
155
+
156
+ for (const preference of preferences) {
157
+ lines.push(
158
+ `| ${sanitizeCell(preference.key)} | ${sanitizeCell(preference.scope)}${preference.projectId ? `:${sanitizeCell(preference.projectId)}` : ""} | ${sanitizeCell(preference.value)} | ${sanitizeCell(preference.confidence)} | ${sanitizeCell(preference.evidenceCount)} | ${sanitizeCell(preference.lastUpdated)} |`,
159
+ );
160
+ }
161
+
162
+ return lines.join("\n");
163
+ }
164
+
165
+ export function formatMemoryOverview(overview: InspectMemoryOverview): string {
166
+ const lines = [
167
+ "Memory Overview",
168
+ "",
169
+ `Total observations: ${overview.stats.totalObservations}`,
170
+ `Total projects: ${overview.stats.totalProjects}`,
171
+ `Total preferences: ${overview.stats.totalPreferences}`,
172
+ `Storage size: ${overview.stats.storageSizeKb} KB`,
173
+ "",
174
+ "Observations by type:",
175
+ ];
176
+
177
+ for (const [type, count] of Object.entries(overview.stats.observationsByType)) {
178
+ lines.push(`- ${type}: ${count}`);
179
+ }
180
+
181
+ lines.push("", "Recent observations:");
182
+ if (overview.recentObservations.length === 0) {
183
+ lines.push("- none");
184
+ } else {
185
+ for (const observation of overview.recentObservations) {
186
+ lines.push(
187
+ `- [${observation.type}] ${observation.summary} (${formatTimestamp(observation.createdAt)})`,
188
+ );
189
+ }
190
+ }
191
+
192
+ lines.push("", "Preferences:");
193
+ if (overview.preferences.length === 0) {
194
+ lines.push("- none");
195
+ } else {
196
+ for (const preference of overview.preferences) {
197
+ lines.push(
198
+ `- ${preference.key}: ${preference.value} (${preference.scope}, confidence ${preference.confidence}, evidence ${preference.evidenceCount})`,
199
+ );
200
+ }
201
+ }
202
+
203
+ return lines.join("\n");
204
+ }
205
+
206
+ export function formatPaths(details: InspectProjectDetails): string {
207
+ if (details.paths.length === 0) {
208
+ return `No paths found for ${details.project.name}.`;
209
+ }
210
+
211
+ const lines = [
212
+ `Paths for ${details.project.name}`,
213
+ "",
214
+ "| Path | Current | First Seen | Last Updated |",
215
+ "|------|---------|------------|--------------|",
216
+ ];
217
+
218
+ for (const path of details.paths) {
219
+ lines.push(
220
+ `| ${sanitizeCell(path.path)} | ${path.isCurrent ? "yes" : "no"} | ${sanitizeCell(path.firstSeenAt)} | ${sanitizeCell(path.lastUpdated)} |`,
221
+ );
222
+ }
223
+
224
+ return lines.join("\n");
225
+ }