@cleocode/core 2026.3.43 → 2026.3.45
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/dist/admin/export-tasks.d.ts.map +1 -1
- package/dist/admin/import-tasks.d.ts +10 -2
- package/dist/admin/import-tasks.d.ts.map +1 -1
- package/dist/agents/agent-schema.d.ts +358 -0
- package/dist/agents/agent-schema.d.ts.map +1 -0
- package/dist/agents/capacity.d.ts +57 -0
- package/dist/agents/capacity.d.ts.map +1 -0
- package/dist/agents/index.d.ts +17 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/registry.d.ts +115 -0
- package/dist/agents/registry.d.ts.map +1 -0
- package/dist/agents/retry.d.ts +83 -0
- package/dist/agents/retry.d.ts.map +1 -0
- package/dist/hooks/index.d.ts +4 -1
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/payload-schemas.d.ts +214 -0
- package/dist/hooks/payload-schemas.d.ts.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16937 -2371
- package/dist/index.js.map +4 -4
- package/dist/inject/index.d.ts.map +1 -1
- package/dist/intelligence/impact.d.ts +51 -0
- package/dist/intelligence/impact.d.ts.map +1 -0
- package/dist/intelligence/index.d.ts +15 -0
- package/dist/intelligence/index.d.ts.map +1 -0
- package/dist/intelligence/patterns.d.ts +66 -0
- package/dist/intelligence/patterns.d.ts.map +1 -0
- package/dist/intelligence/prediction.d.ts +51 -0
- package/dist/intelligence/prediction.d.ts.map +1 -0
- package/dist/intelligence/types.d.ts +221 -0
- package/dist/intelligence/types.d.ts.map +1 -0
- package/dist/internal.d.ts +12 -1
- package/dist/internal.d.ts.map +1 -1
- package/dist/issue/template-parser.d.ts +8 -2
- package/dist/issue/template-parser.d.ts.map +1 -1
- package/dist/lifecycle/pipeline.d.ts +2 -2
- package/dist/lifecycle/pipeline.d.ts.map +1 -1
- package/dist/lifecycle/state-machine.d.ts +1 -1
- package/dist/lifecycle/state-machine.d.ts.map +1 -1
- package/dist/memory/brain-lifecycle.d.ts.map +1 -1
- package/dist/memory/brain-retrieval.d.ts.map +1 -1
- package/dist/memory/brain-row-types.d.ts +40 -6
- package/dist/memory/brain-row-types.d.ts.map +1 -1
- package/dist/memory/brain-search.d.ts.map +1 -1
- package/dist/memory/brain-similarity.d.ts.map +1 -1
- package/dist/memory/claude-mem-migration.d.ts.map +1 -1
- package/dist/nexus/discover.d.ts.map +1 -1
- package/dist/nexus/index.d.ts +2 -0
- package/dist/nexus/index.d.ts.map +1 -1
- package/dist/nexus/transfer-types.d.ts +123 -0
- package/dist/nexus/transfer-types.d.ts.map +1 -0
- package/dist/nexus/transfer.d.ts +31 -0
- package/dist/nexus/transfer.d.ts.map +1 -0
- package/dist/orchestration/bootstrap.d.ts.map +1 -1
- package/dist/orchestration/skill-ops.d.ts +4 -4
- package/dist/orchestration/skill-ops.d.ts.map +1 -1
- package/dist/otel/index.d.ts +1 -1
- package/dist/otel/index.d.ts.map +1 -1
- package/dist/sessions/briefing.d.ts.map +1 -1
- package/dist/sessions/handoff.d.ts.map +1 -1
- package/dist/sessions/index.d.ts +1 -1
- package/dist/sessions/index.d.ts.map +1 -1
- package/dist/sessions/types.d.ts +8 -42
- package/dist/sessions/types.d.ts.map +1 -1
- package/dist/signaldock/signaldock-transport.d.ts +1 -1
- package/dist/signaldock/signaldock-transport.d.ts.map +1 -1
- package/dist/skills/injection/subagent.d.ts +3 -3
- package/dist/skills/injection/subagent.d.ts.map +1 -1
- package/dist/skills/manifests/contribution.d.ts +2 -2
- package/dist/skills/manifests/contribution.d.ts.map +1 -1
- package/dist/skills/orchestrator/spawn.d.ts +6 -6
- package/dist/skills/orchestrator/spawn.d.ts.map +1 -1
- package/dist/skills/orchestrator/startup.d.ts +1 -1
- package/dist/skills/orchestrator/startup.d.ts.map +1 -1
- package/dist/skills/orchestrator/validator.d.ts +2 -2
- package/dist/skills/orchestrator/validator.d.ts.map +1 -1
- package/dist/skills/precedence-types.d.ts +24 -1
- package/dist/skills/precedence-types.d.ts.map +1 -1
- package/dist/skills/types.d.ts +70 -4
- package/dist/skills/types.d.ts.map +1 -1
- package/dist/store/brain-sqlite.d.ts +4 -1
- package/dist/store/brain-sqlite.d.ts.map +1 -1
- package/dist/store/export.d.ts +5 -4
- package/dist/store/export.d.ts.map +1 -1
- package/dist/store/nexus-sqlite.d.ts +4 -1
- package/dist/store/nexus-sqlite.d.ts.map +1 -1
- package/dist/store/sqlite.d.ts +4 -1
- package/dist/store/sqlite.d.ts.map +1 -1
- package/dist/store/tasks-schema.d.ts +14 -4
- package/dist/store/tasks-schema.d.ts.map +1 -1
- package/dist/store/typed-query.d.ts +12 -0
- package/dist/store/typed-query.d.ts.map +1 -0
- package/dist/store/validation-schemas.d.ts +2423 -50
- package/dist/store/validation-schemas.d.ts.map +1 -1
- package/dist/system/inject-generate.d.ts.map +1 -1
- package/dist/validation/doctor/checks.d.ts +5 -0
- package/dist/validation/doctor/checks.d.ts.map +1 -1
- package/dist/validation/engine.d.ts +10 -10
- package/dist/validation/engine.d.ts.map +1 -1
- package/dist/validation/index.d.ts +6 -2
- package/dist/validation/index.d.ts.map +1 -1
- package/dist/validation/protocol-common.d.ts +10 -2
- package/dist/validation/protocol-common.d.ts.map +1 -1
- package/migrations/drizzle-tasks/20260320013731_wave0-schema-hardening/migration.sql +84 -0
- package/migrations/drizzle-tasks/20260320013731_wave0-schema-hardening/snapshot.json +4060 -0
- package/migrations/drizzle-tasks/20260320020000_agent-dimension/migration.sql +35 -0
- package/migrations/drizzle-tasks/20260320020000_agent-dimension/snapshot.json +4312 -0
- package/package.json +2 -2
- package/src/admin/export-tasks.ts +2 -5
- package/src/admin/import-tasks.ts +53 -29
- package/src/agents/__tests__/capacity.test.ts +219 -0
- package/src/agents/__tests__/registry.test.ts +457 -0
- package/src/agents/__tests__/retry.test.ts +289 -0
- package/src/agents/agent-schema.ts +107 -0
- package/src/agents/capacity.ts +151 -0
- package/src/agents/index.ts +68 -0
- package/src/agents/registry.ts +449 -0
- package/src/agents/retry.ts +255 -0
- package/src/hooks/index.ts +20 -1
- package/src/hooks/payload-schemas.ts +199 -0
- package/src/index.ts +69 -0
- package/src/inject/index.ts +14 -14
- package/src/intelligence/__tests__/impact.test.ts +453 -0
- package/src/intelligence/__tests__/patterns.test.ts +450 -0
- package/src/intelligence/__tests__/prediction.test.ts +418 -0
- package/src/intelligence/impact.ts +638 -0
- package/src/intelligence/index.ts +47 -0
- package/src/intelligence/patterns.ts +621 -0
- package/src/intelligence/prediction.ts +621 -0
- package/src/intelligence/types.ts +273 -0
- package/src/internal.ts +89 -2
- package/src/issue/template-parser.ts +65 -4
- package/src/lifecycle/pipeline.ts +14 -7
- package/src/lifecycle/state-machine.ts +6 -2
- package/src/memory/brain-lifecycle.ts +5 -11
- package/src/memory/brain-retrieval.ts +44 -38
- package/src/memory/brain-row-types.ts +43 -6
- package/src/memory/brain-search.ts +53 -32
- package/src/memory/brain-similarity.ts +9 -8
- package/src/memory/claude-mem-migration.ts +4 -3
- package/src/nexus/__tests__/nexus-e2e.test.ts +1481 -0
- package/src/nexus/__tests__/transfer.test.ts +446 -0
- package/src/nexus/discover.ts +1 -0
- package/src/nexus/index.ts +14 -0
- package/src/nexus/transfer-types.ts +129 -0
- package/src/nexus/transfer.ts +314 -0
- package/src/orchestration/bootstrap.ts +11 -17
- package/src/orchestration/skill-ops.ts +52 -32
- package/src/otel/index.ts +48 -4
- package/src/sessions/__tests__/briefing.test.ts +31 -2
- package/src/sessions/briefing.ts +27 -42
- package/src/sessions/handoff.ts +52 -86
- package/src/sessions/index.ts +5 -1
- package/src/sessions/types.ts +9 -43
- package/src/signaldock/signaldock-transport.ts +5 -2
- package/src/skills/injection/subagent.ts +10 -16
- package/src/skills/manifests/contribution.ts +5 -13
- package/src/skills/orchestrator/__tests__/spawn-tier.test.ts +44 -30
- package/src/skills/orchestrator/spawn.ts +18 -31
- package/src/skills/orchestrator/startup.ts +78 -65
- package/src/skills/orchestrator/validator.ts +26 -31
- package/src/skills/precedence-types.ts +24 -1
- package/src/skills/types.ts +72 -5
- package/src/store/__tests__/test-db-helper.d.ts +4 -4
- package/src/store/__tests__/test-db-helper.js +5 -16
- package/src/store/__tests__/test-db-helper.ts +5 -18
- package/src/store/brain-sqlite.ts +7 -3
- package/src/store/chain-schema.ts +1 -1
- package/src/store/export.ts +22 -12
- package/src/store/nexus-sqlite.ts +7 -3
- package/src/store/sqlite.ts +9 -3
- package/src/store/tasks-schema.ts +65 -8
- package/src/store/typed-query.ts +17 -0
- package/src/store/validation-schemas.ts +347 -23
- package/src/system/inject-generate.ts +9 -23
- package/src/validation/doctor/checks.ts +24 -2
- package/src/validation/engine.ts +11 -11
- package/src/validation/index.ts +131 -3
- package/src/validation/protocol-common.ts +54 -3
- package/dist/tasks/reparent.d.ts +0 -38
- package/dist/tasks/reparent.d.ts.map +0 -1
- package/src/tasks/reparent.ts +0 -134
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Skills Precedence Types - Phase 3B of T5238
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
|
+
* Re-exports CAAMP precedence types and adds CLEO-specific wrapper types
|
|
5
|
+
* for skill path resolution and installation context.
|
|
6
|
+
*
|
|
7
|
+
* These types complement the skill types in `./types.ts`:
|
|
8
|
+
* - `./types.ts` defines the CLEO skill domain model (Skill, SkillFrontmatter, etc.)
|
|
9
|
+
* - This file defines CAAMP precedence integration types used when resolving
|
|
10
|
+
* which skill version takes priority across providers and scopes.
|
|
11
|
+
*
|
|
4
12
|
* @task T5238
|
|
5
13
|
*/
|
|
6
14
|
|
|
@@ -21,23 +29,38 @@ export {
|
|
|
21
29
|
|
|
22
30
|
import type { SkillsPrecedence } from '@cleocode/caamp';
|
|
23
31
|
|
|
32
|
+
/** Configuration for skill precedence resolution across providers. */
|
|
24
33
|
export interface SkillsPrecedenceConfig {
|
|
34
|
+
/** Default precedence mode when no provider-specific override exists. */
|
|
25
35
|
defaultPrecedence?: SkillsPrecedence;
|
|
36
|
+
/** Per-provider precedence overrides (provider ID -> precedence). */
|
|
26
37
|
providerOverrides?: Record<string, SkillsPrecedence>;
|
|
27
38
|
}
|
|
28
39
|
|
|
40
|
+
/** A resolved skill path with full provenance metadata. */
|
|
29
41
|
export interface ResolvedSkillPath {
|
|
42
|
+
/** Absolute filesystem path to the skill directory. */
|
|
30
43
|
path: string;
|
|
44
|
+
/** Where the skill was sourced from. */
|
|
31
45
|
source: 'vendor' | 'agents' | 'marketplace';
|
|
46
|
+
/** Whether this is a global or project-scoped skill. */
|
|
32
47
|
scope: 'global' | 'project';
|
|
48
|
+
/** The precedence mode that selected this path. */
|
|
33
49
|
precedence: SkillsPrecedence;
|
|
50
|
+
/** The provider that owns this skill path. */
|
|
34
51
|
providerId: string;
|
|
35
52
|
}
|
|
36
53
|
|
|
54
|
+
/** Context for a skill installation operation. */
|
|
37
55
|
export interface SkillInstallationContext {
|
|
56
|
+
/** Name of the skill being installed. */
|
|
38
57
|
skillName: string;
|
|
58
|
+
/** Source URL or path to install from. */
|
|
39
59
|
source: string;
|
|
60
|
+
/** Provider IDs to install the skill for. */
|
|
40
61
|
targetProviders: string[];
|
|
62
|
+
/** Precedence mode for the installation. */
|
|
41
63
|
precedenceMode?: SkillsPrecedence;
|
|
64
|
+
/** Project root for project-scoped installations. */
|
|
42
65
|
projectRoot?: string;
|
|
43
66
|
}
|
package/src/skills/types.ts
CHANGED
|
@@ -1,13 +1,46 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Type definitions for the skills system.
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
|
+
* ## Dual Type System: CAAMP vs CLEO Skills
|
|
5
|
+
*
|
|
6
|
+
* The skill type system has two layers reflecting the CAAMP/CLEO split:
|
|
7
|
+
*
|
|
8
|
+
* ### CAAMP types (re-exported as `CaampSkillMetadata`, `CtSkillEntry`, etc.)
|
|
9
|
+
* - Defined in `@cleocode/caamp` -- the cross-agent skill standard.
|
|
10
|
+
* - **`CaampSkillMetadata`**: Minimal metadata parsed from SKILL.md YAML header
|
|
11
|
+
* by CAAMP's `parseSkillFile()`. Contains: name, description, version, license,
|
|
12
|
+
* compatibility, metadata, allowedTools.
|
|
13
|
+
* - **`CtSkillEntry`**: A discovered skill with location + metadata. Used by CAAMP's
|
|
14
|
+
* discovery and install pipeline.
|
|
15
|
+
* - Use CAAMP types when interacting with CAAMP APIs (skill discovery, install,
|
|
16
|
+
* provider lock files, skill precedence resolution).
|
|
17
|
+
*
|
|
18
|
+
* ### CLEO types (`Skill`, `SkillFrontmatter`, `SkillSummary`, `SkillManifest`)
|
|
19
|
+
* - Defined here -- CLEO's extended skill domain model.
|
|
20
|
+
* - **`SkillFrontmatter`**: Superset of CaampSkillMetadata. Adds CLEO-specific
|
|
21
|
+
* fields: tags, triggers, dispatchPriority, model, invocable, command, protocol.
|
|
22
|
+
* Parsed by CLEO's own SKILL.md reader with richer YAML support.
|
|
23
|
+
* - **`Skill`**: Full in-memory skill object with filesystem paths and parsed content.
|
|
24
|
+
* - **`SkillSummary`**: Lightweight projection for listings (cached in SkillManifest).
|
|
25
|
+
* - Use CLEO types for skill dispatch, orchestration, CLI display, and manifest caching.
|
|
26
|
+
*
|
|
27
|
+
* ### Relationship
|
|
28
|
+
* - `SkillFrontmatter` is a functional superset of `CaampSkillMetadata`:
|
|
29
|
+
* every field in CaampSkillMetadata exists in SkillFrontmatter (name, description,
|
|
30
|
+
* version, allowedTools). SkillFrontmatter adds CLEO-specific extension fields.
|
|
31
|
+
* - A `Skill` (CLEO) wraps a `SkillFrontmatter` with filesystem context, whereas
|
|
32
|
+
* a `CtSkillEntry` (CAAMP) wraps a `CaampSkillMetadata` with install metadata.
|
|
33
|
+
* - When converting between layers, map `CaampSkillMetadata` -> `SkillFrontmatter`
|
|
34
|
+
* (all CAAMP fields carry over; CLEO-specific fields default to undefined).
|
|
35
|
+
*
|
|
4
36
|
* @epic T4454
|
|
5
37
|
* @task T4516
|
|
6
38
|
*/
|
|
7
39
|
|
|
8
40
|
import type { TaskRef, TaskRefPriority } from '@cleocode/contracts';
|
|
9
41
|
|
|
10
|
-
// Re-export CAAMP types where they overlap with CLEO's domain
|
|
42
|
+
// Re-export CAAMP types where they overlap with CLEO's domain.
|
|
43
|
+
// See module JSDoc above for guidance on which type to use where.
|
|
11
44
|
export type {
|
|
12
45
|
CtDispatchMatrix,
|
|
13
46
|
CtManifest,
|
|
@@ -25,23 +58,52 @@ export type {
|
|
|
25
58
|
// Skill Types
|
|
26
59
|
// ============================================================================
|
|
27
60
|
|
|
28
|
-
/**
|
|
61
|
+
/**
|
|
62
|
+
* Skill frontmatter parsed from SKILL.md YAML header.
|
|
63
|
+
*
|
|
64
|
+
* This is CLEO's extended skill metadata -- a functional superset of CAAMP's
|
|
65
|
+
* `SkillMetadata`. All fields from `CaampSkillMetadata` (name, description,
|
|
66
|
+
* version, allowedTools) are present here. CLEO adds: tags, triggers,
|
|
67
|
+
* dispatchPriority, model, invocable, command, protocol.
|
|
68
|
+
*
|
|
69
|
+
* Use this type when working with CLEO's skill loading, dispatch, and
|
|
70
|
+
* orchestration systems. Use `CaampSkillMetadata` when interfacing directly
|
|
71
|
+
* with CAAMP's discovery/install APIs.
|
|
72
|
+
*/
|
|
29
73
|
export interface SkillFrontmatter {
|
|
74
|
+
/** Skill name (lowercase, hyphens). Maps to CaampSkillMetadata.name. */
|
|
30
75
|
name: string;
|
|
76
|
+
/** Human-readable description. Maps to CaampSkillMetadata.description. */
|
|
31
77
|
description: string;
|
|
78
|
+
/** Semantic version string. Maps to CaampSkillMetadata.version. */
|
|
32
79
|
version?: string;
|
|
80
|
+
/** Skill author (CLEO extension). */
|
|
33
81
|
author?: string;
|
|
82
|
+
/** Classification tags for search/filter (CLEO extension). */
|
|
34
83
|
tags?: string[];
|
|
84
|
+
/** Trigger patterns for auto-dispatch (CLEO extension). */
|
|
35
85
|
triggers?: string[];
|
|
86
|
+
/** Priority for dispatch selection (CLEO extension). */
|
|
36
87
|
dispatchPriority?: number;
|
|
88
|
+
/** Preferred LLM model (CLEO extension). */
|
|
37
89
|
model?: string;
|
|
90
|
+
/** Allowed tool names. Maps to CaampSkillMetadata.allowedTools. */
|
|
38
91
|
allowedTools?: string[];
|
|
92
|
+
/** Whether the skill can be invoked directly (CLEO extension). */
|
|
39
93
|
invocable?: boolean;
|
|
94
|
+
/** CLI command for direct invocation (CLEO extension). */
|
|
40
95
|
command?: string;
|
|
96
|
+
/** RCASD-IVTR+C protocol type (CLEO extension). */
|
|
41
97
|
protocol?: SkillProtocolType;
|
|
42
98
|
}
|
|
43
99
|
|
|
44
|
-
/**
|
|
100
|
+
/**
|
|
101
|
+
* Skill definition loaded from disk.
|
|
102
|
+
*
|
|
103
|
+
* CLEO-specific type that wraps a {@link SkillFrontmatter} with filesystem
|
|
104
|
+
* context. For CAAMP's equivalent, see `CtSkillEntry` which wraps
|
|
105
|
+
* `CaampSkillMetadata` with install/discovery metadata instead.
|
|
106
|
+
*/
|
|
45
107
|
export interface Skill {
|
|
46
108
|
name: string;
|
|
47
109
|
dirName: string;
|
|
@@ -51,7 +113,12 @@ export interface Skill {
|
|
|
51
113
|
content?: string;
|
|
52
114
|
}
|
|
53
115
|
|
|
54
|
-
/**
|
|
116
|
+
/**
|
|
117
|
+
* Lightweight skill summary for manifest/listing.
|
|
118
|
+
*
|
|
119
|
+
* Projected from {@link Skill} for efficient caching in {@link SkillManifest}.
|
|
120
|
+
* Contains only the fields needed for CLI display and dispatch selection.
|
|
121
|
+
*/
|
|
55
122
|
export interface SkillSummary {
|
|
56
123
|
name: string;
|
|
57
124
|
dirName: string;
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*
|
|
8
8
|
* @task T5244
|
|
9
9
|
*/
|
|
10
|
-
import type { Task
|
|
10
|
+
import type { Task } from '@cleocode/contracts';
|
|
11
11
|
import type { DataAccessor } from '../data-accessor.js';
|
|
12
12
|
/** Result of creating a test database environment. */
|
|
13
13
|
export interface TestDbEnv {
|
|
@@ -32,16 +32,16 @@ export interface TestDbEnv {
|
|
|
32
32
|
*/
|
|
33
33
|
export declare function createTestDb(): Promise<TestDbEnv>;
|
|
34
34
|
/**
|
|
35
|
-
* Build
|
|
35
|
+
* Build full Task objects from a list of task partials.
|
|
36
36
|
* Useful for seeding test data via accessor.upsertSingleTask().
|
|
37
37
|
*/
|
|
38
|
-
export declare function
|
|
38
|
+
export declare function makeTasks(
|
|
39
39
|
tasks: Array<
|
|
40
40
|
Partial<Task> & {
|
|
41
41
|
id: string;
|
|
42
42
|
}
|
|
43
43
|
>,
|
|
44
|
-
):
|
|
44
|
+
): Task[];
|
|
45
45
|
/**
|
|
46
46
|
* Seed tasks into the test database via the accessor.
|
|
47
47
|
*
|
|
@@ -40,11 +40,11 @@ export async function createTestDb() {
|
|
|
40
40
|
};
|
|
41
41
|
}
|
|
42
42
|
/**
|
|
43
|
-
* Build
|
|
43
|
+
* Build full Task objects from a list of task partials.
|
|
44
44
|
* Useful for seeding test data via accessor.upsertSingleTask().
|
|
45
45
|
*/
|
|
46
|
-
export function
|
|
47
|
-
|
|
46
|
+
export function makeTasks(tasks) {
|
|
47
|
+
return tasks.map((t) => ({
|
|
48
48
|
title: t.title ?? `Task ${t.id}`,
|
|
49
49
|
description: t.description ?? undefined,
|
|
50
50
|
status: t.status ?? 'pending',
|
|
@@ -52,17 +52,6 @@ export function makeTaskFile(tasks) {
|
|
|
52
52
|
createdAt: t.createdAt ?? new Date().toISOString(),
|
|
53
53
|
...t,
|
|
54
54
|
}));
|
|
55
|
-
return {
|
|
56
|
-
version: '2.10.0',
|
|
57
|
-
project: { name: 'test', phases: {} },
|
|
58
|
-
lastUpdated: new Date().toISOString(),
|
|
59
|
-
_meta: {
|
|
60
|
-
schemaVersion: '2.10.0',
|
|
61
|
-
checksum: '0000000000000000',
|
|
62
|
-
configVersion: '1.0.0',
|
|
63
|
-
},
|
|
64
|
-
tasks: fullTasks,
|
|
65
|
-
};
|
|
66
55
|
}
|
|
67
56
|
/**
|
|
68
57
|
* Seed tasks into the test database via the accessor.
|
|
@@ -79,8 +68,8 @@ export async function seedTasks(accessor, tasks) {
|
|
|
79
68
|
return;
|
|
80
69
|
}
|
|
81
70
|
// Build full Task objects from partials
|
|
82
|
-
const
|
|
83
|
-
|
|
71
|
+
const fullTasks = makeTasks(tasks);
|
|
72
|
+
|
|
84
73
|
// Pass 1: Upsert all tasks without dependencies so FK targets exist
|
|
85
74
|
for (const task of fullTasks) {
|
|
86
75
|
await accessor.upsertSingleTask({ ...task, depends: undefined });
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
import { mkdtempSync, rmSync } from 'node:fs';
|
|
12
12
|
import { tmpdir } from 'node:os';
|
|
13
13
|
import { join } from 'node:path';
|
|
14
|
-
import type { Task
|
|
14
|
+
import type { Task } from '@cleocode/contracts';
|
|
15
15
|
import type { DataAccessor } from '../data-accessor.js';
|
|
16
16
|
import { resetDbState } from '../sqlite.js';
|
|
17
17
|
import { createSqliteDataAccessor } from '../sqlite-data-accessor.js';
|
|
@@ -59,11 +59,11 @@ export async function createTestDb(): Promise<TestDbEnv> {
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
/**
|
|
62
|
-
* Build
|
|
62
|
+
* Build full Task objects from a list of task partials.
|
|
63
63
|
* Useful for seeding test data via accessor.upsertSingleTask().
|
|
64
64
|
*/
|
|
65
|
-
export function
|
|
66
|
-
|
|
65
|
+
export function makeTasks(tasks: Array<Partial<Task> & { id: string }>): Task[] {
|
|
66
|
+
return tasks.map(
|
|
67
67
|
(t) =>
|
|
68
68
|
({
|
|
69
69
|
title: t.title ?? `Task ${t.id}`,
|
|
@@ -74,18 +74,6 @@ export function makeTaskFile(tasks: Array<Partial<Task> & { id: string }>): Task
|
|
|
74
74
|
...t,
|
|
75
75
|
}) as Task,
|
|
76
76
|
);
|
|
77
|
-
|
|
78
|
-
return {
|
|
79
|
-
version: '2.10.0',
|
|
80
|
-
project: { name: 'test', phases: {} },
|
|
81
|
-
lastUpdated: new Date().toISOString(),
|
|
82
|
-
_meta: {
|
|
83
|
-
schemaVersion: '2.10.0',
|
|
84
|
-
checksum: '0000000000000000',
|
|
85
|
-
configVersion: '1.0.0',
|
|
86
|
-
},
|
|
87
|
-
tasks: fullTasks,
|
|
88
|
-
};
|
|
89
77
|
}
|
|
90
78
|
|
|
91
79
|
/**
|
|
@@ -108,8 +96,7 @@ export async function seedTasks(
|
|
|
108
96
|
}
|
|
109
97
|
|
|
110
98
|
// Build full Task objects from partials
|
|
111
|
-
const
|
|
112
|
-
const fullTasks = tf.tasks;
|
|
99
|
+
const fullTasks = makeTasks(tasks);
|
|
113
100
|
|
|
114
101
|
// Pass 1: Upsert all tasks without dependencies so FK targets exist
|
|
115
102
|
for (const task of fullTasks) {
|
|
@@ -50,13 +50,17 @@ export function getBrainDbPath(cwd?: string): string {
|
|
|
50
50
|
|
|
51
51
|
/**
|
|
52
52
|
* Resolve the path to the drizzle-brain migrations folder.
|
|
53
|
-
* Works from both src/ (dev via tsx) and dist/ (compiled).
|
|
53
|
+
* Works from both src/ (dev via tsx) and dist/ (compiled via esbuild bundle).
|
|
54
|
+
*
|
|
55
|
+
* - Source layout: __dirname = src/store/ → need ../../migrations/drizzle-brain
|
|
56
|
+
* - Bundled layout: __dirname = dist/ → need ../migrations/drizzle-brain
|
|
54
57
|
*/
|
|
55
58
|
export function resolveBrainMigrationsFolder(): string {
|
|
56
59
|
const __filename = fileURLToPath(import.meta.url);
|
|
57
60
|
const __dirname = dirname(__filename);
|
|
58
|
-
|
|
59
|
-
|
|
61
|
+
const isBundled = __dirname.endsWith('/dist') || __dirname.endsWith('\\dist');
|
|
62
|
+
const pkgRoot = isBundled ? join(__dirname, '..') : join(__dirname, '..', '..');
|
|
63
|
+
return join(pkgRoot, 'migrations', 'drizzle-brain');
|
|
60
64
|
}
|
|
61
65
|
|
|
62
66
|
/**
|
|
@@ -46,7 +46,7 @@ export const warpChainInstances = sqliteTable(
|
|
|
46
46
|
id: text('id').primaryKey(),
|
|
47
47
|
chainId: text('chain_id')
|
|
48
48
|
.notNull()
|
|
49
|
-
.references(() => warpChains.id),
|
|
49
|
+
.references(() => warpChains.id, { onDelete: 'cascade' }),
|
|
50
50
|
epicId: text('epic_id').notNull(),
|
|
51
51
|
variables: text('variables'), // JSON
|
|
52
52
|
stageToTask: text('stage_to_task'), // JSON
|
package/src/store/export.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { createHash } from 'node:crypto';
|
|
10
|
-
import type { Task
|
|
10
|
+
import type { Task } from '@cleocode/contracts';
|
|
11
11
|
|
|
12
12
|
/** Export format version. */
|
|
13
13
|
const EXPORT_FORMAT_VERSION = '1.0.0';
|
|
@@ -137,17 +137,17 @@ export function buildRelationshipGraph(tasks: Task[]): RelationshipGraph {
|
|
|
137
137
|
*/
|
|
138
138
|
export function buildExportPackage(
|
|
139
139
|
tasks: Task[],
|
|
140
|
-
taskData: TaskFile,
|
|
141
140
|
options: {
|
|
142
141
|
mode: string;
|
|
143
142
|
rootTaskIds: string[];
|
|
144
143
|
includeChildren: boolean;
|
|
145
144
|
cleoVersion?: string;
|
|
146
145
|
filters?: unknown;
|
|
146
|
+
projectName?: string;
|
|
147
147
|
},
|
|
148
148
|
): ExportPackage {
|
|
149
149
|
const now = new Date().toISOString();
|
|
150
|
-
const projectName =
|
|
150
|
+
const projectName = options.projectName ?? 'unknown';
|
|
151
151
|
const maxId = tasks.reduce((max, t) => {
|
|
152
152
|
const num = parseInt(t.id.replace('T', ''), 10);
|
|
153
153
|
return num > max ? num : max;
|
|
@@ -188,41 +188,51 @@ export function buildExportPackage(
|
|
|
188
188
|
/**
|
|
189
189
|
* Export a single task.
|
|
190
190
|
*/
|
|
191
|
-
export function exportSingle(
|
|
192
|
-
|
|
191
|
+
export function exportSingle(
|
|
192
|
+
taskId: string,
|
|
193
|
+
allTasks: Task[],
|
|
194
|
+
projectName?: string,
|
|
195
|
+
): ExportPackage | null {
|
|
196
|
+
const task = allTasks.find((t) => t.id === taskId);
|
|
193
197
|
if (!task) return null;
|
|
194
198
|
|
|
195
|
-
return buildExportPackage([task],
|
|
199
|
+
return buildExportPackage([task], {
|
|
196
200
|
mode: 'single',
|
|
197
201
|
rootTaskIds: [taskId],
|
|
198
202
|
includeChildren: false,
|
|
203
|
+
projectName,
|
|
199
204
|
});
|
|
200
205
|
}
|
|
201
206
|
|
|
202
207
|
/**
|
|
203
208
|
* Export a subtree (task + all descendants).
|
|
204
209
|
*/
|
|
205
|
-
export function exportSubtree(
|
|
206
|
-
|
|
210
|
+
export function exportSubtree(
|
|
211
|
+
rootId: string,
|
|
212
|
+
allTasks: Task[],
|
|
213
|
+
projectName?: string,
|
|
214
|
+
): ExportPackage | null {
|
|
215
|
+
const root = allTasks.find((t) => t.id === rootId);
|
|
207
216
|
if (!root) return null;
|
|
208
217
|
|
|
209
|
-
// Collect all descendants
|
|
218
|
+
// Collect all descendants via BFS
|
|
210
219
|
const collected = new Map<string, Task>();
|
|
211
220
|
const queue = [rootId];
|
|
212
221
|
|
|
213
222
|
while (queue.length > 0) {
|
|
214
223
|
const id = queue.shift()!;
|
|
215
|
-
const task =
|
|
224
|
+
const task = allTasks.find((t) => t.id === id);
|
|
216
225
|
if (!task || collected.has(id)) continue;
|
|
217
226
|
collected.set(id, task);
|
|
218
|
-
const children =
|
|
227
|
+
const children = allTasks.filter((t) => t.parentId === id);
|
|
219
228
|
queue.push(...children.map((c) => c.id));
|
|
220
229
|
}
|
|
221
230
|
|
|
222
231
|
const tasks = [...collected.values()];
|
|
223
|
-
return buildExportPackage(tasks,
|
|
232
|
+
return buildExportPackage(tasks, {
|
|
224
233
|
mode: 'subtree',
|
|
225
234
|
rootTaskIds: [rootId],
|
|
226
235
|
includeChildren: true,
|
|
236
|
+
projectName,
|
|
227
237
|
});
|
|
228
238
|
}
|
|
@@ -46,13 +46,17 @@ export function getNexusDbPath(): string {
|
|
|
46
46
|
|
|
47
47
|
/**
|
|
48
48
|
* Resolve the path to the drizzle-nexus migrations folder.
|
|
49
|
-
* Works from both src/ (dev via tsx) and dist/ (compiled).
|
|
49
|
+
* Works from both src/ (dev via tsx) and dist/ (compiled via esbuild bundle).
|
|
50
|
+
*
|
|
51
|
+
* - Source layout: __dirname = src/store/ → need ../../migrations/drizzle-nexus
|
|
52
|
+
* - Bundled layout: __dirname = dist/ → need ../migrations/drizzle-nexus
|
|
50
53
|
*/
|
|
51
54
|
export function resolveNexusMigrationsFolder(): string {
|
|
52
55
|
const __filename = fileURLToPath(import.meta.url);
|
|
53
56
|
const __dirname = dirname(__filename);
|
|
54
|
-
|
|
55
|
-
|
|
57
|
+
const isBundled = __dirname.endsWith('/dist') || __dirname.endsWith('\\dist');
|
|
58
|
+
const pkgRoot = isBundled ? join(__dirname, '..') : join(__dirname, '..', '..');
|
|
59
|
+
return join(pkgRoot, 'migrations', 'drizzle-nexus');
|
|
56
60
|
}
|
|
57
61
|
|
|
58
62
|
/**
|
package/src/store/sqlite.ts
CHANGED
|
@@ -357,13 +357,19 @@ export async function getDb(cwd?: string): Promise<NodeSQLiteDatabase<typeof sch
|
|
|
357
357
|
|
|
358
358
|
/**
|
|
359
359
|
* Resolve the path to the drizzle migrations folder.
|
|
360
|
-
* Works from both src/ (dev via tsx) and dist/ (compiled).
|
|
360
|
+
* Works from both src/ (dev via tsx) and dist/ (compiled via esbuild bundle).
|
|
361
|
+
*
|
|
362
|
+
* - Source layout: __dirname = src/store/ → need ../../migrations/drizzle-tasks
|
|
363
|
+
* - Bundled layout: __dirname = dist/ → need ../migrations/drizzle-tasks
|
|
361
364
|
*/
|
|
362
365
|
export function resolveMigrationsFolder(): string {
|
|
363
366
|
const __filename = fileURLToPath(import.meta.url);
|
|
364
367
|
const __dirname = dirname(__filename);
|
|
365
|
-
//
|
|
366
|
-
|
|
368
|
+
// When esbuild bundles into dist/index.js, __dirname is dist/ (1 level deep).
|
|
369
|
+
// When running from source via tsx, __dirname is src/store/ (2 levels deep).
|
|
370
|
+
const isBundled = __dirname.endsWith('/dist') || __dirname.endsWith('\\dist');
|
|
371
|
+
const pkgRoot = isBundled ? join(__dirname, '..') : join(__dirname, '..', '..');
|
|
372
|
+
return join(pkgRoot, 'migrations', 'drizzle-tasks');
|
|
367
373
|
}
|
|
368
374
|
|
|
369
375
|
/**
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
primaryKey,
|
|
17
17
|
sqliteTable,
|
|
18
18
|
text,
|
|
19
|
+
unique,
|
|
19
20
|
} from 'drizzle-orm/sqlite-core';
|
|
20
21
|
import {
|
|
21
22
|
ADR_STATUSES,
|
|
@@ -27,6 +28,22 @@ import {
|
|
|
27
28
|
TASK_STATUSES,
|
|
28
29
|
} from './status-registry.js';
|
|
29
30
|
|
|
31
|
+
export type {
|
|
32
|
+
AgentErrorLogRow,
|
|
33
|
+
AgentErrorType,
|
|
34
|
+
AgentInstanceRow,
|
|
35
|
+
AgentInstanceStatus,
|
|
36
|
+
AgentType,
|
|
37
|
+
NewAgentErrorLogRow,
|
|
38
|
+
NewAgentInstanceRow,
|
|
39
|
+
} from '../agents/agent-schema.js';
|
|
40
|
+
// Re-export agent schema tables so drizzle-kit picks them up for migrations.
|
|
41
|
+
export {
|
|
42
|
+
AGENT_INSTANCE_STATUSES,
|
|
43
|
+
AGENT_TYPES,
|
|
44
|
+
agentErrorLog,
|
|
45
|
+
agentInstances,
|
|
46
|
+
} from '../agents/agent-schema.js';
|
|
30
47
|
export type {
|
|
31
48
|
NewWarpChainInstanceRow,
|
|
32
49
|
NewWarpChainRow,
|
|
@@ -95,6 +112,26 @@ export const TOKEN_USAGE_CONFIDENCE = ['real', 'high', 'estimated', 'coarse'] as
|
|
|
95
112
|
/** Transport types for token telemetry. */
|
|
96
113
|
export const TOKEN_USAGE_TRANSPORTS = ['cli', 'mcp', 'api', 'agent', 'unknown'] as const;
|
|
97
114
|
|
|
115
|
+
/** Task relation types matching DB CHECK constraint on task_relations.relation_type. */
|
|
116
|
+
export const TASK_RELATION_TYPES = [
|
|
117
|
+
'related',
|
|
118
|
+
'blocks',
|
|
119
|
+
'duplicates',
|
|
120
|
+
'absorbs',
|
|
121
|
+
'fixes',
|
|
122
|
+
'extends',
|
|
123
|
+
'supersedes',
|
|
124
|
+
] as const;
|
|
125
|
+
|
|
126
|
+
/** Lifecycle transition types matching DB CHECK constraint on lifecycle_transitions.transition_type. */
|
|
127
|
+
export const LIFECYCLE_TRANSITION_TYPES = ['automatic', 'manual', 'forced'] as const;
|
|
128
|
+
|
|
129
|
+
/** External task link types matching DB constraint on external_task_links.link_type. */
|
|
130
|
+
export const EXTERNAL_LINK_TYPES = ['created', 'matched', 'manual', 'transferred'] as const;
|
|
131
|
+
|
|
132
|
+
/** Sync direction types matching DB constraint on external_task_links.sync_direction. */
|
|
133
|
+
export const SYNC_DIRECTIONS = ['inbound', 'outbound', 'bidirectional'] as const;
|
|
134
|
+
|
|
98
135
|
// === TASKS TABLE ===
|
|
99
136
|
|
|
100
137
|
export const tasks = sqliteTable(
|
|
@@ -160,6 +197,7 @@ export const tasks = sqliteTable(
|
|
|
160
197
|
index('idx_tasks_phase').on(table.phase),
|
|
161
198
|
index('idx_tasks_type').on(table.type),
|
|
162
199
|
index('idx_tasks_priority').on(table.priority),
|
|
200
|
+
index('idx_tasks_session_id').on(table.sessionId),
|
|
163
201
|
],
|
|
164
202
|
);
|
|
165
203
|
|
|
@@ -193,13 +231,16 @@ export const taskRelations = sqliteTable(
|
|
|
193
231
|
.notNull()
|
|
194
232
|
.references(() => tasks.id, { onDelete: 'cascade' }),
|
|
195
233
|
relationType: text('relation_type', {
|
|
196
|
-
enum:
|
|
234
|
+
enum: TASK_RELATION_TYPES,
|
|
197
235
|
})
|
|
198
236
|
.notNull()
|
|
199
237
|
.default('related'),
|
|
200
238
|
reason: text('reason'),
|
|
201
239
|
},
|
|
202
|
-
(table) => [
|
|
240
|
+
(table) => [
|
|
241
|
+
primaryKey({ columns: [table.taskId, table.relatedTo] }),
|
|
242
|
+
index('idx_task_relations_related_to').on(table.relatedTo),
|
|
243
|
+
],
|
|
203
244
|
);
|
|
204
245
|
|
|
205
246
|
// === SESSIONS ===
|
|
@@ -225,8 +266,12 @@ export const sessions = sqliteTable(
|
|
|
225
266
|
startedAt: text('started_at').notNull().default(sql`(datetime('now'))`),
|
|
226
267
|
endedAt: text('ended_at'),
|
|
227
268
|
// Session chain columns (T4959)
|
|
228
|
-
previousSessionId: text('previous_session_id'),
|
|
229
|
-
|
|
269
|
+
previousSessionId: text('previous_session_id').references((): AnySQLiteColumn => sessions.id, {
|
|
270
|
+
onDelete: 'set null',
|
|
271
|
+
}),
|
|
272
|
+
nextSessionId: text('next_session_id').references((): AnySQLiteColumn => sessions.id, {
|
|
273
|
+
onDelete: 'set null',
|
|
274
|
+
}),
|
|
230
275
|
agentIdentifier: text('agent_identifier'),
|
|
231
276
|
handoffConsumedAt: text('handoff_consumed_at'),
|
|
232
277
|
handoffConsumedBy: text('handoff_consumed_by'),
|
|
@@ -242,6 +287,7 @@ export const sessions = sqliteTable(
|
|
|
242
287
|
index('idx_sessions_status').on(table.status),
|
|
243
288
|
index('idx_sessions_previous').on(table.previousSessionId),
|
|
244
289
|
index('idx_sessions_agent_identifier').on(table.agentIdentifier),
|
|
290
|
+
index('idx_sessions_started_at').on(table.startedAt),
|
|
245
291
|
],
|
|
246
292
|
);
|
|
247
293
|
|
|
@@ -325,6 +371,7 @@ export const lifecycleStages = sqliteTable(
|
|
|
325
371
|
index('idx_lifecycle_stages_pipeline_id').on(table.pipelineId),
|
|
326
372
|
index('idx_lifecycle_stages_stage_name').on(table.stageName),
|
|
327
373
|
index('idx_lifecycle_stages_status').on(table.status),
|
|
374
|
+
index('idx_lifecycle_stages_validated_by').on(table.validatedBy),
|
|
328
375
|
],
|
|
329
376
|
);
|
|
330
377
|
|
|
@@ -381,7 +428,7 @@ export const lifecycleTransitions = sqliteTable(
|
|
|
381
428
|
fromStageId: text('from_stage_id').notNull(),
|
|
382
429
|
toStageId: text('to_stage_id').notNull(),
|
|
383
430
|
transitionType: text('transition_type', {
|
|
384
|
-
enum:
|
|
431
|
+
enum: LIFECYCLE_TRANSITION_TYPES,
|
|
385
432
|
})
|
|
386
433
|
.notNull()
|
|
387
434
|
.default('automatic'),
|
|
@@ -524,6 +571,7 @@ export const auditLog = sqliteTable(
|
|
|
524
571
|
index('idx_audit_log_domain').on(table.domain),
|
|
525
572
|
index('idx_audit_log_request_id').on(table.requestId),
|
|
526
573
|
index('idx_audit_log_project_hash').on(table.projectHash),
|
|
574
|
+
index('idx_audit_log_actor').on(table.actor),
|
|
527
575
|
],
|
|
528
576
|
);
|
|
529
577
|
|
|
@@ -567,6 +615,7 @@ export const tokenUsage = sqliteTable(
|
|
|
567
615
|
index('idx_token_usage_transport').on(table.transport),
|
|
568
616
|
index('idx_token_usage_domain_operation').on(table.domain, table.operation),
|
|
569
617
|
index('idx_token_usage_method').on(table.method),
|
|
618
|
+
index('idx_token_usage_gateway').on(table.gateway),
|
|
570
619
|
],
|
|
571
620
|
);
|
|
572
621
|
|
|
@@ -603,7 +652,10 @@ export const architectureDecisions = sqliteTable(
|
|
|
603
652
|
keywords: text('keywords'),
|
|
604
653
|
topics: text('topics'),
|
|
605
654
|
},
|
|
606
|
-
(table) => [
|
|
655
|
+
(table) => [
|
|
656
|
+
index('idx_arch_decisions_status').on(table.status),
|
|
657
|
+
index('idx_arch_decisions_amends_id').on(table.amendsId),
|
|
658
|
+
],
|
|
607
659
|
);
|
|
608
660
|
|
|
609
661
|
// === ADR JUNCTION TABLES (ADR-017 §5.3) ===
|
|
@@ -673,11 +725,11 @@ export const externalTaskLinks = sqliteTable(
|
|
|
673
725
|
externalTitle: text('external_title'),
|
|
674
726
|
/** How this link was established. */
|
|
675
727
|
linkType: text('link_type', {
|
|
676
|
-
enum:
|
|
728
|
+
enum: EXTERNAL_LINK_TYPES,
|
|
677
729
|
}).notNull(),
|
|
678
730
|
/** Direction of the sync that created this link. */
|
|
679
731
|
syncDirection: text('sync_direction', {
|
|
680
|
-
enum:
|
|
732
|
+
enum: SYNC_DIRECTIONS,
|
|
681
733
|
})
|
|
682
734
|
.notNull()
|
|
683
735
|
.default('inbound'),
|
|
@@ -692,6 +744,11 @@ export const externalTaskLinks = sqliteTable(
|
|
|
692
744
|
index('idx_ext_links_task_id').on(table.taskId),
|
|
693
745
|
index('idx_ext_links_provider_external').on(table.providerId, table.externalId),
|
|
694
746
|
index('idx_ext_links_provider_id').on(table.providerId),
|
|
747
|
+
unique('uq_ext_links_task_provider_external').on(
|
|
748
|
+
table.taskId,
|
|
749
|
+
table.providerId,
|
|
750
|
+
table.externalId,
|
|
751
|
+
),
|
|
695
752
|
],
|
|
696
753
|
);
|
|
697
754
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { SQLInputValue, StatementSync } from 'node:sqlite';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Type-safe wrapper for {@link StatementSync.all} — centralizes the
|
|
5
|
+
* `as unknown as` cast required by node:sqlite's untyped return type.
|
|
6
|
+
*/
|
|
7
|
+
export function typedAll<T>(stmt: StatementSync, ...params: SQLInputValue[]): T[] {
|
|
8
|
+
return stmt.all(...params) as unknown as T[];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Type-safe wrapper for {@link StatementSync.get} — centralizes the
|
|
13
|
+
* `as unknown as` cast required by node:sqlite's untyped return type.
|
|
14
|
+
*/
|
|
15
|
+
export function typedGet<T>(stmt: StatementSync, ...params: SQLInputValue[]): T | undefined {
|
|
16
|
+
return stmt.get(...params) as unknown as T | undefined;
|
|
17
|
+
}
|