@mclean-capital/neura 3.4.1 → 3.5.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/README.md +8 -0
- package/core/server.bundled.mjs +2582 -1145
- package/core/server.bundled.mjs.map +4 -4
- package/core/version.txt +1 -1
- package/dist/commands/skill.d.ts +26 -0
- package/dist/commands/skill.d.ts.map +1 -0
- package/dist/commands/skill.js +111 -0
- package/dist/commands/skill.js.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/stores/index.js +171 -11
- package/stores/index.js.map +2 -2
- package/stores/mappers.d.ts +27 -3
- package/stores/mappers.d.ts.map +1 -1
- package/stores/mappers.js +23 -0
- package/stores/mappers.js.map +1 -1
- package/stores/migrations.d.ts.map +1 -1
- package/stores/migrations.js +106 -1
- package/stores/migrations.js.map +1 -1
- package/stores/migrations.test.d.ts +14 -0
- package/stores/migrations.test.d.ts.map +1 -0
- package/stores/migrations.test.js +164 -0
- package/stores/migrations.test.js.map +1 -0
- package/stores/pglite-store.d.ts +5 -7
- package/stores/pglite-store.d.ts.map +1 -1
- package/stores/pglite-store.js +2 -2
- package/stores/pglite-store.js.map +1 -1
- package/stores/pglite-store.test.js +110 -0
- package/stores/pglite-store.test.js.map +1 -1
- package/stores/task-comment-queries.d.ts +55 -0
- package/stores/task-comment-queries.d.ts.map +1 -0
- package/stores/task-comment-queries.js +98 -0
- package/stores/task-comment-queries.js.map +1 -0
- package/stores/task-comment-queries.test.d.ts +8 -0
- package/stores/task-comment-queries.test.d.ts.map +1 -0
- package/stores/task-comment-queries.test.js +321 -0
- package/stores/task-comment-queries.test.js.map +1 -0
- package/stores/work-item-queries.d.ts +47 -2
- package/stores/work-item-queries.d.ts.map +1 -1
- package/stores/work-item-queries.js +79 -6
- package/stores/work-item-queries.js.map +1 -1
package/core/version.txt
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
3.
|
|
1
|
+
3.5.0
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
interface Diagnostic {
|
|
2
|
+
type: 'warning' | 'error';
|
|
3
|
+
message: string;
|
|
4
|
+
path?: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Validate a skill or directory of skills against the agentskills.io spec.
|
|
8
|
+
*
|
|
9
|
+
* Delegates core spec validation (name / description / character rules /
|
|
10
|
+
* parent-dir match / frontmatter parse) to pi-coding-agent's loader, then
|
|
11
|
+
* layers on Neura-specific checks for `license` and `compatibility` that
|
|
12
|
+
* pi does not inspect.
|
|
13
|
+
*
|
|
14
|
+
* Any diagnostic — pi's warnings or Neura's — causes a non-zero exit.
|
|
15
|
+
* Designed for skill authors who want a pre-commit / CI check that their
|
|
16
|
+
* SKILL.md will load cleanly in Neura.
|
|
17
|
+
*/
|
|
18
|
+
export declare function skillValidateCommand(pathArg: string): void;
|
|
19
|
+
declare function checkLicense(skillName: string, filePath: string, raw: unknown): Diagnostic[];
|
|
20
|
+
declare function checkCompatibility(skillName: string, filePath: string, raw: unknown): Diagnostic[];
|
|
21
|
+
export declare const __test__: {
|
|
22
|
+
checkLicense: typeof checkLicense;
|
|
23
|
+
checkCompatibility: typeof checkCompatibility;
|
|
24
|
+
};
|
|
25
|
+
export {};
|
|
26
|
+
//# sourceMappingURL=skill.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill.d.ts","sourceRoot":"","sources":["../../src/commands/skill.ts"],"names":[],"mappings":"AAOA,UAAU,UAAU;IAClB,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CA8D1D;AAED,iBAAS,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,UAAU,EAAE,CAYrF;AAED,iBAAS,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,UAAU,EAAE,CAqB3F;AAED,eAAO,MAAM,QAAQ;;;CAAuC,CAAC"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { loadSkills, parseFrontmatter } from '@mariozechner/pi-coding-agent';
|
|
5
|
+
const COMPATIBILITY_MAX_LENGTH = 500;
|
|
6
|
+
/**
|
|
7
|
+
* Validate a skill or directory of skills against the agentskills.io spec.
|
|
8
|
+
*
|
|
9
|
+
* Delegates core spec validation (name / description / character rules /
|
|
10
|
+
* parent-dir match / frontmatter parse) to pi-coding-agent's loader, then
|
|
11
|
+
* layers on Neura-specific checks for `license` and `compatibility` that
|
|
12
|
+
* pi does not inspect.
|
|
13
|
+
*
|
|
14
|
+
* Any diagnostic — pi's warnings or Neura's — causes a non-zero exit.
|
|
15
|
+
* Designed for skill authors who want a pre-commit / CI check that their
|
|
16
|
+
* SKILL.md will load cleanly in Neura.
|
|
17
|
+
*/
|
|
18
|
+
export function skillValidateCommand(pathArg) {
|
|
19
|
+
const absPath = resolve(pathArg);
|
|
20
|
+
const result = loadSkills({
|
|
21
|
+
skillPaths: [absPath],
|
|
22
|
+
includeDefaults: false,
|
|
23
|
+
});
|
|
24
|
+
const diagnostics = result.diagnostics.map((d) => ({
|
|
25
|
+
type: d.type === 'error' ? 'error' : 'warning',
|
|
26
|
+
message: d.message,
|
|
27
|
+
path: d.path,
|
|
28
|
+
}));
|
|
29
|
+
for (const skill of result.skills) {
|
|
30
|
+
try {
|
|
31
|
+
const raw = readFileSync(skill.filePath, 'utf8');
|
|
32
|
+
const { frontmatter } = parseFrontmatter(raw);
|
|
33
|
+
diagnostics.push(...checkLicense(skill.name, skill.filePath, frontmatter.license));
|
|
34
|
+
diagnostics.push(...checkCompatibility(skill.name, skill.filePath, frontmatter.compatibility));
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
diagnostics.push({
|
|
38
|
+
type: 'error',
|
|
39
|
+
message: `Failed to re-parse frontmatter: ${String(err)}`,
|
|
40
|
+
path: skill.filePath,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
console.log(`${result.skills.length} skill(s) found at ${pathArg}`);
|
|
45
|
+
if (result.skills.length === 0 && diagnostics.length === 0) {
|
|
46
|
+
console.log(chalk.red(' ✗ No SKILL.md found — nothing to validate'));
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
const errors = diagnostics.filter((d) => d.type === 'error');
|
|
50
|
+
const warnings = diagnostics.filter((d) => d.type === 'warning');
|
|
51
|
+
if (errors.length === 0 && warnings.length === 0) {
|
|
52
|
+
console.log(chalk.green(' ✓ All skills pass agentskills.io spec validation'));
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (errors.length > 0) {
|
|
56
|
+
console.log(chalk.red(`\n${errors.length} error(s):`));
|
|
57
|
+
for (const e of errors) {
|
|
58
|
+
console.log(chalk.red(` ✗ ${e.message}`));
|
|
59
|
+
if (e.path)
|
|
60
|
+
console.log(chalk.dim(` ${e.path}`));
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (warnings.length > 0) {
|
|
64
|
+
console.log(chalk.yellow(`\n${warnings.length} warning(s):`));
|
|
65
|
+
for (const w of warnings) {
|
|
66
|
+
console.log(chalk.yellow(` ⚠ ${w.message}`));
|
|
67
|
+
if (w.path)
|
|
68
|
+
console.log(chalk.dim(` ${w.path}`));
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
process.exit(1);
|
|
72
|
+
}
|
|
73
|
+
function checkLicense(skillName, filePath, raw) {
|
|
74
|
+
if (raw === undefined)
|
|
75
|
+
return [];
|
|
76
|
+
if (typeof raw !== 'string') {
|
|
77
|
+
return [
|
|
78
|
+
{
|
|
79
|
+
type: 'warning',
|
|
80
|
+
message: `Skill '${skillName}' has 'license' field of type ${typeof raw}; agentskills.io spec requires a string.`,
|
|
81
|
+
path: filePath,
|
|
82
|
+
},
|
|
83
|
+
];
|
|
84
|
+
}
|
|
85
|
+
return [];
|
|
86
|
+
}
|
|
87
|
+
function checkCompatibility(skillName, filePath, raw) {
|
|
88
|
+
if (raw === undefined)
|
|
89
|
+
return [];
|
|
90
|
+
if (typeof raw !== 'string') {
|
|
91
|
+
return [
|
|
92
|
+
{
|
|
93
|
+
type: 'warning',
|
|
94
|
+
message: `Skill '${skillName}' has 'compatibility' field of type ${typeof raw}; agentskills.io spec requires a string.`,
|
|
95
|
+
path: filePath,
|
|
96
|
+
},
|
|
97
|
+
];
|
|
98
|
+
}
|
|
99
|
+
if (raw.length > COMPATIBILITY_MAX_LENGTH) {
|
|
100
|
+
return [
|
|
101
|
+
{
|
|
102
|
+
type: 'warning',
|
|
103
|
+
message: `Skill '${skillName}' has 'compatibility' field of ${raw.length} characters; agentskills.io spec caps at ${COMPATIBILITY_MAX_LENGTH}.`,
|
|
104
|
+
path: filePath,
|
|
105
|
+
},
|
|
106
|
+
];
|
|
107
|
+
}
|
|
108
|
+
return [];
|
|
109
|
+
}
|
|
110
|
+
export const __test__ = { checkLicense, checkCompatibility };
|
|
111
|
+
//# sourceMappingURL=skill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill.js","sourceRoot":"","sources":["../../src/commands/skill.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -15,6 +15,7 @@ import { updateCommand } from './commands/update.js';
|
|
|
15
15
|
import { backupCommand, restoreCommand } from './commands/backup.js';
|
|
16
16
|
import { chatCommand } from './commands/chat.js';
|
|
17
17
|
import { listenCommand } from './commands/listen.js';
|
|
18
|
+
import { skillValidateCommand } from './commands/skill.js';
|
|
18
19
|
const program = new Command();
|
|
19
20
|
program.name('neura').description('Neura — AI assistant core service manager').version(CLI_VERSION);
|
|
20
21
|
// Install & setup
|
|
@@ -71,5 +72,11 @@ program
|
|
|
71
72
|
.option('-p, --port <port>', 'Core server port (default: config or 3002)')
|
|
72
73
|
.option('--debug', 'Print audio pipeline stats every 2s')
|
|
73
74
|
.action(listenCommand);
|
|
75
|
+
// Skill authoring / validation
|
|
76
|
+
const skillCmd = program.command('skill').description('Skill authoring tools');
|
|
77
|
+
skillCmd
|
|
78
|
+
.command('validate <path>')
|
|
79
|
+
.description('Validate skills at <path> against the agentskills.io spec')
|
|
80
|
+
.action(skillValidateCommand);
|
|
74
81
|
program.parse();
|
|
75
82
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/stores/index.js
CHANGED
|
@@ -4386,6 +4386,7 @@ var Logger = class _Logger {
|
|
|
4386
4386
|
// src/stores/migrations.ts
|
|
4387
4387
|
var log = new Logger("store");
|
|
4388
4388
|
async function runMigrations(db, embeddingDimensions = 3072) {
|
|
4389
|
+
await db.exec(`SET TIME ZONE 'UTC'`);
|
|
4389
4390
|
await db.exec("CREATE EXTENSION IF NOT EXISTS vector;");
|
|
4390
4391
|
await db.exec(`
|
|
4391
4392
|
CREATE TABLE IF NOT EXISTS _meta (
|
|
@@ -4519,12 +4520,27 @@ async function runMigrations(db, embeddingDimensions = 3072) {
|
|
|
4519
4520
|
title TEXT NOT NULL,
|
|
4520
4521
|
description TEXT,
|
|
4521
4522
|
status TEXT NOT NULL DEFAULT 'pending'
|
|
4522
|
-
CHECK (status IN (
|
|
4523
|
+
CHECK (status IN (
|
|
4524
|
+
'pending', 'awaiting_dispatch', 'in_progress',
|
|
4525
|
+
'awaiting_clarification', 'awaiting_approval', 'paused',
|
|
4526
|
+
'done', 'cancelled', 'failed'
|
|
4527
|
+
)),
|
|
4523
4528
|
priority TEXT NOT NULL DEFAULT 'medium'
|
|
4524
4529
|
CHECK (priority IN ('low', 'medium', 'high')),
|
|
4525
4530
|
due_at TIMESTAMP,
|
|
4526
4531
|
parent_id TEXT REFERENCES work_items(id) ON DELETE SET NULL,
|
|
4527
4532
|
source_session_id TEXT,
|
|
4533
|
+
-- Phase 6b columns (also added via ALTER for upgrades below)
|
|
4534
|
+
goal TEXT,
|
|
4535
|
+
context JSONB,
|
|
4536
|
+
related_skills JSONB NOT NULL DEFAULT '[]',
|
|
4537
|
+
repo_path TEXT,
|
|
4538
|
+
base_branch TEXT,
|
|
4539
|
+
worker_id TEXT,
|
|
4540
|
+
source TEXT NOT NULL DEFAULT 'user'
|
|
4541
|
+
CHECK (source IN ('user', 'system_proactive', 'discovery_loop')),
|
|
4542
|
+
version INTEGER NOT NULL DEFAULT 0,
|
|
4543
|
+
lease_expires_at TIMESTAMP,
|
|
4528
4544
|
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
|
4529
4545
|
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
|
4530
4546
|
completed_at TIMESTAMP
|
|
@@ -4532,6 +4548,80 @@ async function runMigrations(db, embeddingDimensions = 3072) {
|
|
|
4532
4548
|
`);
|
|
4533
4549
|
await db.exec("CREATE INDEX IF NOT EXISTS idx_work_items_status ON work_items(status)");
|
|
4534
4550
|
await db.exec("CREATE INDEX IF NOT EXISTS idx_work_items_due ON work_items(due_at)");
|
|
4551
|
+
await db.exec(`
|
|
4552
|
+
DO $$
|
|
4553
|
+
BEGIN
|
|
4554
|
+
IF NOT EXISTS (
|
|
4555
|
+
SELECT 1 FROM pg_constraint
|
|
4556
|
+
WHERE conname = 'work_items_status_check'
|
|
4557
|
+
AND pg_get_constraintdef(oid) LIKE '%awaiting_clarification%'
|
|
4558
|
+
) THEN
|
|
4559
|
+
ALTER TABLE work_items DROP CONSTRAINT IF EXISTS work_items_status_check;
|
|
4560
|
+
ALTER TABLE work_items ADD CONSTRAINT work_items_status_check
|
|
4561
|
+
CHECK (status IN (
|
|
4562
|
+
'pending', 'awaiting_dispatch', 'in_progress',
|
|
4563
|
+
'awaiting_clarification', 'awaiting_approval', 'paused',
|
|
4564
|
+
'done', 'cancelled', 'failed'
|
|
4565
|
+
));
|
|
4566
|
+
END IF;
|
|
4567
|
+
END $$
|
|
4568
|
+
`);
|
|
4569
|
+
await db.exec("ALTER TABLE work_items ADD COLUMN IF NOT EXISTS goal TEXT");
|
|
4570
|
+
await db.exec("ALTER TABLE work_items ADD COLUMN IF NOT EXISTS context JSONB");
|
|
4571
|
+
await db.exec(
|
|
4572
|
+
`ALTER TABLE work_items ADD COLUMN IF NOT EXISTS related_skills JSONB NOT NULL DEFAULT '[]'`
|
|
4573
|
+
);
|
|
4574
|
+
await db.exec("ALTER TABLE work_items ADD COLUMN IF NOT EXISTS repo_path TEXT");
|
|
4575
|
+
await db.exec("ALTER TABLE work_items ADD COLUMN IF NOT EXISTS base_branch TEXT");
|
|
4576
|
+
await db.exec("ALTER TABLE work_items ADD COLUMN IF NOT EXISTS worker_id TEXT");
|
|
4577
|
+
await db.exec(
|
|
4578
|
+
`ALTER TABLE work_items ADD COLUMN IF NOT EXISTS source TEXT NOT NULL DEFAULT 'user'`
|
|
4579
|
+
);
|
|
4580
|
+
await db.exec(
|
|
4581
|
+
`ALTER TABLE work_items ADD COLUMN IF NOT EXISTS version INTEGER NOT NULL DEFAULT 0`
|
|
4582
|
+
);
|
|
4583
|
+
await db.exec("ALTER TABLE work_items ADD COLUMN IF NOT EXISTS lease_expires_at TIMESTAMP");
|
|
4584
|
+
await db.exec(`
|
|
4585
|
+
DO $$
|
|
4586
|
+
BEGIN
|
|
4587
|
+
IF NOT EXISTS (
|
|
4588
|
+
SELECT 1 FROM pg_constraint
|
|
4589
|
+
WHERE conname = 'work_items_source_check'
|
|
4590
|
+
) THEN
|
|
4591
|
+
ALTER TABLE work_items ADD CONSTRAINT work_items_source_check
|
|
4592
|
+
CHECK (source IN ('user', 'system_proactive', 'discovery_loop'));
|
|
4593
|
+
END IF;
|
|
4594
|
+
END $$
|
|
4595
|
+
`);
|
|
4596
|
+
await db.exec("CREATE INDEX IF NOT EXISTS idx_work_items_worker ON work_items(worker_id)");
|
|
4597
|
+
await db.exec(
|
|
4598
|
+
"CREATE INDEX IF NOT EXISTS idx_work_items_lease ON work_items(lease_expires_at) WHERE lease_expires_at IS NOT NULL"
|
|
4599
|
+
);
|
|
4600
|
+
await db.exec(`
|
|
4601
|
+
CREATE TABLE IF NOT EXISTS task_comments (
|
|
4602
|
+
id TEXT PRIMARY KEY,
|
|
4603
|
+
task_id TEXT NOT NULL REFERENCES work_items(id) ON DELETE CASCADE,
|
|
4604
|
+
type TEXT NOT NULL
|
|
4605
|
+
CHECK (type IN (
|
|
4606
|
+
'progress', 'heartbeat',
|
|
4607
|
+
'clarification_request', 'approval_request',
|
|
4608
|
+
'clarification_response', 'approval_response',
|
|
4609
|
+
'error', 'result', 'system', 'deferred'
|
|
4610
|
+
)),
|
|
4611
|
+
author TEXT NOT NULL,
|
|
4612
|
+
content TEXT NOT NULL,
|
|
4613
|
+
attachment_path TEXT,
|
|
4614
|
+
urgency TEXT
|
|
4615
|
+
CHECK (urgency IS NULL OR urgency IN ('low', 'normal', 'high', 'critical')),
|
|
4616
|
+
metadata JSONB,
|
|
4617
|
+
created_at TIMESTAMP NOT NULL DEFAULT NOW()
|
|
4618
|
+
)
|
|
4619
|
+
`);
|
|
4620
|
+
await db.exec("CREATE INDEX IF NOT EXISTS idx_task_comments_task ON task_comments(task_id)");
|
|
4621
|
+
await db.exec("CREATE INDEX IF NOT EXISTS idx_task_comments_type ON task_comments(type)");
|
|
4622
|
+
await db.exec(
|
|
4623
|
+
"CREATE INDEX IF NOT EXISTS idx_task_comments_created ON task_comments(created_at)"
|
|
4624
|
+
);
|
|
4535
4625
|
await db.exec("ALTER TABLE facts ADD COLUMN IF NOT EXISTS valid_from TIMESTAMP DEFAULT NOW()");
|
|
4536
4626
|
await db.exec("ALTER TABLE facts ADD COLUMN IF NOT EXISTS valid_to TIMESTAMP");
|
|
4537
4627
|
await db.exec("ALTER TABLE facts ADD COLUMN IF NOT EXISTS superseded_by TEXT");
|
|
@@ -4778,7 +4868,17 @@ function mapWorkItem(r) {
|
|
|
4778
4868
|
sourceSessionId: r.source_session_id,
|
|
4779
4869
|
createdAt: r.created_at,
|
|
4780
4870
|
updatedAt: r.updated_at,
|
|
4781
|
-
completedAt: r.completed_at
|
|
4871
|
+
completedAt: r.completed_at,
|
|
4872
|
+
// Phase 6b fields — defaulted when legacy rows lack them.
|
|
4873
|
+
goal: r.goal ?? null,
|
|
4874
|
+
context: r.context ?? null,
|
|
4875
|
+
relatedSkills: r.related_skills ?? [],
|
|
4876
|
+
repoPath: r.repo_path ?? null,
|
|
4877
|
+
baseBranch: r.base_branch ?? null,
|
|
4878
|
+
workerId: r.worker_id ?? null,
|
|
4879
|
+
source: r.source ?? "user",
|
|
4880
|
+
version: r.version ?? 0,
|
|
4881
|
+
leaseExpiresAt: r.lease_expires_at ?? null
|
|
4782
4882
|
};
|
|
4783
4883
|
}
|
|
4784
4884
|
function mapTranscriptChunk(r) {
|
|
@@ -5411,7 +5511,7 @@ import crypto6 from "crypto";
|
|
|
5411
5511
|
async function getOpenWorkItems(db, limit = 50) {
|
|
5412
5512
|
const result = await db.query(
|
|
5413
5513
|
`SELECT * FROM work_items
|
|
5414
|
-
WHERE status IN ('pending', 'in_progress')
|
|
5514
|
+
WHERE status IN ('pending', 'awaiting_dispatch', 'in_progress', 'awaiting_clarification', 'awaiting_approval', 'paused')
|
|
5415
5515
|
ORDER BY
|
|
5416
5516
|
CASE priority WHEN 'high' THEN 0 WHEN 'medium' THEN 1 WHEN 'low' THEN 2 END,
|
|
5417
5517
|
due_at ASC NULLS LAST,
|
|
@@ -5445,8 +5545,11 @@ async function getWorkItem(db, id) {
|
|
|
5445
5545
|
async function createWorkItem(db, title, priority, options) {
|
|
5446
5546
|
const id = crypto6.randomUUID();
|
|
5447
5547
|
await db.query(
|
|
5448
|
-
`INSERT INTO work_items (
|
|
5449
|
-
|
|
5548
|
+
`INSERT INTO work_items (
|
|
5549
|
+
id, title, priority, description, due_at, parent_id, source_session_id,
|
|
5550
|
+
goal, context, related_skills, repo_path, base_branch, source
|
|
5551
|
+
)
|
|
5552
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)`,
|
|
5450
5553
|
[
|
|
5451
5554
|
id,
|
|
5452
5555
|
title,
|
|
@@ -5454,13 +5557,27 @@ async function createWorkItem(db, title, priority, options) {
|
|
|
5454
5557
|
options?.description ?? null,
|
|
5455
5558
|
options?.dueAt ?? null,
|
|
5456
5559
|
options?.parentId ?? null,
|
|
5457
|
-
options?.sourceSessionId ?? null
|
|
5560
|
+
options?.sourceSessionId ?? null,
|
|
5561
|
+
options?.goal ?? null,
|
|
5562
|
+
options?.context ? JSON.stringify(options.context) : null,
|
|
5563
|
+
JSON.stringify(options?.relatedSkills ?? []),
|
|
5564
|
+
options?.repoPath ?? null,
|
|
5565
|
+
options?.baseBranch ?? null,
|
|
5566
|
+
options?.source ?? "user"
|
|
5458
5567
|
]
|
|
5459
5568
|
);
|
|
5460
5569
|
return id;
|
|
5461
5570
|
}
|
|
5462
|
-
|
|
5463
|
-
|
|
5571
|
+
var VersionConflictError = class extends Error {
|
|
5572
|
+
constructor(id, expectedVersion) {
|
|
5573
|
+
super(`version conflict on work_item ${id} (expected ${expectedVersion})`);
|
|
5574
|
+
this.id = id;
|
|
5575
|
+
this.expectedVersion = expectedVersion;
|
|
5576
|
+
this.name = "VersionConflictError";
|
|
5577
|
+
}
|
|
5578
|
+
};
|
|
5579
|
+
async function updateWorkItem(db, id, updates, opts) {
|
|
5580
|
+
const sets = ["updated_at = NOW()", "version = version + 1"];
|
|
5464
5581
|
const values = [];
|
|
5465
5582
|
let paramIdx = 1;
|
|
5466
5583
|
if (updates.title !== void 0) {
|
|
@@ -5486,8 +5603,51 @@ async function updateWorkItem(db, id, updates) {
|
|
|
5486
5603
|
sets.push(`due_at = $${paramIdx++}`);
|
|
5487
5604
|
values.push(updates.dueAt);
|
|
5488
5605
|
}
|
|
5606
|
+
if (updates.goal !== void 0) {
|
|
5607
|
+
sets.push(`goal = $${paramIdx++}`);
|
|
5608
|
+
values.push(updates.goal);
|
|
5609
|
+
}
|
|
5610
|
+
if (updates.context !== void 0) {
|
|
5611
|
+
sets.push(`context = $${paramIdx++}`);
|
|
5612
|
+
values.push(updates.context === null ? null : JSON.stringify(updates.context));
|
|
5613
|
+
}
|
|
5614
|
+
if (updates.relatedSkills !== void 0) {
|
|
5615
|
+
sets.push(`related_skills = $${paramIdx++}`);
|
|
5616
|
+
values.push(JSON.stringify(updates.relatedSkills));
|
|
5617
|
+
}
|
|
5618
|
+
if (updates.repoPath !== void 0) {
|
|
5619
|
+
sets.push(`repo_path = $${paramIdx++}`);
|
|
5620
|
+
values.push(updates.repoPath);
|
|
5621
|
+
}
|
|
5622
|
+
if (updates.baseBranch !== void 0) {
|
|
5623
|
+
sets.push(`base_branch = $${paramIdx++}`);
|
|
5624
|
+
values.push(updates.baseBranch);
|
|
5625
|
+
}
|
|
5626
|
+
if (updates.workerId !== void 0) {
|
|
5627
|
+
sets.push(`worker_id = $${paramIdx++}`);
|
|
5628
|
+
values.push(updates.workerId);
|
|
5629
|
+
}
|
|
5630
|
+
if (updates.leaseExpiresAt !== void 0) {
|
|
5631
|
+
sets.push(`lease_expires_at = $${paramIdx++}`);
|
|
5632
|
+
values.push(updates.leaseExpiresAt);
|
|
5633
|
+
}
|
|
5634
|
+
let whereClause = `WHERE id = $${paramIdx++}`;
|
|
5489
5635
|
values.push(id);
|
|
5490
|
-
|
|
5636
|
+
if (opts?.expectVersion !== void 0) {
|
|
5637
|
+
whereClause += ` AND version = $${paramIdx}`;
|
|
5638
|
+
values.push(opts.expectVersion);
|
|
5639
|
+
}
|
|
5640
|
+
const result = await db.query(
|
|
5641
|
+
`UPDATE work_items SET ${sets.join(", ")} ${whereClause} RETURNING version`,
|
|
5642
|
+
values
|
|
5643
|
+
);
|
|
5644
|
+
if (result.rows.length === 0) {
|
|
5645
|
+
if (opts?.expectVersion !== void 0) {
|
|
5646
|
+
throw new VersionConflictError(id, opts.expectVersion);
|
|
5647
|
+
}
|
|
5648
|
+
throw new Error(`work_item ${id} not found`);
|
|
5649
|
+
}
|
|
5650
|
+
return result.rows[0].version;
|
|
5491
5651
|
}
|
|
5492
5652
|
async function deleteWorkItem(db, id) {
|
|
5493
5653
|
await db.query("DELETE FROM work_items WHERE id = $1", [id]);
|
|
@@ -5895,8 +6055,8 @@ var PgliteStore = class _PgliteStore {
|
|
|
5895
6055
|
createWorkItem(title, priority, options) {
|
|
5896
6056
|
return createWorkItem(this.db, title, priority, options);
|
|
5897
6057
|
}
|
|
5898
|
-
updateWorkItem(id, updates) {
|
|
5899
|
-
return updateWorkItem(this.db, id, updates);
|
|
6058
|
+
updateWorkItem(id, updates, opts) {
|
|
6059
|
+
return updateWorkItem(this.db, id, updates, opts);
|
|
5900
6060
|
}
|
|
5901
6061
|
deleteWorkItem(id) {
|
|
5902
6062
|
return deleteWorkItem(this.db, id);
|