@jaimevalasek/aioson 1.3.0 → 1.4.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 +19 -2
- package/docs/pt/README.md +62 -2
- package/docs/pt/advisor-spec.md +5 -5
- package/docs/pt/agentes-customizados.md +670 -0
- package/docs/pt/agentes.md +111 -13
- package/docs/pt/automacao-squads.md +407 -0
- package/docs/pt/cenarios.md +3 -3
- package/docs/pt/clientes-ai.md +62 -0
- package/docs/pt/comandos-cli.md +167 -17
- package/docs/pt/deyvin.md +115 -0
- package/docs/pt/genome-3.0-spec.md +11 -11
- package/docs/pt/inicio-rapido.md +45 -0
- package/docs/pt/memoria-contexto.md +255 -0
- package/docs/pt/output-strategy-delivery.md +655 -0
- package/docs/pt/profiler-system.md +17 -17
- package/docs/pt/runtime-observability.md +5 -1
- package/docs/pt/skills.md +175 -0
- package/docs/pt/{squad-genoma.md → squad-genome.md} +81 -75
- package/docs/testing/genome-2.0-rollout.md +1 -1
- package/package.json +3 -3
- package/src/agents.js +21 -5
- package/src/backup-provider.js +303 -0
- package/src/cli.js +178 -2
- package/src/commands/agents.js +22 -4
- package/src/commands/backup.js +533 -0
- package/src/commands/cloud.js +17 -17
- package/src/commands/context-pack.js +45 -0
- package/src/commands/implementation-plan.js +340 -0
- package/src/commands/learning.js +134 -0
- package/src/commands/live.js +1583 -0
- package/src/commands/runtime.js +833 -2
- package/src/commands/scan-project.js +288 -24
- package/src/commands/setup-context.js +23 -0
- package/src/commands/skill.js +558 -0
- package/src/commands/squad-agent-create.js +788 -0
- package/src/commands/squad-doctor.js +51 -1
- package/src/commands/squad-investigate.js +261 -0
- package/src/commands/squad-learning.js +209 -0
- package/src/commands/squad-pipeline.js +247 -1
- package/src/commands/squad-plan.js +329 -0
- package/src/commands/squad-status.js +1 -1
- package/src/commands/squad-validate.js +57 -1
- package/src/commands/test-agents.js +6 -1
- package/src/commands/workflow-next.js +8 -1
- package/src/commands/workflow-status.js +250 -0
- package/src/constants.js +80 -16
- package/src/context-memory.js +837 -0
- package/src/context-writer.js +2 -0
- package/src/delivery-runner.js +319 -0
- package/src/genome-files.js +1 -1
- package/src/genome-format.js +1 -1
- package/src/i18n/messages/en.js +206 -7
- package/src/i18n/messages/es.js +123 -6
- package/src/i18n/messages/fr.js +122 -5
- package/src/i18n/messages/pt-BR.js +205 -12
- package/src/installer.js +30 -2
- package/src/lib/genomes/compat.js +1 -1
- package/src/runtime-store.js +780 -42
- package/src/session-handoff.js +77 -0
- package/template/.aioson/agents/analyst.md +36 -9
- package/template/.aioson/agents/architect.md +20 -5
- package/template/.aioson/agents/dev.md +135 -15
- package/template/.aioson/agents/deyvin.md +166 -0
- package/template/.aioson/agents/discovery-design-doc.md +25 -1
- package/template/.aioson/agents/{genoma.md → genome.md} +20 -20
- package/template/.aioson/agents/orache.md +371 -0
- package/template/.aioson/agents/orchestrator.md +37 -2
- package/template/.aioson/agents/pair.md +5 -0
- package/template/.aioson/agents/pm.md +17 -5
- package/template/.aioson/agents/product.md +58 -22
- package/template/.aioson/agents/profiler-enricher.md +1 -1
- package/template/.aioson/agents/profiler-forge.md +9 -9
- package/template/.aioson/agents/profiler-researcher.md +1 -1
- package/template/.aioson/agents/qa.md +17 -5
- package/template/.aioson/agents/setup.md +81 -5
- package/template/.aioson/agents/squad.md +675 -28
- package/template/.aioson/agents/ux-ui.md +277 -34
- package/template/.aioson/config.md +175 -0
- package/template/.aioson/context/spec.md.template +17 -0
- package/template/.aioson/genomes/.gitkeep +0 -0
- package/template/.aioson/installed-skills/.gitkeep +0 -0
- package/template/.aioson/locales/en/agents/analyst.md +26 -4
- package/template/.aioson/locales/en/agents/architect.md +10 -0
- package/template/.aioson/locales/en/agents/dev.md +89 -4
- package/template/.aioson/locales/en/agents/deyvin.md +129 -0
- package/template/.aioson/locales/en/agents/{genoma.md → genome.md} +14 -14
- package/template/.aioson/locales/en/agents/orchestrator.md +36 -2
- package/template/.aioson/locales/en/agents/pair.md +5 -0
- package/template/.aioson/locales/en/agents/pm.md +7 -0
- package/template/.aioson/locales/en/agents/product.md +35 -17
- package/template/.aioson/locales/en/agents/qa.md +7 -0
- package/template/.aioson/locales/en/agents/setup.md +51 -5
- package/template/.aioson/locales/en/agents/squad.md +203 -15
- package/template/.aioson/locales/en/agents/ux-ui.md +375 -35
- package/template/.aioson/locales/es/agents/analyst.md +16 -4
- package/template/.aioson/locales/es/agents/architect.md +10 -0
- package/template/.aioson/locales/es/agents/dev.md +70 -2
- package/template/.aioson/locales/es/agents/deyvin.md +89 -0
- package/template/.aioson/locales/es/agents/{genoma.md → genome.md} +13 -13
- package/template/.aioson/locales/es/agents/orache.md +103 -0
- package/template/.aioson/locales/es/agents/orchestrator.md +36 -2
- package/template/.aioson/locales/es/agents/pair.md +5 -0
- package/template/.aioson/locales/es/agents/pm.md +7 -0
- package/template/.aioson/locales/es/agents/product.md +13 -3
- package/template/.aioson/locales/es/agents/qa.md +7 -0
- package/template/.aioson/locales/es/agents/setup.md +28 -5
- package/template/.aioson/locales/es/agents/squad.md +221 -15
- package/template/.aioson/locales/es/agents/ux-ui.md +26 -25
- package/template/.aioson/locales/fr/agents/analyst.md +16 -4
- package/template/.aioson/locales/fr/agents/architect.md +10 -0
- package/template/.aioson/locales/fr/agents/dev.md +70 -2
- package/template/.aioson/locales/fr/agents/deyvin.md +89 -0
- package/template/.aioson/locales/fr/agents/{genoma.md → genome.md} +7 -7
- package/template/.aioson/locales/fr/agents/orache.md +104 -0
- package/template/.aioson/locales/fr/agents/orchestrator.md +36 -2
- package/template/.aioson/locales/fr/agents/pair.md +5 -0
- package/template/.aioson/locales/fr/agents/pm.md +7 -0
- package/template/.aioson/locales/fr/agents/product.md +13 -3
- package/template/.aioson/locales/fr/agents/qa.md +7 -0
- package/template/.aioson/locales/fr/agents/setup.md +28 -5
- package/template/.aioson/locales/fr/agents/squad.md +216 -10
- package/template/.aioson/locales/fr/agents/ux-ui.md +26 -25
- package/template/.aioson/locales/pt-BR/agents/analyst.md +26 -4
- package/template/.aioson/locales/pt-BR/agents/architect.md +10 -0
- package/template/.aioson/locales/pt-BR/agents/dev.md +93 -4
- package/template/.aioson/locales/pt-BR/agents/deyvin.md +129 -0
- package/template/.aioson/locales/pt-BR/agents/{genoma.md → genome.md} +49 -49
- package/template/.aioson/locales/pt-BR/agents/orache.md +137 -0
- package/template/.aioson/locales/pt-BR/agents/orchestrator.md +36 -2
- package/template/.aioson/locales/pt-BR/agents/pair.md +5 -0
- package/template/.aioson/locales/pt-BR/agents/pm.md +7 -0
- package/template/.aioson/locales/pt-BR/agents/product.md +35 -17
- package/template/.aioson/locales/pt-BR/agents/qa.md +7 -0
- package/template/.aioson/locales/pt-BR/agents/setup.md +51 -5
- package/template/.aioson/locales/pt-BR/agents/squad.md +486 -47
- package/template/.aioson/locales/pt-BR/agents/ux-ui.md +361 -22
- package/template/.aioson/my-agents/.gitkeep +0 -0
- package/template/.aioson/rules/.gitkeep +0 -0
- package/template/.aioson/rules/squad/.gitkeep +0 -0
- package/template/.aioson/rules/squad/README.md +50 -0
- package/template/.aioson/schemas/genome-meta.schema.json +1 -1
- package/template/.aioson/schemas/genome.schema.json +1 -1
- package/template/.aioson/schemas/squad-blueprint.schema.json +11 -0
- package/template/.aioson/schemas/squad-manifest.schema.json +257 -1
- package/template/.aioson/skills/design/cognitive-core-ui/SKILL.md +157 -0
- package/template/.aioson/skills/design/cognitive-core-ui/references/components.md +407 -0
- package/template/.aioson/skills/design/cognitive-core-ui/references/dashboards.md +172 -0
- package/template/.aioson/skills/design/cognitive-core-ui/references/design-tokens.md +490 -0
- package/template/.aioson/skills/design/cognitive-core-ui/references/motion.md +237 -0
- package/template/.aioson/skills/design/cognitive-core-ui/references/patterns.md +289 -0
- package/template/.aioson/skills/design/cognitive-core-ui/references/websites.md +350 -0
- package/template/.aioson/skills/design/interface-design/SKILL.md +47 -0
- package/template/.aioson/skills/design/interface-design/references/components-and-states.md +105 -0
- package/template/.aioson/skills/design/interface-design/references/design-directions.md +101 -0
- package/template/.aioson/skills/design/interface-design/references/handoff-and-quality.md +71 -0
- package/template/.aioson/skills/design/interface-design/references/intent-and-domain.md +74 -0
- package/template/.aioson/skills/design/interface-design/references/tokens-and-depth.md +173 -0
- package/template/.aioson/skills/design/premium-command-center-ui/SKILL.md +62 -0
- package/template/.aioson/skills/design/premium-command-center-ui/references/operations.md +74 -0
- package/template/.aioson/skills/design/premium-command-center-ui/references/patterns.md +116 -0
- package/template/.aioson/skills/design/premium-command-center-ui/references/validation.md +47 -0
- package/template/.aioson/skills/design/premium-command-center-ui/references/visual-system.md +215 -0
- package/template/.aioson/skills/design-system/SKILL.md +92 -0
- package/template/.aioson/skills/design-system/cognitive-core-ui.skill +0 -0
- package/template/.aioson/skills/design-system/components/SKILL.md +274 -0
- package/template/.aioson/skills/design-system/components/SKILL.md:Zone.Identifier +0 -0
- package/template/.aioson/skills/design-system/dashboards/SKILL.md +184 -0
- package/template/.aioson/skills/design-system/dashboards/SKILL.md:Zone.Identifier +0 -0
- package/template/.aioson/skills/design-system/foundations/SKILL.md +250 -0
- package/template/.aioson/skills/design-system/foundations/SKILL.md:Zone.Identifier +0 -0
- package/template/.aioson/skills/design-system/motion/SKILL.md +197 -0
- package/template/.aioson/skills/design-system/motion/SKILL.md:Zone.Identifier +0 -0
- package/template/.aioson/skills/design-system/patterns/SKILL.md +231 -0
- package/template/.aioson/skills/design-system/patterns/SKILL.md:Zone.Identifier +0 -0
- package/template/.aioson/skills/squad/SKILL.md +58 -0
- package/template/.aioson/skills/squad/domains/.gitkeep +0 -0
- package/template/.aioson/skills/squad/formats/.gitkeep +0 -0
- package/template/.aioson/skills/squad/patterns/.gitkeep +0 -0
- package/template/.aioson/skills/squad/references/.gitkeep +0 -0
- package/template/.aioson/tasks/implementation-plan.md +288 -0
- package/template/.aioson/tasks/squad-create.md +1 -1
- package/template/.aioson/tasks/squad-execution-plan.md +279 -0
- package/template/.aioson/tasks/squad-export.md +1 -1
- package/template/.aioson/tasks/squad-investigate.md +44 -0
- package/template/.aioson/tasks/squad-learning-review.md +44 -0
- package/template/.aioson/tasks/squad-output-config.md +177 -0
- package/template/.aioson/tasks/squad-validate.md +1 -1
- package/template/.claude/commands/aioson/agent/deyvin.md +5 -0
- package/template/.claude/commands/aioson/agent/discovery-design-doc.md +5 -0
- package/template/.claude/commands/aioson/agent/genome.md +5 -0
- package/template/.claude/commands/aioson/agent/product.md +5 -0
- package/template/.claude/commands/aioson/agent/profiler-enricher.md +5 -0
- package/template/.claude/commands/aioson/agent/profiler-forge.md +5 -0
- package/template/.claude/commands/aioson/agent/profiler-researcher.md +5 -0
- package/template/.claude/commands/aioson/agent/squad.md +5 -0
- package/template/.gemini/GEMINI.md +2 -0
- package/template/.gemini/commands/aios-deyvin.toml +6 -0
- package/template/.gemini/commands/aios-pair.toml +6 -0
- package/template/AGENTS.md +34 -6
- package/template/CLAUDE.md +31 -4
- package/template/OPENCODE.md +6 -2
- package/template/squad-searches/.gitkeep +0 -0
- package/template/.aioson/skills/static/interface-design.md +0 -372
- package/template/.aioson/skills/static/premium-command-center-ui.md +0 -190
- /package/template/.aioson/{genomas → docs}/.gitkeep +0 -0
- /package/template/.claude/commands/aioson/{analyst.md → agent/analyst.md} +0 -0
- /package/template/.claude/commands/aioson/{architect.md → agent/architect.md} +0 -0
- /package/template/.claude/commands/aioson/{dev.md → agent/dev.md} +0 -0
- /package/template/.claude/commands/aioson/{orchestrator.md → agent/orchestrator.md} +0 -0
- /package/template/.claude/commands/aioson/{pm.md → agent/pm.md} +0 -0
- /package/template/.claude/commands/aioson/{qa.md → agent/qa.md} +0 -0
- /package/template/.claude/commands/aioson/{setup.md → agent/setup.md} +0 -0
- /package/template/.claude/commands/aioson/{ux-ui.md → agent/ux-ui.md} +0 -0
package/src/runtime-store.js
CHANGED
|
@@ -12,6 +12,7 @@ const {
|
|
|
12
12
|
|
|
13
13
|
const RUNTIME_DIR = path.join('.aioson', 'runtime');
|
|
14
14
|
const DB_FILE = 'aios.sqlite';
|
|
15
|
+
const LOGS_DIR = 'aioson-logs';
|
|
15
16
|
const SESSIONS_DIR = '.sessions';
|
|
16
17
|
const VALID_STATUSES = new Set(['queued', 'running', 'completed', 'failed']);
|
|
17
18
|
const VALID_TASK_STATUSES = new Set(['queued', 'running', 'completed', 'failed']);
|
|
@@ -32,7 +33,8 @@ function resolveRuntimePaths(targetDir) {
|
|
|
32
33
|
const runtimeDir = path.join(targetDir, RUNTIME_DIR);
|
|
33
34
|
return {
|
|
34
35
|
runtimeDir,
|
|
35
|
-
dbPath: path.join(runtimeDir, DB_FILE)
|
|
36
|
+
dbPath: path.join(runtimeDir, DB_FILE),
|
|
37
|
+
logsDir: path.join(targetDir, LOGS_DIR)
|
|
36
38
|
};
|
|
37
39
|
}
|
|
38
40
|
|
|
@@ -42,7 +44,7 @@ async function runtimeStoreExists(targetDir) {
|
|
|
42
44
|
}
|
|
43
45
|
|
|
44
46
|
async function openRuntimeDb(targetDir, options = {}) {
|
|
45
|
-
const { runtimeDir, dbPath } = resolveRuntimePaths(targetDir);
|
|
47
|
+
const { runtimeDir, dbPath, logsDir } = resolveRuntimePaths(targetDir);
|
|
46
48
|
const mustExist = Boolean(options.mustExist);
|
|
47
49
|
|
|
48
50
|
if (mustExist && !(await exists(dbPath))) {
|
|
@@ -50,6 +52,7 @@ async function openRuntimeDb(targetDir, options = {}) {
|
|
|
50
52
|
}
|
|
51
53
|
|
|
52
54
|
await ensureDir(runtimeDir);
|
|
55
|
+
await ensureDir(logsDir);
|
|
53
56
|
|
|
54
57
|
const db = new Database(dbPath);
|
|
55
58
|
db.pragma('journal_mode = WAL');
|
|
@@ -125,8 +128,11 @@ async function openRuntimeDb(targetDir, options = {}) {
|
|
|
125
128
|
task_key TEXT PRIMARY KEY,
|
|
126
129
|
squad_slug TEXT,
|
|
127
130
|
session_key TEXT,
|
|
131
|
+
task_kind TEXT,
|
|
132
|
+
parent_task_key TEXT,
|
|
128
133
|
title TEXT NOT NULL,
|
|
129
134
|
goal TEXT,
|
|
135
|
+
meta_json TEXT,
|
|
130
136
|
status TEXT NOT NULL,
|
|
131
137
|
created_by TEXT,
|
|
132
138
|
created_at TEXT NOT NULL,
|
|
@@ -351,6 +357,145 @@ async function openRuntimeDb(targetDir, options = {}) {
|
|
|
351
357
|
|
|
352
358
|
CREATE INDEX IF NOT EXISTS idx_artisan_squads_status ON artisan_squads(status, updated_at DESC);
|
|
353
359
|
CREATE INDEX IF NOT EXISTS idx_artisan_messages_artisan ON artisan_messages(artisan_id, created_at ASC);
|
|
360
|
+
|
|
361
|
+
CREATE TABLE IF NOT EXISTS delivery_log (
|
|
362
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
363
|
+
squad_slug TEXT NOT NULL,
|
|
364
|
+
content_key TEXT,
|
|
365
|
+
webhook_slug TEXT,
|
|
366
|
+
trigger_type TEXT NOT NULL,
|
|
367
|
+
url TEXT NOT NULL,
|
|
368
|
+
status_code INTEGER,
|
|
369
|
+
response_body TEXT,
|
|
370
|
+
error_message TEXT,
|
|
371
|
+
attempt INTEGER DEFAULT 1,
|
|
372
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
373
|
+
);
|
|
374
|
+
|
|
375
|
+
CREATE INDEX IF NOT EXISTS idx_delivery_log_squad ON delivery_log(squad_slug);
|
|
376
|
+
CREATE INDEX IF NOT EXISTS idx_delivery_log_content ON delivery_log(content_key);
|
|
377
|
+
|
|
378
|
+
CREATE TABLE IF NOT EXISTS backup_manifest (
|
|
379
|
+
record_key TEXT PRIMARY KEY,
|
|
380
|
+
record_type TEXT NOT NULL,
|
|
381
|
+
content_hash TEXT NOT NULL,
|
|
382
|
+
backed_up_at TEXT NOT NULL,
|
|
383
|
+
remote_key TEXT NOT NULL
|
|
384
|
+
);
|
|
385
|
+
CREATE INDEX IF NOT EXISTS idx_backup_manifest_type ON backup_manifest(record_type, backed_up_at DESC);
|
|
386
|
+
|
|
387
|
+
CREATE TABLE IF NOT EXISTS squad_investigations (
|
|
388
|
+
investigation_slug TEXT PRIMARY KEY,
|
|
389
|
+
domain TEXT NOT NULL,
|
|
390
|
+
mode TEXT DEFAULT 'full',
|
|
391
|
+
dimensions_covered INTEGER DEFAULT 0,
|
|
392
|
+
total_dimensions INTEGER DEFAULT 7,
|
|
393
|
+
confidence REAL DEFAULT 0,
|
|
394
|
+
report_path TEXT,
|
|
395
|
+
linked_squad_slug TEXT,
|
|
396
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
397
|
+
updated_at TEXT DEFAULT (datetime('now'))
|
|
398
|
+
);
|
|
399
|
+
|
|
400
|
+
CREATE INDEX IF NOT EXISTS idx_squad_investigations_domain ON squad_investigations(domain);
|
|
401
|
+
CREATE INDEX IF NOT EXISTS idx_squad_investigations_squad ON squad_investigations(linked_squad_slug);
|
|
402
|
+
|
|
403
|
+
CREATE TABLE IF NOT EXISTS implementation_plans (
|
|
404
|
+
plan_id TEXT PRIMARY KEY,
|
|
405
|
+
project_name TEXT,
|
|
406
|
+
scope TEXT DEFAULT 'project',
|
|
407
|
+
feature_slug TEXT,
|
|
408
|
+
status TEXT DEFAULT 'draft',
|
|
409
|
+
classification TEXT,
|
|
410
|
+
phases_total INTEGER DEFAULT 0,
|
|
411
|
+
phases_completed INTEGER DEFAULT 0,
|
|
412
|
+
source_artifacts TEXT,
|
|
413
|
+
source_hash TEXT,
|
|
414
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
415
|
+
updated_at TEXT DEFAULT (datetime('now'))
|
|
416
|
+
);
|
|
417
|
+
|
|
418
|
+
CREATE TABLE IF NOT EXISTS plan_phases (
|
|
419
|
+
plan_id TEXT NOT NULL,
|
|
420
|
+
phase_number INTEGER NOT NULL,
|
|
421
|
+
title TEXT NOT NULL,
|
|
422
|
+
status TEXT DEFAULT 'pending',
|
|
423
|
+
completed_at TEXT,
|
|
424
|
+
notes TEXT,
|
|
425
|
+
PRIMARY KEY (plan_id, phase_number),
|
|
426
|
+
FOREIGN KEY (plan_id) REFERENCES implementation_plans(plan_id)
|
|
427
|
+
);
|
|
428
|
+
|
|
429
|
+
CREATE TABLE IF NOT EXISTS squad_execution_plans (
|
|
430
|
+
plan_slug TEXT PRIMARY KEY,
|
|
431
|
+
squad_slug TEXT NOT NULL,
|
|
432
|
+
status TEXT DEFAULT 'draft',
|
|
433
|
+
rounds_total INTEGER DEFAULT 0,
|
|
434
|
+
rounds_completed INTEGER DEFAULT 0,
|
|
435
|
+
based_on_blueprint TEXT,
|
|
436
|
+
based_on_investigation TEXT,
|
|
437
|
+
source_hash TEXT,
|
|
438
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
439
|
+
updated_at TEXT DEFAULT (datetime('now'))
|
|
440
|
+
);
|
|
441
|
+
|
|
442
|
+
CREATE TABLE IF NOT EXISTS squad_plan_rounds (
|
|
443
|
+
plan_slug TEXT NOT NULL,
|
|
444
|
+
round_number INTEGER NOT NULL,
|
|
445
|
+
executor_slug TEXT NOT NULL,
|
|
446
|
+
title TEXT NOT NULL,
|
|
447
|
+
status TEXT DEFAULT 'pending',
|
|
448
|
+
completed_at TEXT,
|
|
449
|
+
notes TEXT,
|
|
450
|
+
PRIMARY KEY (plan_slug, round_number),
|
|
451
|
+
FOREIGN KEY (plan_slug) REFERENCES squad_execution_plans(plan_slug)
|
|
452
|
+
);
|
|
453
|
+
|
|
454
|
+
CREATE TABLE IF NOT EXISTS squad_learnings (
|
|
455
|
+
learning_id TEXT PRIMARY KEY,
|
|
456
|
+
squad_slug TEXT NOT NULL,
|
|
457
|
+
type TEXT NOT NULL CHECK (type IN ('preference', 'process', 'domain', 'quality')),
|
|
458
|
+
title TEXT NOT NULL,
|
|
459
|
+
signal TEXT DEFAULT 'explicit' CHECK (signal IN ('explicit', 'implicit')),
|
|
460
|
+
confidence TEXT DEFAULT 'medium' CHECK (confidence IN ('high', 'medium', 'low')),
|
|
461
|
+
frequency INTEGER DEFAULT 1,
|
|
462
|
+
last_reinforced TEXT,
|
|
463
|
+
applies_to TEXT DEFAULT 'squad',
|
|
464
|
+
file_path TEXT,
|
|
465
|
+
promoted_to TEXT,
|
|
466
|
+
status TEXT DEFAULT 'active' CHECK (status IN ('active', 'stale', 'archived', 'promoted')),
|
|
467
|
+
source_session TEXT,
|
|
468
|
+
evidence TEXT,
|
|
469
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
470
|
+
updated_at TEXT DEFAULT (datetime('now'))
|
|
471
|
+
);
|
|
472
|
+
|
|
473
|
+
CREATE TABLE IF NOT EXISTS project_learnings (
|
|
474
|
+
learning_id TEXT PRIMARY KEY,
|
|
475
|
+
project_name TEXT,
|
|
476
|
+
feature_slug TEXT,
|
|
477
|
+
type TEXT NOT NULL CHECK (type IN ('preference', 'process', 'domain', 'quality')),
|
|
478
|
+
title TEXT NOT NULL,
|
|
479
|
+
confidence TEXT DEFAULT 'medium',
|
|
480
|
+
frequency INTEGER DEFAULT 1,
|
|
481
|
+
last_reinforced TEXT,
|
|
482
|
+
applies_to TEXT DEFAULT 'project',
|
|
483
|
+
promoted_to TEXT,
|
|
484
|
+
status TEXT DEFAULT 'active' CHECK (status IN ('active', 'stale', 'archived', 'promoted')),
|
|
485
|
+
source_session TEXT,
|
|
486
|
+
evidence TEXT,
|
|
487
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
488
|
+
updated_at TEXT DEFAULT (datetime('now'))
|
|
489
|
+
);
|
|
490
|
+
|
|
491
|
+
CREATE INDEX IF NOT EXISTS idx_impl_plans_status ON implementation_plans(status);
|
|
492
|
+
CREATE INDEX IF NOT EXISTS idx_squad_exec_plans_squad ON squad_execution_plans(squad_slug);
|
|
493
|
+
CREATE INDEX IF NOT EXISTS idx_squad_exec_plans_status ON squad_execution_plans(status);
|
|
494
|
+
CREATE INDEX IF NOT EXISTS idx_squad_learnings_squad ON squad_learnings(squad_slug);
|
|
495
|
+
CREATE INDEX IF NOT EXISTS idx_squad_learnings_type ON squad_learnings(type);
|
|
496
|
+
CREATE INDEX IF NOT EXISTS idx_squad_learnings_status ON squad_learnings(status);
|
|
497
|
+
CREATE INDEX IF NOT EXISTS idx_project_learnings_type ON project_learnings(type);
|
|
498
|
+
CREATE INDEX IF NOT EXISTS idx_project_learnings_status ON project_learnings(status);
|
|
354
499
|
`);
|
|
355
500
|
|
|
356
501
|
ensureLegacyColumns(db);
|
|
@@ -381,6 +526,25 @@ function normalizeTaskStatus(value, fallback) {
|
|
|
381
526
|
}
|
|
382
527
|
|
|
383
528
|
function ensureLegacyColumns(db) {
|
|
529
|
+
const taskColumns = db.prepare('PRAGMA table_info(tasks)').all();
|
|
530
|
+
const taskColumnNames = new Set(taskColumns.map((column) => column.name));
|
|
531
|
+
|
|
532
|
+
if (!taskColumnNames.has('task_kind')) {
|
|
533
|
+
db.exec('ALTER TABLE tasks ADD COLUMN task_kind TEXT');
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
if (!taskColumnNames.has('parent_task_key')) {
|
|
537
|
+
db.exec('ALTER TABLE tasks ADD COLUMN parent_task_key TEXT');
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
if (!taskColumnNames.has('meta_json')) {
|
|
541
|
+
db.exec('ALTER TABLE tasks ADD COLUMN meta_json TEXT');
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
db.exec('CREATE INDEX IF NOT EXISTS idx_tasks_session ON tasks(session_key, updated_at DESC)');
|
|
545
|
+
db.exec('CREATE INDEX IF NOT EXISTS idx_tasks_parent ON tasks(parent_task_key, updated_at DESC)');
|
|
546
|
+
db.exec('CREATE INDEX IF NOT EXISTS idx_tasks_kind ON tasks(task_kind, updated_at DESC)');
|
|
547
|
+
|
|
384
548
|
const agentRunColumns = db.prepare('PRAGMA table_info(agent_runs)').all();
|
|
385
549
|
const agentRunColumnNames = new Set(agentRunColumns.map((column) => column.name));
|
|
386
550
|
|
|
@@ -498,56 +662,66 @@ function appendRunEvent(db, options) {
|
|
|
498
662
|
const now = options.createdAt || nowIso();
|
|
499
663
|
const payloadJson = options.payload ? JSON.stringify(options.payload) : null;
|
|
500
664
|
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
665
|
+
const doInsert = db.transaction(() => {
|
|
666
|
+
insertEvent(db, {
|
|
667
|
+
run_key: run.run_key,
|
|
668
|
+
event_type: String(options.eventType || 'update'),
|
|
669
|
+
message: String(options.message || ''),
|
|
670
|
+
payload_json: payloadJson,
|
|
671
|
+
created_at: now
|
|
672
|
+
});
|
|
508
673
|
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
674
|
+
insertExecutionEvent(db, {
|
|
675
|
+
task_key: run.task_key,
|
|
676
|
+
run_key: run.run_key,
|
|
677
|
+
agent_name: run.agent_name,
|
|
678
|
+
agent_kind: run.agent_kind,
|
|
679
|
+
squad_slug: run.squad_slug,
|
|
680
|
+
session_key: run.session_key,
|
|
681
|
+
source: run.source,
|
|
682
|
+
workflow_id: run.workflow_id,
|
|
683
|
+
workflow_stage: run.workflow_stage,
|
|
684
|
+
parent_run_key: run.parent_run_key,
|
|
685
|
+
event_type: String(options.eventType || 'update'),
|
|
686
|
+
phase: options.phase ? String(options.phase).trim() : null,
|
|
687
|
+
status: options.status ? String(options.status).trim() : run.status || null,
|
|
688
|
+
tool_name: options.toolName ? String(options.toolName).trim() : null,
|
|
689
|
+
message: String(options.message || ''),
|
|
690
|
+
payload_json: payloadJson,
|
|
691
|
+
sequence_no: nextExecutionSequence(db, run.run_key),
|
|
692
|
+
parent_event_id: options.parentEventId || null,
|
|
693
|
+
created_at: now
|
|
694
|
+
});
|
|
529
695
|
});
|
|
696
|
+
|
|
697
|
+
doInsert();
|
|
530
698
|
}
|
|
531
699
|
|
|
532
700
|
function startTask(db, options) {
|
|
533
701
|
const now = nowIso();
|
|
534
702
|
const taskKey = String(options.taskKey || createTaskKey(options.title));
|
|
535
703
|
const status = normalizeTaskStatus(options.status, 'running');
|
|
704
|
+
const metaJson = options.metaJson && typeof options.metaJson === 'object'
|
|
705
|
+
? JSON.stringify(options.metaJson)
|
|
706
|
+
: (typeof options.metaJson === 'string' && options.metaJson.trim() ? options.metaJson.trim() : null);
|
|
536
707
|
|
|
537
708
|
db.prepare(`
|
|
538
709
|
INSERT INTO tasks (
|
|
539
|
-
task_key, squad_slug, session_key,
|
|
540
|
-
created_at, updated_at, finished_at
|
|
710
|
+
task_key, squad_slug, session_key, task_kind, parent_task_key,
|
|
711
|
+
title, goal, meta_json, status, created_by, created_at, updated_at, finished_at
|
|
541
712
|
) VALUES (
|
|
542
|
-
@task_key, @squad_slug, @session_key, @
|
|
543
|
-
@created_at, @updated_at, @finished_at
|
|
713
|
+
@task_key, @squad_slug, @session_key, @task_kind, @parent_task_key,
|
|
714
|
+
@title, @goal, @meta_json, @status, @created_by, @created_at, @updated_at, @finished_at
|
|
544
715
|
)
|
|
545
716
|
`).run({
|
|
546
717
|
task_key: taskKey,
|
|
547
718
|
squad_slug: options.squadSlug ? String(options.squadSlug).trim() : null,
|
|
548
719
|
session_key: options.sessionKey ? String(options.sessionKey).trim() : null,
|
|
720
|
+
task_kind: options.taskKind ? String(options.taskKind).trim() : null,
|
|
721
|
+
parent_task_key: options.parentTaskKey ? String(options.parentTaskKey).trim() : null,
|
|
549
722
|
title: String(options.title).trim(),
|
|
550
723
|
goal: options.goal ? String(options.goal).trim() : null,
|
|
724
|
+
meta_json: metaJson,
|
|
551
725
|
status,
|
|
552
726
|
created_by: options.createdBy ? String(options.createdBy).trim() : null,
|
|
553
727
|
created_at: now,
|
|
@@ -566,12 +740,18 @@ function updateTask(db, options) {
|
|
|
566
740
|
|
|
567
741
|
const now = nowIso();
|
|
568
742
|
const nextStatus = normalizeTaskStatus(options.status, existing.status || 'running');
|
|
743
|
+
const metaJson = options.metaJson && typeof options.metaJson === 'object'
|
|
744
|
+
? JSON.stringify(options.metaJson)
|
|
745
|
+
: (typeof options.metaJson === 'string' && options.metaJson.trim() ? options.metaJson.trim() : null);
|
|
569
746
|
|
|
570
747
|
db.prepare(`
|
|
571
748
|
UPDATE tasks
|
|
572
749
|
SET
|
|
573
750
|
status = @status,
|
|
574
751
|
goal = COALESCE(@goal, goal),
|
|
752
|
+
task_kind = COALESCE(@task_kind, task_kind),
|
|
753
|
+
parent_task_key = COALESCE(@parent_task_key, parent_task_key),
|
|
754
|
+
meta_json = COALESCE(@meta_json, meta_json),
|
|
575
755
|
updated_at = @updated_at,
|
|
576
756
|
finished_at = CASE
|
|
577
757
|
WHEN @status IN ('completed', 'failed') THEN @updated_at
|
|
@@ -582,6 +762,9 @@ function updateTask(db, options) {
|
|
|
582
762
|
task_key: String(options.taskKey),
|
|
583
763
|
status: nextStatus,
|
|
584
764
|
goal: options.goal ? String(options.goal).trim() : null,
|
|
765
|
+
task_kind: options.taskKind ? String(options.taskKind).trim() : null,
|
|
766
|
+
parent_task_key: options.parentTaskKey ? String(options.parentTaskKey).trim() : null,
|
|
767
|
+
meta_json: metaJson,
|
|
585
768
|
updated_at: now
|
|
586
769
|
});
|
|
587
770
|
|
|
@@ -696,6 +879,52 @@ function parseJsonArray(value) {
|
|
|
696
879
|
}
|
|
697
880
|
}
|
|
698
881
|
|
|
882
|
+
|
|
883
|
+
function parseJsonObject(value) {
|
|
884
|
+
if (!value) return null;
|
|
885
|
+
try {
|
|
886
|
+
const parsed = JSON.parse(value);
|
|
887
|
+
return parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? parsed : null;
|
|
888
|
+
} catch {
|
|
889
|
+
return null;
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
function getTaskPlanProgress(meta) {
|
|
894
|
+
const steps = Array.isArray(meta?.plan_steps) ? meta.plan_steps : [];
|
|
895
|
+
return {
|
|
896
|
+
plan_steps_done: steps.filter((step) => step && step.done).length,
|
|
897
|
+
plan_steps_total: steps.length
|
|
898
|
+
};
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
function decorateTaskSnapshotRow(row) {
|
|
902
|
+
const meta = parseJsonObject(row.meta_json);
|
|
903
|
+
const progress = getTaskPlanProgress(meta);
|
|
904
|
+
row.meta = meta;
|
|
905
|
+
row.plan_steps_done = progress.plan_steps_done;
|
|
906
|
+
row.plan_steps_total = progress.plan_steps_total;
|
|
907
|
+
row.is_live_session = row.task_kind === 'live_session';
|
|
908
|
+
row.is_micro_task = row.task_kind === 'micro_task';
|
|
909
|
+
return row;
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
function decorateRunSnapshotRow(row) {
|
|
913
|
+
row.used_skills = parseJsonArray(row.used_skills_json);
|
|
914
|
+
row.is_live = row.source === 'live';
|
|
915
|
+
row.is_handoff_child = Boolean(row.parent_run_key);
|
|
916
|
+
return row;
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
function decorateExecutionEventSnapshotRow(row) {
|
|
920
|
+
const payload = parseJsonObject(row.payload_json);
|
|
921
|
+
row.payload = payload;
|
|
922
|
+
row.is_handoff = row.event_type === 'handoff';
|
|
923
|
+
row.handoff_from = payload?.from || row.agent_name || null;
|
|
924
|
+
row.handoff_to = payload?.to || null;
|
|
925
|
+
return row;
|
|
926
|
+
}
|
|
927
|
+
|
|
699
928
|
function upsertSquadManifest(db, options) {
|
|
700
929
|
const now = nowIso();
|
|
701
930
|
const slug = String(options.slug).trim();
|
|
@@ -1110,7 +1339,7 @@ function startRun(db, options) {
|
|
|
1110
1339
|
|
|
1111
1340
|
appendRunEvent(db, {
|
|
1112
1341
|
runKey,
|
|
1113
|
-
eventType: 'start',
|
|
1342
|
+
eventType: String(options.eventType || 'start'),
|
|
1114
1343
|
phase: options.phase || 'run',
|
|
1115
1344
|
status,
|
|
1116
1345
|
message: String(options.message || options.title || 'Agent started'),
|
|
@@ -1242,7 +1471,7 @@ function getStatusSnapshot(db) {
|
|
|
1242
1471
|
|
|
1243
1472
|
const activeTasks = db.prepare(`
|
|
1244
1473
|
SELECT
|
|
1245
|
-
task_key, squad_slug, session_key, title, goal, status, created_by, created_at, updated_at,
|
|
1474
|
+
task_key, squad_slug, session_key, task_kind, parent_task_key, title, goal, meta_json, status, created_by, created_at, updated_at,
|
|
1246
1475
|
(
|
|
1247
1476
|
SELECT COUNT(*)
|
|
1248
1477
|
FROM agent_runs
|
|
@@ -1252,7 +1481,29 @@ function getStatusSnapshot(db) {
|
|
|
1252
1481
|
SELECT COUNT(*)
|
|
1253
1482
|
FROM artifacts
|
|
1254
1483
|
WHERE artifacts.task_key = tasks.task_key
|
|
1255
|
-
) AS artifact_count
|
|
1484
|
+
) AS artifact_count,
|
|
1485
|
+
(
|
|
1486
|
+
SELECT agent_name
|
|
1487
|
+
FROM agent_runs
|
|
1488
|
+
WHERE agent_runs.task_key = tasks.task_key
|
|
1489
|
+
ORDER BY CASE WHEN agent_runs.status IN ('queued', 'running') THEN 0 ELSE 1 END, updated_at DESC, started_at DESC
|
|
1490
|
+
LIMIT 1
|
|
1491
|
+
) AS latest_agent_name,
|
|
1492
|
+
(
|
|
1493
|
+
SELECT COUNT(*)
|
|
1494
|
+
FROM tasks AS child_tasks
|
|
1495
|
+
WHERE child_tasks.parent_task_key = tasks.task_key
|
|
1496
|
+
) AS child_task_count,
|
|
1497
|
+
(
|
|
1498
|
+
SELECT COUNT(*)
|
|
1499
|
+
FROM tasks AS child_tasks
|
|
1500
|
+
WHERE child_tasks.parent_task_key = tasks.task_key AND child_tasks.status = 'completed'
|
|
1501
|
+
) AS completed_child_task_count,
|
|
1502
|
+
(
|
|
1503
|
+
SELECT COUNT(*)
|
|
1504
|
+
FROM agent_runs AS handoff_runs
|
|
1505
|
+
WHERE handoff_runs.task_key = tasks.task_key AND handoff_runs.parent_run_key IS NOT NULL
|
|
1506
|
+
) AS handoff_count
|
|
1256
1507
|
FROM tasks
|
|
1257
1508
|
WHERE status IN ('queued', 'running')
|
|
1258
1509
|
ORDER BY updated_at DESC, created_at DESC
|
|
@@ -1260,7 +1511,7 @@ function getStatusSnapshot(db) {
|
|
|
1260
1511
|
|
|
1261
1512
|
const recentTasks = db.prepare(`
|
|
1262
1513
|
SELECT
|
|
1263
|
-
task_key, squad_slug, session_key, title, goal, status, created_by, created_at, updated_at, finished_at,
|
|
1514
|
+
task_key, squad_slug, session_key, task_kind, parent_task_key, title, goal, meta_json, status, created_by, created_at, updated_at, finished_at,
|
|
1264
1515
|
(
|
|
1265
1516
|
SELECT COUNT(*)
|
|
1266
1517
|
FROM agent_runs
|
|
@@ -1270,7 +1521,29 @@ function getStatusSnapshot(db) {
|
|
|
1270
1521
|
SELECT COUNT(*)
|
|
1271
1522
|
FROM artifacts
|
|
1272
1523
|
WHERE artifacts.task_key = tasks.task_key
|
|
1273
|
-
) AS artifact_count
|
|
1524
|
+
) AS artifact_count,
|
|
1525
|
+
(
|
|
1526
|
+
SELECT agent_name
|
|
1527
|
+
FROM agent_runs
|
|
1528
|
+
WHERE agent_runs.task_key = tasks.task_key
|
|
1529
|
+
ORDER BY CASE WHEN agent_runs.status IN ('queued', 'running') THEN 0 ELSE 1 END, updated_at DESC, started_at DESC
|
|
1530
|
+
LIMIT 1
|
|
1531
|
+
) AS latest_agent_name,
|
|
1532
|
+
(
|
|
1533
|
+
SELECT COUNT(*)
|
|
1534
|
+
FROM tasks AS child_tasks
|
|
1535
|
+
WHERE child_tasks.parent_task_key = tasks.task_key
|
|
1536
|
+
) AS child_task_count,
|
|
1537
|
+
(
|
|
1538
|
+
SELECT COUNT(*)
|
|
1539
|
+
FROM tasks AS child_tasks
|
|
1540
|
+
WHERE child_tasks.parent_task_key = tasks.task_key AND child_tasks.status = 'completed'
|
|
1541
|
+
) AS completed_child_task_count,
|
|
1542
|
+
(
|
|
1543
|
+
SELECT COUNT(*)
|
|
1544
|
+
FROM agent_runs AS handoff_runs
|
|
1545
|
+
WHERE handoff_runs.task_key = tasks.task_key AND handoff_runs.parent_run_key IS NOT NULL
|
|
1546
|
+
) AS handoff_count
|
|
1274
1547
|
FROM tasks
|
|
1275
1548
|
ORDER BY updated_at DESC, created_at DESC
|
|
1276
1549
|
LIMIT 20
|
|
@@ -1303,17 +1576,35 @@ function getStatusSnapshot(db) {
|
|
|
1303
1576
|
`).all();
|
|
1304
1577
|
|
|
1305
1578
|
for (const row of activeRuns) {
|
|
1306
|
-
|
|
1579
|
+
decorateRunSnapshotRow(row);
|
|
1307
1580
|
}
|
|
1308
1581
|
|
|
1309
1582
|
for (const row of recentRuns) {
|
|
1310
|
-
|
|
1583
|
+
decorateRunSnapshotRow(row);
|
|
1584
|
+
}
|
|
1585
|
+
|
|
1586
|
+
for (const row of activeTasks) {
|
|
1587
|
+
decorateTaskSnapshotRow(row);
|
|
1588
|
+
}
|
|
1589
|
+
|
|
1590
|
+
for (const row of recentTasks) {
|
|
1591
|
+
decorateTaskSnapshotRow(row);
|
|
1311
1592
|
}
|
|
1312
1593
|
|
|
1313
1594
|
for (const row of recentContentItems) {
|
|
1314
1595
|
row.used_skills = parseJsonArray(row.used_skills_json);
|
|
1315
1596
|
}
|
|
1316
1597
|
|
|
1598
|
+
for (const row of recentExecutionEvents) {
|
|
1599
|
+
decorateExecutionEventSnapshotRow(row);
|
|
1600
|
+
}
|
|
1601
|
+
|
|
1602
|
+
const activeLiveSessions = activeTasks.filter((task) => task.task_kind === 'live_session');
|
|
1603
|
+
const activeMicroTasks = activeTasks.filter((task) => task.task_kind === 'micro_task');
|
|
1604
|
+
const recentLiveSessions = recentTasks.filter((task) => task.task_kind === 'live_session');
|
|
1605
|
+
const recentMicroTasks = recentTasks.filter((task) => task.task_kind === 'micro_task');
|
|
1606
|
+
const recentHandoffs = recentExecutionEvents.filter((event) => event.event_type === 'handoff');
|
|
1607
|
+
|
|
1317
1608
|
return {
|
|
1318
1609
|
taskCounts,
|
|
1319
1610
|
counts,
|
|
@@ -1321,6 +1612,11 @@ function getStatusSnapshot(db) {
|
|
|
1321
1612
|
recentTasks,
|
|
1322
1613
|
activeRuns,
|
|
1323
1614
|
recentRuns,
|
|
1615
|
+
activeLiveSessions,
|
|
1616
|
+
activeMicroTasks,
|
|
1617
|
+
recentLiveSessions,
|
|
1618
|
+
recentMicroTasks,
|
|
1619
|
+
recentHandoffs,
|
|
1324
1620
|
recentArtifacts,
|
|
1325
1621
|
recentContentItems,
|
|
1326
1622
|
recentExecutionEvents
|
|
@@ -1374,6 +1670,7 @@ async function clearAgentSession(runtimeDir, agentName) {
|
|
|
1374
1670
|
async function logAgentEvent(db, runtimeDir, options) {
|
|
1375
1671
|
const agentName = String(options.agentName || 'unknown').trim();
|
|
1376
1672
|
const squadSlug = options.squadSlug ? String(options.squadSlug).trim() : null;
|
|
1673
|
+
const sessionKey = options.sessionKey ? String(options.sessionKey).trim() : null;
|
|
1377
1674
|
const isFinish = Boolean(options.finish);
|
|
1378
1675
|
const now = nowIso();
|
|
1379
1676
|
|
|
@@ -1442,6 +1739,7 @@ async function logAgentEvent(db, runtimeDir, options) {
|
|
|
1442
1739
|
taskKey = startTask(db, {
|
|
1443
1740
|
title: taskTitle,
|
|
1444
1741
|
squadSlug: null,
|
|
1742
|
+
sessionKey,
|
|
1445
1743
|
status: 'running',
|
|
1446
1744
|
createdBy: agentName
|
|
1447
1745
|
});
|
|
@@ -1450,10 +1748,11 @@ async function logAgentEvent(db, runtimeDir, options) {
|
|
|
1450
1748
|
agentName,
|
|
1451
1749
|
agentKind: 'official',
|
|
1452
1750
|
squadSlug: null,
|
|
1751
|
+
sessionKey,
|
|
1453
1752
|
title: taskTitle,
|
|
1454
1753
|
message: options.message || 'Iniciando'
|
|
1455
1754
|
});
|
|
1456
|
-
await writeAgentSession(runtimeDir, agentName, { runKey, taskKey, startedAt: now, finished: false });
|
|
1755
|
+
await writeAgentSession(runtimeDir, agentName, { runKey, taskKey, sessionKey, startedAt: now, finished: false });
|
|
1457
1756
|
} else {
|
|
1458
1757
|
appendRunEvent(db, {
|
|
1459
1758
|
runKey,
|
|
@@ -1487,6 +1786,405 @@ async function logAgentEvent(db, runtimeDir, options) {
|
|
|
1487
1786
|
return { runKey, taskKey };
|
|
1488
1787
|
}
|
|
1489
1788
|
|
|
1789
|
+
// --- Squad Investigations CRUD ---
|
|
1790
|
+
|
|
1791
|
+
function insertInvestigation(db, options = {}) {
|
|
1792
|
+
const slug = options.investigationSlug || `inv-${slugify(options.domain || 'unknown')}-${Date.now()}`;
|
|
1793
|
+
const now = nowIso();
|
|
1794
|
+
db.prepare(`
|
|
1795
|
+
INSERT OR REPLACE INTO squad_investigations
|
|
1796
|
+
(investigation_slug, domain, mode, dimensions_covered, total_dimensions,
|
|
1797
|
+
confidence, report_path, linked_squad_slug, created_at, updated_at)
|
|
1798
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
1799
|
+
`).run(
|
|
1800
|
+
slug,
|
|
1801
|
+
String(options.domain || ''),
|
|
1802
|
+
String(options.mode || 'full'),
|
|
1803
|
+
Number(options.dimensionsCovered) || 0,
|
|
1804
|
+
Number(options.totalDimensions) || 7,
|
|
1805
|
+
Number(options.confidence) || 0,
|
|
1806
|
+
options.reportPath || null,
|
|
1807
|
+
options.linkedSquadSlug || null,
|
|
1808
|
+
now,
|
|
1809
|
+
now
|
|
1810
|
+
);
|
|
1811
|
+
return slug;
|
|
1812
|
+
}
|
|
1813
|
+
|
|
1814
|
+
function listInvestigations(db) {
|
|
1815
|
+
return db.prepare(`
|
|
1816
|
+
SELECT * FROM squad_investigations ORDER BY created_at DESC
|
|
1817
|
+
`).all();
|
|
1818
|
+
}
|
|
1819
|
+
|
|
1820
|
+
function getInvestigation(db, slug) {
|
|
1821
|
+
return db.prepare(`
|
|
1822
|
+
SELECT * FROM squad_investigations WHERE investigation_slug = ?
|
|
1823
|
+
`).get(slug) || null;
|
|
1824
|
+
}
|
|
1825
|
+
|
|
1826
|
+
function linkInvestigation(db, investigationSlug, squadSlug) {
|
|
1827
|
+
const now = nowIso();
|
|
1828
|
+
const result = db.prepare(`
|
|
1829
|
+
UPDATE squad_investigations
|
|
1830
|
+
SET linked_squad_slug = ?, updated_at = ?
|
|
1831
|
+
WHERE investigation_slug = ?
|
|
1832
|
+
`).run(squadSlug, now, investigationSlug);
|
|
1833
|
+
return result.changes > 0;
|
|
1834
|
+
}
|
|
1835
|
+
|
|
1836
|
+
// --- Implementation Plans CRUD ---
|
|
1837
|
+
|
|
1838
|
+
function upsertImplementationPlan(db, options = {}) {
|
|
1839
|
+
const planId = options.planId || `plan-${slugify(options.projectName || 'proj')}-${Date.now()}`;
|
|
1840
|
+
const now = nowIso();
|
|
1841
|
+
db.prepare(`
|
|
1842
|
+
INSERT OR REPLACE INTO implementation_plans
|
|
1843
|
+
(plan_id, project_name, scope, feature_slug, status, classification,
|
|
1844
|
+
phases_total, phases_completed, source_artifacts, source_hash, created_at, updated_at)
|
|
1845
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
1846
|
+
`).run(
|
|
1847
|
+
planId,
|
|
1848
|
+
options.projectName || null,
|
|
1849
|
+
options.scope || 'project',
|
|
1850
|
+
options.featureSlug || null,
|
|
1851
|
+
options.status || 'draft',
|
|
1852
|
+
options.classification || null,
|
|
1853
|
+
Number(options.phasesTotal) || 0,
|
|
1854
|
+
Number(options.phasesCompleted) || 0,
|
|
1855
|
+
options.sourceArtifacts ? JSON.stringify(options.sourceArtifacts) : null,
|
|
1856
|
+
options.sourceHash || null,
|
|
1857
|
+
now,
|
|
1858
|
+
now
|
|
1859
|
+
);
|
|
1860
|
+
return planId;
|
|
1861
|
+
}
|
|
1862
|
+
|
|
1863
|
+
function getImplementationPlan(db, planId) {
|
|
1864
|
+
return db.prepare(`
|
|
1865
|
+
SELECT * FROM implementation_plans WHERE plan_id = ?
|
|
1866
|
+
`).get(planId) || null;
|
|
1867
|
+
}
|
|
1868
|
+
|
|
1869
|
+
function listImplementationPlans(db) {
|
|
1870
|
+
return db.prepare(`
|
|
1871
|
+
SELECT * FROM implementation_plans ORDER BY created_at DESC
|
|
1872
|
+
`).all();
|
|
1873
|
+
}
|
|
1874
|
+
|
|
1875
|
+
function updateImplementationPlanStatus(db, planId, status) {
|
|
1876
|
+
const now = nowIso();
|
|
1877
|
+
const result = db.prepare(`
|
|
1878
|
+
UPDATE implementation_plans SET status = ?, updated_at = ? WHERE plan_id = ?
|
|
1879
|
+
`).run(status, now, planId);
|
|
1880
|
+
return result.changes > 0;
|
|
1881
|
+
}
|
|
1882
|
+
|
|
1883
|
+
function upsertPlanPhase(db, planId, phaseNumber, title, status) {
|
|
1884
|
+
db.prepare(`
|
|
1885
|
+
INSERT OR REPLACE INTO plan_phases (plan_id, phase_number, title, status, completed_at)
|
|
1886
|
+
VALUES (?, ?, ?, ?, ?)
|
|
1887
|
+
`).run(
|
|
1888
|
+
planId,
|
|
1889
|
+
phaseNumber,
|
|
1890
|
+
title,
|
|
1891
|
+
status || 'pending',
|
|
1892
|
+
status === 'completed' ? nowIso() : null
|
|
1893
|
+
);
|
|
1894
|
+
}
|
|
1895
|
+
|
|
1896
|
+
function updatePlanPhaseStatus(db, planId, phaseNumber, status, notes) {
|
|
1897
|
+
const now = nowIso();
|
|
1898
|
+
const result = db.prepare(`
|
|
1899
|
+
UPDATE plan_phases SET status = ?, completed_at = ?, notes = ?
|
|
1900
|
+
WHERE plan_id = ? AND phase_number = ?
|
|
1901
|
+
`).run(
|
|
1902
|
+
status,
|
|
1903
|
+
status === 'completed' ? now : null,
|
|
1904
|
+
notes || null,
|
|
1905
|
+
planId,
|
|
1906
|
+
phaseNumber
|
|
1907
|
+
);
|
|
1908
|
+
if (result.changes > 0 && status === 'completed') {
|
|
1909
|
+
db.prepare(`
|
|
1910
|
+
UPDATE implementation_plans
|
|
1911
|
+
SET phases_completed = (SELECT COUNT(*) FROM plan_phases WHERE plan_id = ? AND status = 'completed'),
|
|
1912
|
+
updated_at = ?
|
|
1913
|
+
WHERE plan_id = ?
|
|
1914
|
+
`).run(planId, now, planId);
|
|
1915
|
+
}
|
|
1916
|
+
return result.changes > 0;
|
|
1917
|
+
}
|
|
1918
|
+
|
|
1919
|
+
function getPlanPhases(db, planId) {
|
|
1920
|
+
return db.prepare(`
|
|
1921
|
+
SELECT * FROM plan_phases WHERE plan_id = ? ORDER BY phase_number
|
|
1922
|
+
`).all(planId);
|
|
1923
|
+
}
|
|
1924
|
+
|
|
1925
|
+
// --- Squad Execution Plans CRUD ---
|
|
1926
|
+
|
|
1927
|
+
function upsertSquadExecutionPlan(db, options = {}) {
|
|
1928
|
+
const planSlug = options.planSlug || `sqplan-${slugify(options.squadSlug || 'squad')}-${Date.now()}`;
|
|
1929
|
+
const now = nowIso();
|
|
1930
|
+
db.prepare(`
|
|
1931
|
+
INSERT OR REPLACE INTO squad_execution_plans
|
|
1932
|
+
(plan_slug, squad_slug, status, rounds_total, rounds_completed,
|
|
1933
|
+
based_on_blueprint, based_on_investigation, source_hash, created_at, updated_at)
|
|
1934
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
1935
|
+
`).run(
|
|
1936
|
+
planSlug,
|
|
1937
|
+
options.squadSlug || '',
|
|
1938
|
+
options.status || 'draft',
|
|
1939
|
+
Number(options.roundsTotal) || 0,
|
|
1940
|
+
Number(options.roundsCompleted) || 0,
|
|
1941
|
+
options.basedOnBlueprint || null,
|
|
1942
|
+
options.basedOnInvestigation || null,
|
|
1943
|
+
options.sourceHash || null,
|
|
1944
|
+
now,
|
|
1945
|
+
now
|
|
1946
|
+
);
|
|
1947
|
+
return planSlug;
|
|
1948
|
+
}
|
|
1949
|
+
|
|
1950
|
+
function getSquadExecutionPlan(db, planSlug) {
|
|
1951
|
+
return db.prepare(`
|
|
1952
|
+
SELECT * FROM squad_execution_plans WHERE plan_slug = ?
|
|
1953
|
+
`).get(planSlug) || null;
|
|
1954
|
+
}
|
|
1955
|
+
|
|
1956
|
+
function getSquadExecutionPlanBySquad(db, squadSlug) {
|
|
1957
|
+
return db.prepare(`
|
|
1958
|
+
SELECT * FROM squad_execution_plans WHERE squad_slug = ? ORDER BY created_at DESC LIMIT 1
|
|
1959
|
+
`).get(squadSlug) || null;
|
|
1960
|
+
}
|
|
1961
|
+
|
|
1962
|
+
function listSquadExecutionPlans(db) {
|
|
1963
|
+
return db.prepare(`
|
|
1964
|
+
SELECT * FROM squad_execution_plans ORDER BY created_at DESC
|
|
1965
|
+
`).all();
|
|
1966
|
+
}
|
|
1967
|
+
|
|
1968
|
+
function updateSquadExecutionPlanStatus(db, planSlug, status) {
|
|
1969
|
+
const now = nowIso();
|
|
1970
|
+
const result = db.prepare(`
|
|
1971
|
+
UPDATE squad_execution_plans SET status = ?, updated_at = ? WHERE plan_slug = ?
|
|
1972
|
+
`).run(status, now, planSlug);
|
|
1973
|
+
return result.changes > 0;
|
|
1974
|
+
}
|
|
1975
|
+
|
|
1976
|
+
function upsertSquadPlanRound(db, planSlug, roundNumber, executorSlug, title, status) {
|
|
1977
|
+
db.prepare(`
|
|
1978
|
+
INSERT OR REPLACE INTO squad_plan_rounds (plan_slug, round_number, executor_slug, title, status, completed_at)
|
|
1979
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
1980
|
+
`).run(
|
|
1981
|
+
planSlug,
|
|
1982
|
+
roundNumber,
|
|
1983
|
+
executorSlug,
|
|
1984
|
+
title,
|
|
1985
|
+
status || 'pending',
|
|
1986
|
+
status === 'completed' ? nowIso() : null
|
|
1987
|
+
);
|
|
1988
|
+
}
|
|
1989
|
+
|
|
1990
|
+
function updateSquadPlanRoundStatus(db, planSlug, roundNumber, status, notes) {
|
|
1991
|
+
const now = nowIso();
|
|
1992
|
+
const result = db.prepare(`
|
|
1993
|
+
UPDATE squad_plan_rounds SET status = ?, completed_at = ?, notes = ?
|
|
1994
|
+
WHERE plan_slug = ? AND round_number = ?
|
|
1995
|
+
`).run(
|
|
1996
|
+
status,
|
|
1997
|
+
status === 'completed' ? now : null,
|
|
1998
|
+
notes || null,
|
|
1999
|
+
planSlug,
|
|
2000
|
+
roundNumber
|
|
2001
|
+
);
|
|
2002
|
+
if (result.changes > 0 && status === 'completed') {
|
|
2003
|
+
db.prepare(`
|
|
2004
|
+
UPDATE squad_execution_plans
|
|
2005
|
+
SET rounds_completed = (SELECT COUNT(*) FROM squad_plan_rounds WHERE plan_slug = ? AND status = 'completed'),
|
|
2006
|
+
updated_at = ?
|
|
2007
|
+
WHERE plan_slug = ?
|
|
2008
|
+
`).run(planSlug, now, planSlug);
|
|
2009
|
+
}
|
|
2010
|
+
return result.changes > 0;
|
|
2011
|
+
}
|
|
2012
|
+
|
|
2013
|
+
function getSquadPlanRounds(db, planSlug) {
|
|
2014
|
+
return db.prepare(`
|
|
2015
|
+
SELECT * FROM squad_plan_rounds WHERE plan_slug = ? ORDER BY round_number
|
|
2016
|
+
`).all(planSlug);
|
|
2017
|
+
}
|
|
2018
|
+
|
|
2019
|
+
// --- Squad Learnings CRUD ---
|
|
2020
|
+
|
|
2021
|
+
function insertSquadLearning(db, options = {}) {
|
|
2022
|
+
const learningId = options.learningId || `sl-${slugify(options.squadSlug || 'squad')}-${Date.now()}`;
|
|
2023
|
+
const now = nowIso();
|
|
2024
|
+
db.prepare(`
|
|
2025
|
+
INSERT OR REPLACE INTO squad_learnings
|
|
2026
|
+
(learning_id, squad_slug, type, title, signal, confidence, frequency,
|
|
2027
|
+
last_reinforced, applies_to, file_path, promoted_to, status,
|
|
2028
|
+
source_session, evidence, created_at, updated_at)
|
|
2029
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
2030
|
+
`).run(
|
|
2031
|
+
learningId,
|
|
2032
|
+
options.squadSlug || '',
|
|
2033
|
+
options.type || 'preference',
|
|
2034
|
+
options.title || '',
|
|
2035
|
+
options.signal || 'explicit',
|
|
2036
|
+
options.confidence || 'medium',
|
|
2037
|
+
Number(options.frequency) || 1,
|
|
2038
|
+
options.lastReinforced || now,
|
|
2039
|
+
options.appliesTo || 'squad',
|
|
2040
|
+
options.filePath || null,
|
|
2041
|
+
options.promotedTo || null,
|
|
2042
|
+
options.status || 'active',
|
|
2043
|
+
options.sourceSession || null,
|
|
2044
|
+
options.evidence || null,
|
|
2045
|
+
now,
|
|
2046
|
+
now
|
|
2047
|
+
);
|
|
2048
|
+
return learningId;
|
|
2049
|
+
}
|
|
2050
|
+
|
|
2051
|
+
function listSquadLearnings(db, squadSlug, statusFilter) {
|
|
2052
|
+
if (statusFilter) {
|
|
2053
|
+
return db.prepare(`
|
|
2054
|
+
SELECT * FROM squad_learnings WHERE squad_slug = ? AND status = ? ORDER BY created_at DESC
|
|
2055
|
+
`).all(squadSlug, statusFilter);
|
|
2056
|
+
}
|
|
2057
|
+
return db.prepare(`
|
|
2058
|
+
SELECT * FROM squad_learnings WHERE squad_slug = ? ORDER BY created_at DESC
|
|
2059
|
+
`).all(squadSlug);
|
|
2060
|
+
}
|
|
2061
|
+
|
|
2062
|
+
function getSquadLearning(db, learningId) {
|
|
2063
|
+
return db.prepare(`
|
|
2064
|
+
SELECT * FROM squad_learnings WHERE learning_id = ?
|
|
2065
|
+
`).get(learningId) || null;
|
|
2066
|
+
}
|
|
2067
|
+
|
|
2068
|
+
function updateSquadLearningStatus(db, learningId, status) {
|
|
2069
|
+
const now = nowIso();
|
|
2070
|
+
const result = db.prepare(`
|
|
2071
|
+
UPDATE squad_learnings SET status = ?, updated_at = ? WHERE learning_id = ?
|
|
2072
|
+
`).run(status, now, learningId);
|
|
2073
|
+
return result.changes > 0;
|
|
2074
|
+
}
|
|
2075
|
+
|
|
2076
|
+
function reinforceSquadLearning(db, learningId) {
|
|
2077
|
+
const now = nowIso();
|
|
2078
|
+
const result = db.prepare(`
|
|
2079
|
+
UPDATE squad_learnings SET frequency = frequency + 1, last_reinforced = ?, updated_at = ? WHERE learning_id = ?
|
|
2080
|
+
`).run(now, now, learningId);
|
|
2081
|
+
return result.changes > 0;
|
|
2082
|
+
}
|
|
2083
|
+
|
|
2084
|
+
function promoteSquadLearning(db, learningId, promotedTo) {
|
|
2085
|
+
const now = nowIso();
|
|
2086
|
+
const result = db.prepare(`
|
|
2087
|
+
UPDATE squad_learnings SET status = 'promoted', promoted_to = ?, updated_at = ? WHERE learning_id = ?
|
|
2088
|
+
`).run(promotedTo, now, learningId);
|
|
2089
|
+
return result.changes > 0;
|
|
2090
|
+
}
|
|
2091
|
+
|
|
2092
|
+
function archiveStaleSquadLearnings(db, squadSlug, staleDays) {
|
|
2093
|
+
const days = Number(staleDays) || 90;
|
|
2094
|
+
const cutoff = new Date(Date.now() - days * 86400000).toISOString();
|
|
2095
|
+
const result = db.prepare(`
|
|
2096
|
+
UPDATE squad_learnings SET status = 'stale', updated_at = datetime('now')
|
|
2097
|
+
WHERE squad_slug = ? AND status = 'active' AND last_reinforced < ?
|
|
2098
|
+
`).run(squadSlug, cutoff);
|
|
2099
|
+
return result.changes;
|
|
2100
|
+
}
|
|
2101
|
+
|
|
2102
|
+
function getSquadLearningStats(db, squadSlug) {
|
|
2103
|
+
return db.prepare(`
|
|
2104
|
+
SELECT type, status, COUNT(*) as count FROM squad_learnings
|
|
2105
|
+
WHERE squad_slug = ? GROUP BY type, status ORDER BY type, status
|
|
2106
|
+
`).all(squadSlug);
|
|
2107
|
+
}
|
|
2108
|
+
|
|
2109
|
+
// --- Project Learnings CRUD ---
|
|
2110
|
+
|
|
2111
|
+
function insertProjectLearning(db, options = {}) {
|
|
2112
|
+
const learningId = options.learningId || `pl-${slugify(options.projectName || 'proj')}-${Date.now()}`;
|
|
2113
|
+
const now = nowIso();
|
|
2114
|
+
db.prepare(`
|
|
2115
|
+
INSERT OR REPLACE INTO project_learnings
|
|
2116
|
+
(learning_id, project_name, feature_slug, type, title, confidence, frequency,
|
|
2117
|
+
last_reinforced, applies_to, promoted_to, status,
|
|
2118
|
+
source_session, evidence, created_at, updated_at)
|
|
2119
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
2120
|
+
`).run(
|
|
2121
|
+
learningId,
|
|
2122
|
+
options.projectName || null,
|
|
2123
|
+
options.featureSlug || null,
|
|
2124
|
+
options.type || 'preference',
|
|
2125
|
+
options.title || '',
|
|
2126
|
+
options.confidence || 'medium',
|
|
2127
|
+
Number(options.frequency) || 1,
|
|
2128
|
+
options.lastReinforced || now,
|
|
2129
|
+
options.appliesTo || 'project',
|
|
2130
|
+
options.promotedTo || null,
|
|
2131
|
+
options.status || 'active',
|
|
2132
|
+
options.sourceSession || null,
|
|
2133
|
+
options.evidence || null,
|
|
2134
|
+
now,
|
|
2135
|
+
now
|
|
2136
|
+
);
|
|
2137
|
+
return learningId;
|
|
2138
|
+
}
|
|
2139
|
+
|
|
2140
|
+
function listProjectLearnings(db, statusFilter) {
|
|
2141
|
+
if (statusFilter) {
|
|
2142
|
+
return db.prepare(`
|
|
2143
|
+
SELECT * FROM project_learnings WHERE status = ? ORDER BY created_at DESC
|
|
2144
|
+
`).all(statusFilter);
|
|
2145
|
+
}
|
|
2146
|
+
return db.prepare(`
|
|
2147
|
+
SELECT * FROM project_learnings ORDER BY created_at DESC
|
|
2148
|
+
`).all();
|
|
2149
|
+
}
|
|
2150
|
+
|
|
2151
|
+
function getProjectLearning(db, learningId) {
|
|
2152
|
+
return db.prepare(`
|
|
2153
|
+
SELECT * FROM project_learnings WHERE learning_id = ?
|
|
2154
|
+
`).get(learningId) || null;
|
|
2155
|
+
}
|
|
2156
|
+
|
|
2157
|
+
function updateProjectLearningStatus(db, learningId, status) {
|
|
2158
|
+
const now = nowIso();
|
|
2159
|
+
const result = db.prepare(`
|
|
2160
|
+
UPDATE project_learnings SET status = ?, updated_at = ? WHERE learning_id = ?
|
|
2161
|
+
`).run(status, now, learningId);
|
|
2162
|
+
return result.changes > 0;
|
|
2163
|
+
}
|
|
2164
|
+
|
|
2165
|
+
function reinforceProjectLearning(db, learningId) {
|
|
2166
|
+
const now = nowIso();
|
|
2167
|
+
const result = db.prepare(`
|
|
2168
|
+
UPDATE project_learnings SET frequency = frequency + 1, last_reinforced = ?, updated_at = ? WHERE learning_id = ?
|
|
2169
|
+
`).run(now, now, learningId);
|
|
2170
|
+
return result.changes > 0;
|
|
2171
|
+
}
|
|
2172
|
+
|
|
2173
|
+
function promoteProjectLearning(db, learningId, promotedTo) {
|
|
2174
|
+
const now = nowIso();
|
|
2175
|
+
const result = db.prepare(`
|
|
2176
|
+
UPDATE project_learnings SET status = 'promoted', promoted_to = ?, updated_at = ? WHERE learning_id = ?
|
|
2177
|
+
`).run(promotedTo, now, learningId);
|
|
2178
|
+
return result.changes > 0;
|
|
2179
|
+
}
|
|
2180
|
+
|
|
2181
|
+
function getProjectLearningStats(db) {
|
|
2182
|
+
return db.prepare(`
|
|
2183
|
+
SELECT type, status, COUNT(*) as count FROM project_learnings
|
|
2184
|
+
GROUP BY type, status ORDER BY type, status
|
|
2185
|
+
`).all();
|
|
2186
|
+
}
|
|
2187
|
+
|
|
1490
2188
|
module.exports = {
|
|
1491
2189
|
resolveRuntimePaths,
|
|
1492
2190
|
runtimeStoreExists,
|
|
@@ -1505,6 +2203,7 @@ module.exports = {
|
|
|
1505
2203
|
appendRunEvent,
|
|
1506
2204
|
logAgentEvent,
|
|
1507
2205
|
readAgentSession,
|
|
2206
|
+
writeAgentSession,
|
|
1508
2207
|
clearAgentSession,
|
|
1509
2208
|
// Pipeline CRUD
|
|
1510
2209
|
upsertPipeline,
|
|
@@ -1523,5 +2222,44 @@ module.exports = {
|
|
|
1523
2222
|
listArtisanSquads,
|
|
1524
2223
|
deleteArtisanSquad,
|
|
1525
2224
|
addArtisanMessage,
|
|
1526
|
-
getArtisanMessages
|
|
2225
|
+
getArtisanMessages,
|
|
2226
|
+
// Investigation CRUD
|
|
2227
|
+
insertInvestigation,
|
|
2228
|
+
listInvestigations,
|
|
2229
|
+
getInvestigation,
|
|
2230
|
+
linkInvestigation,
|
|
2231
|
+
// Implementation Plans CRUD
|
|
2232
|
+
upsertImplementationPlan,
|
|
2233
|
+
getImplementationPlan,
|
|
2234
|
+
listImplementationPlans,
|
|
2235
|
+
updateImplementationPlanStatus,
|
|
2236
|
+
upsertPlanPhase,
|
|
2237
|
+
updatePlanPhaseStatus,
|
|
2238
|
+
getPlanPhases,
|
|
2239
|
+
// Squad Execution Plans CRUD
|
|
2240
|
+
upsertSquadExecutionPlan,
|
|
2241
|
+
getSquadExecutionPlan,
|
|
2242
|
+
getSquadExecutionPlanBySquad,
|
|
2243
|
+
listSquadExecutionPlans,
|
|
2244
|
+
updateSquadExecutionPlanStatus,
|
|
2245
|
+
upsertSquadPlanRound,
|
|
2246
|
+
updateSquadPlanRoundStatus,
|
|
2247
|
+
getSquadPlanRounds,
|
|
2248
|
+
// Squad Learnings CRUD
|
|
2249
|
+
insertSquadLearning,
|
|
2250
|
+
listSquadLearnings,
|
|
2251
|
+
getSquadLearning,
|
|
2252
|
+
updateSquadLearningStatus,
|
|
2253
|
+
reinforceSquadLearning,
|
|
2254
|
+
promoteSquadLearning,
|
|
2255
|
+
archiveStaleSquadLearnings,
|
|
2256
|
+
getSquadLearningStats,
|
|
2257
|
+
// Project Learnings CRUD
|
|
2258
|
+
insertProjectLearning,
|
|
2259
|
+
listProjectLearnings,
|
|
2260
|
+
getProjectLearning,
|
|
2261
|
+
updateProjectLearningStatus,
|
|
2262
|
+
reinforceProjectLearning,
|
|
2263
|
+
promoteProjectLearning,
|
|
2264
|
+
getProjectLearningStats
|
|
1527
2265
|
};
|