ndomo 0.1.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.
- package/.bun-version +1 -0
- package/.dockerignore +79 -0
- package/.editorconfig +18 -0
- package/.env.example +19 -0
- package/.github/CODEOWNERS +8 -0
- package/.github/ISSUE_TEMPLATE/bug_report.yml +62 -0
- package/.github/ISSUE_TEMPLATE/config.yml +2 -0
- package/.github/ISSUE_TEMPLATE/feature_request.yml +34 -0
- package/.github/dependabot.yml +36 -0
- package/.github/pull_request_template.md +24 -0
- package/.github/release.yml +30 -0
- package/.github/workflows/gitleaks.yml +28 -0
- package/.github/workflows/release-please.yml +27 -0
- package/.github/workflows/smoke.yml +29 -0
- package/.husky/commit-msg +1 -0
- package/CHANGELOG.md +114 -0
- package/Dockerfile +32 -0
- package/README.es.md +174 -0
- package/README.md +187 -0
- package/agents/chronicler.md +98 -0
- package/agents/ci-smith.md +136 -0
- package/agents/craftsman.md +341 -0
- package/agents/deploy-smith.md +138 -0
- package/agents/foreman.md +377 -0
- package/agents/go-smith.md +164 -0
- package/agents/guild.md +188 -0
- package/agents/inspector.md +83 -0
- package/agents/js-smith.md +127 -0
- package/agents/ops-scout.md +173 -0
- package/agents/painter.md +200 -0
- package/agents/python-smith.md +120 -0
- package/agents/ranger.md +307 -0
- package/agents/release-smith.md +165 -0
- package/agents/rust-smith.md +159 -0
- package/agents/sage.md +178 -0
- package/agents/scout.md +144 -0
- package/agents/scribe.md +156 -0
- package/agents/smith.md +201 -0
- package/agents/vue-smith.md +155 -0
- package/agents/warden.md +216 -0
- package/agents/zig-smith.md +156 -0
- package/bin/ndomo-analyses.ts +4 -0
- package/bin/ndomo-status.ts +4 -0
- package/biome.json +57 -0
- package/bun.lock +514 -0
- package/commitlint.config.js +3 -0
- package/config/ndomo.config.json +258 -0
- package/config/ndomo.schema.json +166 -0
- package/docs/agents.md +375 -0
- package/docs/bugs/plan-create-orphan-fk.md +131 -0
- package/docs/bugs/task_create_batch-order-index-collision.md +158 -0
- package/docs/configuration.md +276 -0
- package/docs/database.md +364 -0
- package/docs/features/feature-flexible-builder-v1.md +724 -0
- package/docs/features/feature-flexible-builder-v2.md +882 -0
- package/docs/features/feature-flexible-builder.md +974 -0
- package/docs/http-server.md +244 -0
- package/docs/installation.md +259 -0
- package/docs/integrations.md +129 -0
- package/docs/operations/anti-pattern-sub-agent-verify-2026-06-21.md +32 -0
- package/docs/operations/audit-v1.md +417 -0
- package/docs/operations/audit-v2.md +197 -0
- package/docs/operations/audit-v3.md +306 -0
- package/docs/operations/db-optimize-foundations.md +123 -0
- package/docs/operations/verify-gate-architecture.md +82 -0
- package/docs/workflows.md +448 -0
- package/opencode.json +5 -0
- package/package.json +65 -0
- package/release-please-config.json +11 -0
- package/scripts/dev-bust-cache.sh +164 -0
- package/scripts/install.sh +688 -0
- package/scripts/smoke-e2e.ts +704 -0
- package/scripts/smoke-hot.ts +417 -0
- package/scripts/smoke-http.sh +228 -0
- package/scripts/smoke-v4.ts +256 -0
- package/scripts/smoke-v5.ts +397 -0
- package/scripts/smoke.sh +9 -0
- package/scripts/uninstall.sh +224 -0
- package/skills/api-security-best-practices/SKILL.md +915 -0
- package/skills/bash-scripting/SKILL.md +201 -0
- package/skills/bun/SKILL.md +313 -0
- package/skills/cavecrew/SKILL.md +82 -0
- package/skills/caveman/SKILL.md +74 -0
- package/skills/caveman-review/README.md +33 -0
- package/skills/caveman-review/SKILL.md +55 -0
- package/skills/find-skills/SKILL.md +142 -0
- package/skills/frontend-design/LICENSE.txt +177 -0
- package/skills/frontend-design/SKILL.md +55 -0
- package/skills/golang-patterns/SKILL.md +674 -0
- package/skills/golang-security/SKILL.md +185 -0
- package/skills/golang-security/evals/evals.json +595 -0
- package/skills/golang-security/references/architecture.md +268 -0
- package/skills/golang-security/references/checklist.md +80 -0
- package/skills/golang-security/references/cookies.md +200 -0
- package/skills/golang-security/references/cryptography.md +424 -0
- package/skills/golang-security/references/filesystem.md +285 -0
- package/skills/golang-security/references/injection.md +315 -0
- package/skills/golang-security/references/logging.md +163 -0
- package/skills/golang-security/references/memory-safety.md +241 -0
- package/skills/golang-security/references/network.md +253 -0
- package/skills/golang-security/references/secrets.md +189 -0
- package/skills/golang-security/references/third-party.md +159 -0
- package/skills/golang-security/references/threat-modeling.md +189 -0
- package/skills/golang-testing/SKILL.md +720 -0
- package/skills/grill-me/SKILL.md +7 -0
- package/skills/javascript-testing-patterns/SKILL.md +537 -0
- package/skills/javascript-testing-patterns/references/advanced-testing-patterns.md +513 -0
- package/skills/modern-javascript-patterns/SKILL.md +43 -0
- package/skills/modern-javascript-patterns/references/advanced-patterns.md +487 -0
- package/skills/modern-javascript-patterns/references/details.md +457 -0
- package/skills/python-anti-patterns/SKILL.md +349 -0
- package/skills/python-design-patterns/SKILL.md +85 -0
- package/skills/python-design-patterns/references/details.md +353 -0
- package/skills/python-error-handling/SKILL.md +193 -0
- package/skills/python-error-handling/references/details.md +171 -0
- package/skills/python-testing-patterns/SKILL.md +278 -0
- package/skills/python-testing-patterns/references/advanced-patterns.md +411 -0
- package/skills/python-testing-patterns/references/details.md +349 -0
- package/skills/rust-patterns/SKILL.md +500 -0
- package/skills/rust-testing/SKILL.md +501 -0
- package/skills/security-review/SKILL.md +504 -0
- package/skills/security-review/cloud-infrastructure-security.md +361 -0
- package/skills/vue-best-practices/SKILL.md +154 -0
- package/skills/vue-best-practices/references/animation-class-based-technique.md +254 -0
- package/skills/vue-best-practices/references/animation-state-driven-technique.md +291 -0
- package/skills/vue-best-practices/references/component-async.md +97 -0
- package/skills/vue-best-practices/references/component-data-flow.md +307 -0
- package/skills/vue-best-practices/references/component-fallthrough-attrs.md +174 -0
- package/skills/vue-best-practices/references/component-keep-alive.md +137 -0
- package/skills/vue-best-practices/references/component-slots.md +216 -0
- package/skills/vue-best-practices/references/component-suspense.md +228 -0
- package/skills/vue-best-practices/references/component-teleport.md +108 -0
- package/skills/vue-best-practices/references/component-transition-group.md +128 -0
- package/skills/vue-best-practices/references/component-transition.md +125 -0
- package/skills/vue-best-practices/references/composables.md +290 -0
- package/skills/vue-best-practices/references/directives.md +162 -0
- package/skills/vue-best-practices/references/perf-avoid-component-abstraction-in-lists.md +159 -0
- package/skills/vue-best-practices/references/perf-v-once-v-memo-directives.md +182 -0
- package/skills/vue-best-practices/references/perf-virtualize-large-lists.md +187 -0
- package/skills/vue-best-practices/references/plugins.md +166 -0
- package/skills/vue-best-practices/references/reactivity.md +344 -0
- package/skills/vue-best-practices/references/render-functions.md +201 -0
- package/skills/vue-best-practices/references/sfc.md +310 -0
- package/skills/vue-best-practices/references/state-management.md +135 -0
- package/skills/vue-best-practices/references/updated-hook-performance.md +187 -0
- package/skills/vue-pinia-best-practices/SKILL.md +21 -0
- package/skills/vue-pinia-best-practices/reference/pinia-no-active-pinia-error.md +248 -0
- package/skills/vue-pinia-best-practices/reference/pinia-setup-store-return-all-state.md +227 -0
- package/skills/vue-pinia-best-practices/reference/pinia-store-destructuring-breaks-reactivity.md +193 -0
- package/skills/vue-pinia-best-practices/reference/state-url-for-ephemeral-filters.md +238 -0
- package/skills/vue-pinia-best-practices/reference/state-use-pinia-for-large-apps.md +262 -0
- package/skills/vue-pinia-best-practices/reference/store-method-binding-parentheses.md +191 -0
- package/skills/zig-0.16/SKILL.md +840 -0
- package/skills/zig-0.16/scripts/check-zig-version.sh +21 -0
- package/src/cli/analyses.ts +280 -0
- package/src/cli/index.ts +108 -0
- package/src/cli/serve.ts +192 -0
- package/src/cli/smoke.ts +131 -0
- package/src/cli/status.test.ts +204 -0
- package/src/cli/status.ts +263 -0
- package/src/cli/vacuum.test.ts +82 -0
- package/src/cli/vacuum.ts +96 -0
- package/src/config/schema.test.ts +88 -0
- package/src/config/schema.ts +64 -0
- package/src/db/analyses-migration.test.ts +210 -0
- package/src/db/analyses.test.ts +466 -0
- package/src/db/analyses.ts +375 -0
- package/src/db/auto-checkpoint.ts +131 -0
- package/src/db/client.test.ts +129 -0
- package/src/db/client.ts +55 -0
- package/src/db/fts-escape.ts +20 -0
- package/src/db/incidents.test.ts +201 -0
- package/src/db/incidents.ts +93 -0
- package/src/db/index.ts +86 -0
- package/src/db/migrations-v13.test.ts +141 -0
- package/src/db/migrations-v8.test.ts +301 -0
- package/src/db/migrations.ts +147 -0
- package/src/db/plan-archive.test.ts +180 -0
- package/src/db/plan-archive.ts +274 -0
- package/src/db/plan-create.test.ts +276 -0
- package/src/db/plan-create.ts +78 -0
- package/src/db/plan-files.test.ts +289 -0
- package/src/db/plan-update-status.ts +287 -0
- package/src/db/plans.test.ts +490 -0
- package/src/db/plans.ts +534 -0
- package/src/db/resolve-project-dir.test.ts +143 -0
- package/src/db/resolve-project-dir.ts +75 -0
- package/src/db/rollbacks.test.ts +150 -0
- package/src/db/rollbacks.ts +67 -0
- package/src/db/schema.ts +907 -0
- package/src/db/sessions.test.ts +80 -0
- package/src/db/sessions.ts +135 -0
- package/src/db/shutdown.test.ts +147 -0
- package/src/db/shutdown.ts +45 -0
- package/src/db/tasks.test.ts +921 -0
- package/src/db/tasks.ts +747 -0
- package/src/db/types.ts +619 -0
- package/src/http/__tests__/auth.test.ts +196 -0
- package/src/http/__tests__/routes.test.ts +465 -0
- package/src/http/__tests__/sse.test.ts +317 -0
- package/src/http/auth.ts +72 -0
- package/src/http/middleware/cors.ts +53 -0
- package/src/http/middleware/security-headers.ts +21 -0
- package/src/http/routes/events.ts +112 -0
- package/src/http/routes/health.ts +51 -0
- package/src/http/routes/plans.ts +66 -0
- package/src/http/routes/sessions.ts +50 -0
- package/src/http/routes/tasks.ts +60 -0
- package/src/http/server.ts +95 -0
- package/src/http/sse.ts +116 -0
- package/src/index.ts +37 -0
- package/src/lib.ts +65 -0
- package/src/mem/scoped.ts +65 -0
- package/src/orchestrator/background.test.ts +268 -0
- package/src/orchestrator/background.ts +293 -0
- package/src/orchestrator/memory-hook.ts +182 -0
- package/src/orchestrator/reconciler.ts +123 -0
- package/src/orchestrator/scheduler.test.ts +300 -0
- package/src/orchestrator/scheduler.ts +243 -0
- package/src/plugin.test.ts +2574 -0
- package/src/plugin.ts +1690 -0
- package/src/sdk/client.ts +66 -0
- package/src/worktrees/manager.ts +236 -0
- package/src/worktrees/state.ts +87 -0
- package/tests/integration/ranger-flow.test.ts +257 -0
- package/tools/analysis_archive.ts +28 -0
- package/tools/analysis_create.ts +55 -0
- package/tools/analysis_get.ts +33 -0
- package/tools/analysis_link_plan.ts +44 -0
- package/tools/analysis_list.ts +48 -0
- package/tools/analysis_search.ts +36 -0
- package/tools/analysis_update.ts +44 -0
- package/tools/plan_approve.ts +31 -0
- package/tools/plan_create.ts +58 -0
- package/tools/plan_get.ts +40 -0
- package/tools/plan_list.ts +37 -0
- package/tools/plan_search.ts +34 -0
- package/tools/plan_update_status.ts +71 -0
- package/tools/session_checkpoint.ts +31 -0
- package/tools/session_end.ts +26 -0
- package/tools/session_start.ts +43 -0
- package/tools/task_create_batch.ts +70 -0
- package/tools/task_list.ts +35 -0
- package/tools/task_next_for_agent.ts +30 -0
- package/tools/task_search.ts +34 -0
- package/tools/task_update_status.ts +37 -0
- package/tsconfig.json +31 -0
package/src/db/types.ts
ADDED
|
@@ -0,0 +1,619 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ndomo DB — Type definitions for plans, tasks, and sessions.
|
|
3
|
+
*
|
|
4
|
+
* All interfaces use camelCase. Mapper functions convert snake_case
|
|
5
|
+
* SQLite rows into typed objects using nullish coalescing for nullable
|
|
6
|
+
* fields and JSON.parse for serialized columns.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export type PlanStatus = "draft" | "approved" | "executing" | "completed" | "failed" | "abandoned";
|
|
10
|
+
|
|
11
|
+
export type TaskStatus = "pending" | "running" | "done" | "failed" | "blocked";
|
|
12
|
+
|
|
13
|
+
export type PlanCategory = "feature" | "refactor" | "bugfix" | "docs" | "infra";
|
|
14
|
+
|
|
15
|
+
export type SessionOutcome = "success" | "partial" | "failed" | "abandoned";
|
|
16
|
+
|
|
17
|
+
export interface PlanMetadata {
|
|
18
|
+
category?: PlanCategory;
|
|
19
|
+
externalRefs?: {
|
|
20
|
+
githubPrUrl?: string;
|
|
21
|
+
jiraTicket?: string;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface TaskMetadata {
|
|
26
|
+
reviewedBy?: string;
|
|
27
|
+
tokensUsed?: number;
|
|
28
|
+
durationMs?: number;
|
|
29
|
+
artifacts?: string[];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface SessionMetadata {
|
|
33
|
+
outcome?: SessionOutcome;
|
|
34
|
+
metrics?: {
|
|
35
|
+
totalTokens?: number;
|
|
36
|
+
totalTasks?: number;
|
|
37
|
+
totalDurationMs?: number;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface Plan {
|
|
42
|
+
id: string;
|
|
43
|
+
slug: string;
|
|
44
|
+
title: string;
|
|
45
|
+
status: PlanStatus;
|
|
46
|
+
priority: number;
|
|
47
|
+
createdAt: number;
|
|
48
|
+
updatedAt: number;
|
|
49
|
+
approvedAt: number | null;
|
|
50
|
+
completedAt: number | null;
|
|
51
|
+
/** @see sessions.id — foreign key constraint enforced at app level (v3 Fix #1) */
|
|
52
|
+
sessionId: string | null;
|
|
53
|
+
overview: string;
|
|
54
|
+
approach: string | null;
|
|
55
|
+
complexity: number;
|
|
56
|
+
createdBy: string;
|
|
57
|
+
updatedBy: string;
|
|
58
|
+
sourceSessionId: string | null;
|
|
59
|
+
sourceMessageId: string | null;
|
|
60
|
+
category: PlanCategory | null;
|
|
61
|
+
metadata: PlanMetadata;
|
|
62
|
+
/** v5: soft delete timestamp (null = active, number = archived epoch ms) */
|
|
63
|
+
archivedAt: number | null;
|
|
64
|
+
/** v6: write-once — JSON snapshot of plan data at creation time */
|
|
65
|
+
originalPlanData?: string | null;
|
|
66
|
+
/** v8: agent that created this plan (distinct from createdBy which is audit user) */
|
|
67
|
+
createdByAgent?: string | null;
|
|
68
|
+
/** v8: agent that last executed work on this plan */
|
|
69
|
+
executedByAgent?: string | null;
|
|
70
|
+
/** v8: session that last executed work on this plan (FK sessions, app-level) */
|
|
71
|
+
executedBySession?: string | null;
|
|
72
|
+
/** v7: files associated with this plan (from plan_files join table) */
|
|
73
|
+
files?: Array<{ filePath: string; role: string }>;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export interface PlanTask {
|
|
77
|
+
id: string;
|
|
78
|
+
planId: string;
|
|
79
|
+
orderIndex: number;
|
|
80
|
+
description: string;
|
|
81
|
+
agent: string;
|
|
82
|
+
files: string[];
|
|
83
|
+
complexity: number;
|
|
84
|
+
status: TaskStatus;
|
|
85
|
+
startedAt: number | null;
|
|
86
|
+
completedAt: number | null;
|
|
87
|
+
result: string | null;
|
|
88
|
+
error: string | null;
|
|
89
|
+
dependencies: string[];
|
|
90
|
+
createdBy: string;
|
|
91
|
+
updatedBy: string;
|
|
92
|
+
sourceSessionId: string | null;
|
|
93
|
+
sourceMessageId: string | null;
|
|
94
|
+
reviewedBy: string | null;
|
|
95
|
+
tokensUsed: number | null;
|
|
96
|
+
durationMs: number | null;
|
|
97
|
+
artifacts: string[];
|
|
98
|
+
metadata: TaskMetadata;
|
|
99
|
+
/** v5: soft delete timestamp (null = active, number = archived epoch ms) */
|
|
100
|
+
archivedAt: number | null;
|
|
101
|
+
/** v6: write-once — JSON snapshot of task data at creation time */
|
|
102
|
+
originalPlanData?: string | null;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export interface Session {
|
|
106
|
+
id: string;
|
|
107
|
+
startedAt: number;
|
|
108
|
+
endedAt: number | null;
|
|
109
|
+
lastCheckpoint: number | null;
|
|
110
|
+
planId: string | null;
|
|
111
|
+
goal: string;
|
|
112
|
+
state: Record<string, unknown>;
|
|
113
|
+
agentHistory: Array<{
|
|
114
|
+
agent: string;
|
|
115
|
+
taskId: string | null;
|
|
116
|
+
startedAt: number;
|
|
117
|
+
endedAt: number | null;
|
|
118
|
+
}>;
|
|
119
|
+
keyDecisions: string | null;
|
|
120
|
+
createdBy: string;
|
|
121
|
+
sourceMessageId: string | null;
|
|
122
|
+
parentSessionId: string | null;
|
|
123
|
+
outcome: SessionOutcome | null;
|
|
124
|
+
metadata: SessionMetadata;
|
|
125
|
+
/** v5: soft delete timestamp (null = active, number = archived epoch ms) */
|
|
126
|
+
archivedAt: number | null;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// ─── Row mappers ─────────────────────────────────────────────────────────────
|
|
130
|
+
|
|
131
|
+
interface PlanRow {
|
|
132
|
+
id: string;
|
|
133
|
+
slug: string;
|
|
134
|
+
title: string;
|
|
135
|
+
status: string;
|
|
136
|
+
priority: number;
|
|
137
|
+
created_at: number;
|
|
138
|
+
updated_at: number;
|
|
139
|
+
approved_at: number | null;
|
|
140
|
+
completed_at: number | null;
|
|
141
|
+
session_id: string | null;
|
|
142
|
+
overview: string;
|
|
143
|
+
approach: string | null;
|
|
144
|
+
complexity: number;
|
|
145
|
+
metadata: string | null;
|
|
146
|
+
created_by: string;
|
|
147
|
+
updated_by: string;
|
|
148
|
+
source_session_id: string | null;
|
|
149
|
+
source_message_id: string | null;
|
|
150
|
+
category: string | null;
|
|
151
|
+
archived_at: number | null;
|
|
152
|
+
original_plan_data: string | null;
|
|
153
|
+
created_by_agent: string | null;
|
|
154
|
+
executed_by_agent: string | null;
|
|
155
|
+
executed_by_session: string | null;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
interface TaskRow {
|
|
159
|
+
id: string;
|
|
160
|
+
plan_id: string;
|
|
161
|
+
order_index: number;
|
|
162
|
+
description: string;
|
|
163
|
+
agent: string;
|
|
164
|
+
files: string;
|
|
165
|
+
complexity: number;
|
|
166
|
+
status: string;
|
|
167
|
+
started_at: number | null;
|
|
168
|
+
completed_at: number | null;
|
|
169
|
+
result: string | null;
|
|
170
|
+
error: string | null;
|
|
171
|
+
dependencies: string;
|
|
172
|
+
metadata: string | null;
|
|
173
|
+
created_by: string;
|
|
174
|
+
updated_by: string;
|
|
175
|
+
source_session_id: string | null;
|
|
176
|
+
source_message_id: string | null;
|
|
177
|
+
reviewed_by: string | null;
|
|
178
|
+
tokens_used: number | null;
|
|
179
|
+
duration_ms: number | null;
|
|
180
|
+
artifacts: string;
|
|
181
|
+
archived_at: number | null;
|
|
182
|
+
original_plan_data: string | null;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
interface SessionRow {
|
|
186
|
+
id: string;
|
|
187
|
+
started_at: number;
|
|
188
|
+
ended_at: number | null;
|
|
189
|
+
last_checkpoint: number | null;
|
|
190
|
+
plan_id: string | null;
|
|
191
|
+
goal: string;
|
|
192
|
+
state: string;
|
|
193
|
+
agent_history: string;
|
|
194
|
+
key_decisions: string | null;
|
|
195
|
+
metadata: string | null;
|
|
196
|
+
created_by: string;
|
|
197
|
+
source_message_id: string | null;
|
|
198
|
+
parent_session_id: string | null;
|
|
199
|
+
outcome: string | null;
|
|
200
|
+
archived_at: number | null;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export function planFromRow(row: unknown): Plan {
|
|
204
|
+
const r = row as PlanRow;
|
|
205
|
+
return {
|
|
206
|
+
id: r.id,
|
|
207
|
+
slug: r.slug,
|
|
208
|
+
title: r.title,
|
|
209
|
+
status: r.status as PlanStatus,
|
|
210
|
+
priority: r.priority,
|
|
211
|
+
createdAt: r.created_at,
|
|
212
|
+
updatedAt: r.updated_at,
|
|
213
|
+
approvedAt: r.approved_at ?? null,
|
|
214
|
+
completedAt: r.completed_at ?? null,
|
|
215
|
+
sessionId: r.session_id ?? null,
|
|
216
|
+
overview: r.overview,
|
|
217
|
+
approach: r.approach ?? null,
|
|
218
|
+
complexity: r.complexity,
|
|
219
|
+
createdBy: r.created_by ?? "unknown",
|
|
220
|
+
updatedBy: r.updated_by ?? "unknown",
|
|
221
|
+
sourceSessionId: r.source_session_id ?? null,
|
|
222
|
+
sourceMessageId: r.source_message_id ?? null,
|
|
223
|
+
category: (r.category ?? null) as PlanCategory | null,
|
|
224
|
+
metadata: (r.metadata != null ? JSON.parse(r.metadata) : {}) as PlanMetadata,
|
|
225
|
+
archivedAt: r.archived_at ?? null,
|
|
226
|
+
originalPlanData: r.original_plan_data ?? null,
|
|
227
|
+
createdByAgent: r.created_by_agent ?? null,
|
|
228
|
+
executedByAgent: r.executed_by_agent ?? null,
|
|
229
|
+
executedBySession: r.executed_by_session ?? null,
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
interface PlanFileRow {
|
|
234
|
+
file_path: string;
|
|
235
|
+
role: string;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
export function planWithFilesFromRow(planRow: unknown, fileRows: unknown[]): Plan {
|
|
239
|
+
const plan = planFromRow(planRow);
|
|
240
|
+
const files = (fileRows as PlanFileRow[]).map((f) => ({
|
|
241
|
+
filePath: f.file_path,
|
|
242
|
+
role: f.role,
|
|
243
|
+
}));
|
|
244
|
+
return { ...plan, files };
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
export function taskFromRow(row: unknown): PlanTask {
|
|
248
|
+
const r = row as TaskRow;
|
|
249
|
+
return {
|
|
250
|
+
id: r.id,
|
|
251
|
+
planId: r.plan_id,
|
|
252
|
+
orderIndex: r.order_index,
|
|
253
|
+
description: r.description,
|
|
254
|
+
agent: r.agent,
|
|
255
|
+
files: (JSON.parse(r.files) as string[]) ?? [],
|
|
256
|
+
complexity: r.complexity,
|
|
257
|
+
status: r.status as TaskStatus,
|
|
258
|
+
startedAt: r.started_at ?? null,
|
|
259
|
+
completedAt: r.completed_at ?? null,
|
|
260
|
+
result: r.result ?? null,
|
|
261
|
+
error: r.error ?? null,
|
|
262
|
+
dependencies: (JSON.parse(r.dependencies) as string[]) ?? [],
|
|
263
|
+
createdBy: r.created_by ?? "unknown",
|
|
264
|
+
updatedBy: r.updated_by ?? "unknown",
|
|
265
|
+
sourceSessionId: r.source_session_id ?? null,
|
|
266
|
+
sourceMessageId: r.source_message_id ?? null,
|
|
267
|
+
reviewedBy: r.reviewed_by ?? null,
|
|
268
|
+
tokensUsed: r.tokens_used ?? null,
|
|
269
|
+
durationMs: r.duration_ms ?? null,
|
|
270
|
+
artifacts: (JSON.parse(r.artifacts) as string[]) ?? [],
|
|
271
|
+
metadata: (r.metadata != null ? JSON.parse(r.metadata) : {}) as TaskMetadata,
|
|
272
|
+
archivedAt: r.archived_at ?? null,
|
|
273
|
+
originalPlanData: r.original_plan_data ?? null,
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
export function sessionFromRow(row: unknown): Session {
|
|
278
|
+
const r = row as SessionRow;
|
|
279
|
+
return {
|
|
280
|
+
id: r.id,
|
|
281
|
+
startedAt: r.started_at,
|
|
282
|
+
endedAt: r.ended_at ?? null,
|
|
283
|
+
lastCheckpoint: r.last_checkpoint ?? null,
|
|
284
|
+
planId: r.plan_id ?? null,
|
|
285
|
+
goal: r.goal,
|
|
286
|
+
state: (JSON.parse(r.state) as Record<string, unknown>) ?? {},
|
|
287
|
+
agentHistory: (JSON.parse(r.agent_history) as Session["agentHistory"]) ?? [],
|
|
288
|
+
keyDecisions: r.key_decisions ?? null,
|
|
289
|
+
createdBy: r.created_by ?? "unknown",
|
|
290
|
+
sourceMessageId: r.source_message_id ?? null,
|
|
291
|
+
parentSessionId: r.parent_session_id ?? null,
|
|
292
|
+
outcome: (r.outcome ?? null) as SessionOutcome | null,
|
|
293
|
+
metadata: (r.metadata != null ? JSON.parse(r.metadata) : {}) as SessionMetadata,
|
|
294
|
+
archivedAt: r.archived_at ?? null,
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// ── v13: Ops types ──────────────────────────────────────────────
|
|
299
|
+
|
|
300
|
+
export type EnvironmentSlug = string
|
|
301
|
+
export type ReleaseVersion = string
|
|
302
|
+
|
|
303
|
+
export type DeploymentStatus = "planned" | "in_progress" | "succeeded" | "failed" | "rolled_back"
|
|
304
|
+
export type IncidentSeverity = "sev1" | "sev2" | "sev3" | "sev4"
|
|
305
|
+
export type IncidentStatus = "open" | "triaging" | "mitigated" | "resolved" | "postmortem"
|
|
306
|
+
export type RollbackStatus = "planned" | "approved" | "dry_run" | "executing" | "success" | "failed" | "cancelled"
|
|
307
|
+
|
|
308
|
+
export interface Environment {
|
|
309
|
+
id: string
|
|
310
|
+
name: string
|
|
311
|
+
slug: string
|
|
312
|
+
description: string | null
|
|
313
|
+
metadata: Record<string, unknown> | null
|
|
314
|
+
createdAt: number
|
|
315
|
+
updatedAt: number
|
|
316
|
+
archivedAt: number | null
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
export interface Release {
|
|
320
|
+
id: string
|
|
321
|
+
version: string
|
|
322
|
+
title: string
|
|
323
|
+
notes: string | null
|
|
324
|
+
metadata: Record<string, unknown> | null
|
|
325
|
+
createdAt: number
|
|
326
|
+
archivedAt: number | null
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
export interface Deployment {
|
|
330
|
+
id: string
|
|
331
|
+
releaseId: string
|
|
332
|
+
environmentId: string
|
|
333
|
+
status: DeploymentStatus
|
|
334
|
+
deployedAt: number | null
|
|
335
|
+
createdAt: number
|
|
336
|
+
metadata: Record<string, unknown> | null
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
export interface Incident {
|
|
340
|
+
id: string
|
|
341
|
+
title: string
|
|
342
|
+
severity: IncidentSeverity
|
|
343
|
+
status: IncidentStatus
|
|
344
|
+
summary: string | null
|
|
345
|
+
triggeredByDeploymentId: string | null
|
|
346
|
+
createdAt: number
|
|
347
|
+
updatedAt: number
|
|
348
|
+
resolvedAt: number | null
|
|
349
|
+
metadata: Record<string, unknown> | null
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
export interface RollbackExecution {
|
|
353
|
+
id: string
|
|
354
|
+
deploymentId: string
|
|
355
|
+
incidentId: string | null
|
|
356
|
+
newDeploymentId: string | null
|
|
357
|
+
status: RollbackStatus
|
|
358
|
+
plan: string
|
|
359
|
+
executedAt: number | null
|
|
360
|
+
createdAt: number
|
|
361
|
+
metadata: Record<string, unknown> | null
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// Insert types (for createIncident/recordRollback helpers)
|
|
365
|
+
export interface InsertIncident {
|
|
366
|
+
title: string
|
|
367
|
+
severity: IncidentSeverity
|
|
368
|
+
summary?: string
|
|
369
|
+
triggeredByDeploymentId?: string
|
|
370
|
+
metadata?: Record<string, unknown>
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
export interface InsertRollback {
|
|
374
|
+
deploymentId: string
|
|
375
|
+
incidentId?: string
|
|
376
|
+
newDeploymentId?: string
|
|
377
|
+
status?: RollbackStatus
|
|
378
|
+
plan: string
|
|
379
|
+
metadata?: Record<string, unknown>
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
// Row types (internal, for mappers)
|
|
383
|
+
interface EnvironmentRow {
|
|
384
|
+
id: string
|
|
385
|
+
name: string
|
|
386
|
+
slug: string
|
|
387
|
+
description: string | null
|
|
388
|
+
metadata: string | null
|
|
389
|
+
created_at: number
|
|
390
|
+
updated_at: number
|
|
391
|
+
archived_at: number | null
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
interface ReleaseRow {
|
|
395
|
+
id: string
|
|
396
|
+
version: string
|
|
397
|
+
title: string
|
|
398
|
+
notes: string | null
|
|
399
|
+
metadata: string | null
|
|
400
|
+
created_at: number
|
|
401
|
+
archived_at: number | null
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
interface DeploymentRow {
|
|
405
|
+
id: string
|
|
406
|
+
release_id: string
|
|
407
|
+
environment_id: string
|
|
408
|
+
status: string
|
|
409
|
+
deployed_at: number | null
|
|
410
|
+
created_at: number
|
|
411
|
+
metadata: string | null
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
interface IncidentRow {
|
|
415
|
+
id: string
|
|
416
|
+
title: string
|
|
417
|
+
severity: string
|
|
418
|
+
status: string
|
|
419
|
+
summary: string | null
|
|
420
|
+
triggered_by_deployment_id: string | null
|
|
421
|
+
created_at: number
|
|
422
|
+
updated_at: number
|
|
423
|
+
resolved_at: number | null
|
|
424
|
+
metadata: string | null
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
interface RollbackRow {
|
|
428
|
+
id: string
|
|
429
|
+
deployment_id: string
|
|
430
|
+
incident_id: string | null
|
|
431
|
+
new_deployment_id: string | null
|
|
432
|
+
status: string
|
|
433
|
+
plan: string
|
|
434
|
+
executed_at: number | null
|
|
435
|
+
created_at: number
|
|
436
|
+
metadata: string | null
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
export function environmentFromRow(row: unknown): Environment {
|
|
440
|
+
const r = row as EnvironmentRow
|
|
441
|
+
return {
|
|
442
|
+
id: r.id,
|
|
443
|
+
name: r.name,
|
|
444
|
+
slug: r.slug,
|
|
445
|
+
description: r.description ?? null,
|
|
446
|
+
metadata: r.metadata != null ? JSON.parse(r.metadata) : null,
|
|
447
|
+
createdAt: r.created_at,
|
|
448
|
+
updatedAt: r.updated_at,
|
|
449
|
+
archivedAt: r.archived_at ?? null,
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
export function releaseFromRow(row: unknown): Release {
|
|
454
|
+
const r = row as ReleaseRow
|
|
455
|
+
return {
|
|
456
|
+
id: r.id,
|
|
457
|
+
version: r.version,
|
|
458
|
+
title: r.title,
|
|
459
|
+
notes: r.notes ?? null,
|
|
460
|
+
metadata: r.metadata != null ? JSON.parse(r.metadata) : null,
|
|
461
|
+
createdAt: r.created_at,
|
|
462
|
+
archivedAt: r.archived_at ?? null,
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
export function deploymentFromRow(row: unknown): Deployment {
|
|
467
|
+
const r = row as DeploymentRow
|
|
468
|
+
return {
|
|
469
|
+
id: r.id,
|
|
470
|
+
releaseId: r.release_id,
|
|
471
|
+
environmentId: r.environment_id,
|
|
472
|
+
status: r.status as DeploymentStatus,
|
|
473
|
+
deployedAt: r.deployed_at ?? null,
|
|
474
|
+
createdAt: r.created_at,
|
|
475
|
+
metadata: r.metadata != null ? JSON.parse(r.metadata) : null,
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
export function incidentFromRow(row: unknown): Incident {
|
|
480
|
+
const r = row as IncidentRow
|
|
481
|
+
return {
|
|
482
|
+
id: r.id,
|
|
483
|
+
title: r.title,
|
|
484
|
+
severity: r.severity as IncidentSeverity,
|
|
485
|
+
status: r.status as IncidentStatus,
|
|
486
|
+
summary: r.summary ?? null,
|
|
487
|
+
triggeredByDeploymentId: r.triggered_by_deployment_id ?? null,
|
|
488
|
+
createdAt: r.created_at,
|
|
489
|
+
updatedAt: r.updated_at,
|
|
490
|
+
resolvedAt: r.resolved_at ?? null,
|
|
491
|
+
metadata: r.metadata != null ? JSON.parse(r.metadata) : null,
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
export function rollbackFromRow(row: unknown): RollbackExecution {
|
|
496
|
+
const r = row as RollbackRow
|
|
497
|
+
return {
|
|
498
|
+
id: r.id,
|
|
499
|
+
deploymentId: r.deployment_id,
|
|
500
|
+
incidentId: r.incident_id ?? null,
|
|
501
|
+
newDeploymentId: r.new_deployment_id ?? null,
|
|
502
|
+
status: r.status as RollbackStatus,
|
|
503
|
+
plan: r.plan,
|
|
504
|
+
executedAt: r.executed_at ?? null,
|
|
505
|
+
createdAt: r.created_at,
|
|
506
|
+
metadata: r.metadata != null ? JSON.parse(r.metadata) : null,
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// ── v14: Analyses ───────────────────────────────────────────────
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* Severity classification for analysis findings.
|
|
514
|
+
* Mirrors the existing observed convention in stored findings_json.
|
|
515
|
+
*/
|
|
516
|
+
export type FindingSeverity = "high" | "medium" | "low" | "info";
|
|
517
|
+
|
|
518
|
+
/**
|
|
519
|
+
* Agent boundary contract for analysis findings (v15):
|
|
520
|
+
*
|
|
521
|
+
* - `observation` (REQUIRED): a factual, descriptive statement. Every
|
|
522
|
+
* agent — ranger, foreman, craftsman, smiths — MAY emit observation.
|
|
523
|
+
* Observations do not prescribe action; they describe what exists.
|
|
524
|
+
*
|
|
525
|
+
* - `proposedAction` (OPTIONAL): a prescriptive recommendation only
|
|
526
|
+
* decision-capable agents may emit. Concretely:
|
|
527
|
+
* • ranger is EXCLUDED. Validated at write time by
|
|
528
|
+
* `validateAnalysisFindings()` in src/db/analyses.ts.
|
|
529
|
+
* • foreman, craftsman, warden, smiths, sage, etc. MAY emit it
|
|
530
|
+
* when they have explicit decision/architectural authority.
|
|
531
|
+
*
|
|
532
|
+
* The boundary enforces ranger's "observation-only" role and keeps
|
|
533
|
+
* prescriptive planning in the hands of decision-capable agents.
|
|
534
|
+
*/
|
|
535
|
+
export interface Finding {
|
|
536
|
+
severity: FindingSeverity;
|
|
537
|
+
/** Optional file:line or code location the finding refers to. */
|
|
538
|
+
location?: string;
|
|
539
|
+
/** Factual statement. Required for all agents. */
|
|
540
|
+
observation: string;
|
|
541
|
+
/**
|
|
542
|
+
* Prescriptive recommendation. OPTIONAL — and FORBIDDEN when agent === 'ranger'.
|
|
543
|
+
* See agent boundary contract above.
|
|
544
|
+
*/
|
|
545
|
+
proposedAction?: string;
|
|
546
|
+
/** Optional effort estimate (e.g. 'small', 'medium', 'large'). */
|
|
547
|
+
effort?: string;
|
|
548
|
+
/** Optional impact estimate (e.g. 'low', 'medium', 'high'). */
|
|
549
|
+
impact?: string;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
/**
|
|
553
|
+
* Analysis row. `findingsJson` is the serialized JSON array of {@link Finding}
|
|
554
|
+
* entries stored in the analyses table (TEXT column). The DB layer keeps it
|
|
555
|
+
* as a string for query/index flexibility; consumers parse on read.
|
|
556
|
+
*/
|
|
557
|
+
export interface Analysis {
|
|
558
|
+
id: string;
|
|
559
|
+
slug: string;
|
|
560
|
+
title: string;
|
|
561
|
+
projectPath: string;
|
|
562
|
+
summary: string;
|
|
563
|
+
/** JSON array of {@link Finding}. Parse with JSON.parse(findingsJson) before use. */
|
|
564
|
+
findingsJson: string;
|
|
565
|
+
sourcePlanId: string | null;
|
|
566
|
+
agent: string;
|
|
567
|
+
sessionId: string | null;
|
|
568
|
+
createdBy: string | null;
|
|
569
|
+
createdAt: string;
|
|
570
|
+
updatedAt: string;
|
|
571
|
+
archivedAt: string | null;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
export interface InsertAnalysis {
|
|
575
|
+
slug: string;
|
|
576
|
+
title: string;
|
|
577
|
+
projectPath: string;
|
|
578
|
+
summary?: string;
|
|
579
|
+
findingsJson?: string;
|
|
580
|
+
sourcePlanId?: string | null;
|
|
581
|
+
agent?: string;
|
|
582
|
+
sessionId?: string | null;
|
|
583
|
+
createdBy?: string | null;
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
export interface AnalysisRow {
|
|
587
|
+
id: string;
|
|
588
|
+
slug: string;
|
|
589
|
+
title: string;
|
|
590
|
+
project_path: string;
|
|
591
|
+
summary: string;
|
|
592
|
+
findings_json: string;
|
|
593
|
+
source_plan_id: string | null;
|
|
594
|
+
agent: string;
|
|
595
|
+
session_id: string | null;
|
|
596
|
+
created_by: string | null;
|
|
597
|
+
created_at: string;
|
|
598
|
+
updated_at: string;
|
|
599
|
+
archived_at: string | null;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
export function analysisFromRow(row: unknown): Analysis {
|
|
603
|
+
const r = row as AnalysisRow;
|
|
604
|
+
return {
|
|
605
|
+
id: r.id,
|
|
606
|
+
slug: r.slug,
|
|
607
|
+
title: r.title,
|
|
608
|
+
projectPath: r.project_path,
|
|
609
|
+
summary: r.summary,
|
|
610
|
+
findingsJson: r.findings_json,
|
|
611
|
+
sourcePlanId: r.source_plan_id ?? null,
|
|
612
|
+
agent: r.agent,
|
|
613
|
+
sessionId: r.session_id ?? null,
|
|
614
|
+
createdBy: r.created_by ?? null,
|
|
615
|
+
createdAt: r.created_at,
|
|
616
|
+
updatedAt: r.updated_at,
|
|
617
|
+
archivedAt: r.archived_at ?? null,
|
|
618
|
+
};
|
|
619
|
+
}
|