@cleocode/cleo 2026.3.4 → 2026.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/dist/cli/index.js +2277 -609
  2. package/dist/cli/index.js.map +4 -4
  3. package/dist/mcp/index.js +1838 -443
  4. package/dist/mcp/index.js.map +4 -4
  5. package/package.json +1 -1
  6. package/packages/ct-skills/index.js +1 -1
  7. package/packages/ct-skills/package.json +0 -2
  8. package/packages/ct-skills/profiles/core.json +1 -1
  9. package/packages/ct-skills/profiles/full.json +4 -5
  10. package/packages/ct-skills/profiles/minimal.json +3 -3
  11. package/packages/ct-skills/profiles/recommended.json +2 -2
  12. package/packages/ct-skills/provider-skills-map.json +97 -0
  13. package/packages/ct-skills/skills/_shared/skill-chaining-patterns.md +23 -26
  14. package/packages/ct-skills/skills/_shared/testing-framework-config.md +9 -9
  15. package/packages/ct-skills/skills/ct-cleo/SKILL.md +21 -1
  16. package/packages/ct-skills/skills/ct-dev-workflow/SKILL.md +1 -1
  17. package/packages/ct-skills/skills/ct-documentor/SKILL.md +1 -1
  18. package/packages/ct-skills/skills/ct-epic-architect/SKILL.md +1 -1
  19. package/packages/ct-skills/skills/ct-orchestrator/SKILL.md +119 -43
  20. package/packages/ct-skills/skills/ct-orchestrator/orchestrator-prompt.txt +17 -0
  21. package/packages/ct-skills/skills/ct-orchestrator/references/orchestrator-patterns.md +1 -1
  22. package/packages/ct-skills/skills/ct-research-agent/SKILL.md +1 -1
  23. package/packages/ct-skills/skills/ct-spec-writer/SKILL.md +1 -1
  24. package/packages/ct-skills/skills/ct-task-executor/SKILL.md +1 -1
  25. package/packages/ct-skills/skills/ct-validator/SKILL.md +1 -1
  26. package/packages/ct-skills/skills/manifest.json +217 -947
  27. package/packages/ct-skills/skills.json +244 -3
  28. package/templates/CLEO-INJECTION.md +24 -0
  29. package/packages/ct-skills/protocols/agent-protocol.md +0 -260
  30. package/packages/ct-skills/protocols/artifact-publish.md +0 -587
  31. package/packages/ct-skills/protocols/consensus.md +0 -309
  32. package/packages/ct-skills/protocols/contribution.md +0 -375
  33. package/packages/ct-skills/protocols/decomposition.md +0 -352
  34. package/packages/ct-skills/protocols/implementation.md +0 -344
  35. package/packages/ct-skills/protocols/provenance.md +0 -600
  36. package/packages/ct-skills/protocols/release.md +0 -635
  37. package/packages/ct-skills/protocols/research.md +0 -248
  38. package/packages/ct-skills/protocols/specification.md +0 -287
  39. package/packages/ct-skills/protocols/testing.md +0 -346
  40. package/packages/ct-skills/protocols/validation.md +0 -229
  41. package/packages/ct-skills/skills/ct-gitbook/SKILL.md +0 -516
  42. package/packages/ct-skills/skills/ct-gitbook/assets/SUMMARY.md +0 -28
  43. package/packages/ct-skills/skills/ct-gitbook/assets/gitbook.yaml +0 -14
  44. package/packages/ct-skills/skills/ct-gitbook/references/api-sdk.md +0 -318
  45. package/packages/ct-skills/skills/ct-gitbook/references/auth-sso.md +0 -208
  46. package/packages/ct-skills/skills/ct-gitbook/references/change-requests.md +0 -169
  47. package/packages/ct-skills/skills/ct-gitbook/references/content-blocks.md +0 -230
  48. package/packages/ct-skills/skills/ct-gitbook/references/docs-sites.md +0 -202
  49. package/packages/ct-skills/skills/ct-gitbook/references/git-sync.md +0 -175
  50. package/packages/ct-skills/skills/ct-gitbook/references/llm-ready.md +0 -178
  51. package/packages/ct-skills/skills/ct-gitbook/references/migration.md +0 -263
  52. package/packages/ct-skills/skills/ct-library-implementer-bash/SKILL.md +0 -316
  53. package/packages/ct-skills/skills/ct-skill-lookup/SKILL.md +0 -179
  54. package/packages/ct-skills/skills/ct-test-writer-bats/SKILL.md +0 -347
  55. package/packages/ct-skills/skills/railway-platform/SKILL.md +0 -506
  56. package/packages/ct-skills/skills/railway-platform/_shared/scripts/railway-api.sh +0 -180
  57. package/packages/ct-skills/skills/railway-platform/_shared/scripts/railway-common.sh +0 -262
  58. package/packages/ct-skills/skills/railway-platform/references/01-getting-started.md +0 -149
  59. package/packages/ct-skills/skills/railway-platform/references/02-projects.md +0 -116
  60. package/packages/ct-skills/skills/railway-platform/references/03-services.md +0 -147
  61. package/packages/ct-skills/skills/railway-platform/references/04-deployments.md +0 -210
  62. package/packages/ct-skills/skills/railway-platform/references/05-databases.md +0 -142
  63. package/packages/ct-skills/skills/railway-platform/references/06-environments.md +0 -261
  64. package/packages/ct-skills/skills/railway-platform/references/07-domains.md +0 -139
  65. package/packages/ct-skills/skills/railway-platform/references/08-volumes.md +0 -533
  66. package/packages/ct-skills/skills/railway-platform/references/09-networking.md +0 -592
  67. package/packages/ct-skills/skills/railway-platform/references/10-cron.md +0 -488
  68. package/packages/ct-skills/skills/railway-platform/references/11-functions.md +0 -170
  69. package/packages/ct-skills/skills/railway-platform/references/12-monorepo.md +0 -294
  70. package/packages/ct-skills/skills/railway-platform/references/13-troubleshooting.md +0 -335
  71. package/packages/ct-skills/skills/railway-platform/references/14-railway-metal.md +0 -197
package/dist/mcp/index.js CHANGED
@@ -3850,6 +3850,1338 @@ var init_handoff = __esm({
3850
3850
  }
3851
3851
  });
3852
3852
 
3853
+ // src/store/brain-schema.ts
3854
+ var brain_schema_exports = {};
3855
+ __export(brain_schema_exports, {
3856
+ BRAIN_CONFIDENCE_LEVELS: () => BRAIN_CONFIDENCE_LEVELS,
3857
+ BRAIN_DECISION_TYPES: () => BRAIN_DECISION_TYPES,
3858
+ BRAIN_IMPACT_LEVELS: () => BRAIN_IMPACT_LEVELS,
3859
+ BRAIN_LINK_TYPES: () => BRAIN_LINK_TYPES,
3860
+ BRAIN_MEMORY_TYPES: () => BRAIN_MEMORY_TYPES,
3861
+ BRAIN_OBSERVATION_SOURCE_TYPES: () => BRAIN_OBSERVATION_SOURCE_TYPES,
3862
+ BRAIN_OBSERVATION_TYPES: () => BRAIN_OBSERVATION_TYPES,
3863
+ BRAIN_OUTCOME_TYPES: () => BRAIN_OUTCOME_TYPES,
3864
+ BRAIN_PATTERN_TYPES: () => BRAIN_PATTERN_TYPES,
3865
+ brainDecisions: () => brainDecisions,
3866
+ brainLearnings: () => brainLearnings,
3867
+ brainMemoryLinks: () => brainMemoryLinks,
3868
+ brainObservations: () => brainObservations,
3869
+ brainPatterns: () => brainPatterns,
3870
+ brainSchemaMeta: () => brainSchemaMeta
3871
+ });
3872
+ import {
3873
+ sqliteTable as sqliteTable2,
3874
+ text as text2,
3875
+ integer as integer2,
3876
+ real,
3877
+ index as index2,
3878
+ primaryKey as primaryKey2
3879
+ } from "drizzle-orm/sqlite-core";
3880
+ import { sql as sql3 } from "drizzle-orm";
3881
+ var BRAIN_DECISION_TYPES, BRAIN_CONFIDENCE_LEVELS, BRAIN_OUTCOME_TYPES, BRAIN_PATTERN_TYPES, BRAIN_IMPACT_LEVELS, BRAIN_LINK_TYPES, BRAIN_OBSERVATION_TYPES, BRAIN_OBSERVATION_SOURCE_TYPES, BRAIN_MEMORY_TYPES, brainDecisions, brainPatterns, brainLearnings, brainObservations, brainMemoryLinks, brainSchemaMeta;
3882
+ var init_brain_schema = __esm({
3883
+ "src/store/brain-schema.ts"() {
3884
+ "use strict";
3885
+ BRAIN_DECISION_TYPES = ["architecture", "technical", "process", "strategic", "tactical"];
3886
+ BRAIN_CONFIDENCE_LEVELS = ["low", "medium", "high"];
3887
+ BRAIN_OUTCOME_TYPES = ["success", "failure", "mixed", "pending"];
3888
+ BRAIN_PATTERN_TYPES = ["workflow", "blocker", "success", "failure", "optimization"];
3889
+ BRAIN_IMPACT_LEVELS = ["low", "medium", "high"];
3890
+ BRAIN_LINK_TYPES = ["produced_by", "applies_to", "informed_by", "contradicts"];
3891
+ BRAIN_OBSERVATION_TYPES = ["discovery", "change", "feature", "bugfix", "decision", "refactor"];
3892
+ BRAIN_OBSERVATION_SOURCE_TYPES = ["agent", "session-debrief", "claude-mem", "manual"];
3893
+ BRAIN_MEMORY_TYPES = ["decision", "pattern", "learning", "observation"];
3894
+ brainDecisions = sqliteTable2("brain_decisions", {
3895
+ id: text2("id").primaryKey(),
3896
+ type: text2("type", { enum: BRAIN_DECISION_TYPES }).notNull(),
3897
+ decision: text2("decision").notNull(),
3898
+ rationale: text2("rationale").notNull(),
3899
+ confidence: text2("confidence", { enum: BRAIN_CONFIDENCE_LEVELS }).notNull(),
3900
+ outcome: text2("outcome", { enum: BRAIN_OUTCOME_TYPES }),
3901
+ alternativesJson: text2("alternatives_json"),
3902
+ contextEpicId: text2("context_epic_id"),
3903
+ // soft FK to tasks.id in tasks.db
3904
+ contextTaskId: text2("context_task_id"),
3905
+ // soft FK to tasks.id in tasks.db
3906
+ contextPhase: text2("context_phase"),
3907
+ createdAt: text2("created_at").notNull().default(sql3`(datetime('now'))`),
3908
+ updatedAt: text2("updated_at")
3909
+ }, (table) => [
3910
+ index2("idx_brain_decisions_type").on(table.type),
3911
+ index2("idx_brain_decisions_confidence").on(table.confidence),
3912
+ index2("idx_brain_decisions_outcome").on(table.outcome),
3913
+ index2("idx_brain_decisions_context_epic").on(table.contextEpicId),
3914
+ index2("idx_brain_decisions_context_task").on(table.contextTaskId)
3915
+ ]);
3916
+ brainPatterns = sqliteTable2("brain_patterns", {
3917
+ id: text2("id").primaryKey(),
3918
+ type: text2("type", { enum: BRAIN_PATTERN_TYPES }).notNull(),
3919
+ pattern: text2("pattern").notNull(),
3920
+ context: text2("context").notNull(),
3921
+ frequency: integer2("frequency").notNull().default(1),
3922
+ successRate: real("success_rate"),
3923
+ impact: text2("impact", { enum: BRAIN_IMPACT_LEVELS }),
3924
+ antiPattern: text2("anti_pattern"),
3925
+ mitigation: text2("mitigation"),
3926
+ examplesJson: text2("examples_json").default("[]"),
3927
+ extractedAt: text2("extracted_at").notNull().default(sql3`(datetime('now'))`),
3928
+ updatedAt: text2("updated_at")
3929
+ }, (table) => [
3930
+ index2("idx_brain_patterns_type").on(table.type),
3931
+ index2("idx_brain_patterns_impact").on(table.impact),
3932
+ index2("idx_brain_patterns_frequency").on(table.frequency)
3933
+ ]);
3934
+ brainLearnings = sqliteTable2("brain_learnings", {
3935
+ id: text2("id").primaryKey(),
3936
+ insight: text2("insight").notNull(),
3937
+ source: text2("source").notNull(),
3938
+ confidence: real("confidence").notNull(),
3939
+ // 0.0-1.0
3940
+ actionable: integer2("actionable", { mode: "boolean" }).notNull().default(false),
3941
+ application: text2("application"),
3942
+ applicableTypesJson: text2("applicable_types_json"),
3943
+ createdAt: text2("created_at").notNull().default(sql3`(datetime('now'))`),
3944
+ updatedAt: text2("updated_at")
3945
+ }, (table) => [
3946
+ index2("idx_brain_learnings_confidence").on(table.confidence),
3947
+ index2("idx_brain_learnings_actionable").on(table.actionable)
3948
+ ]);
3949
+ brainObservations = sqliteTable2("brain_observations", {
3950
+ id: text2("id").primaryKey(),
3951
+ type: text2("type", { enum: BRAIN_OBSERVATION_TYPES }).notNull(),
3952
+ title: text2("title").notNull(),
3953
+ subtitle: text2("subtitle"),
3954
+ narrative: text2("narrative"),
3955
+ factsJson: text2("facts_json"),
3956
+ // JSON array of fact strings
3957
+ conceptsJson: text2("concepts_json"),
3958
+ // JSON array of concept strings
3959
+ project: text2("project"),
3960
+ filesReadJson: text2("files_read_json"),
3961
+ // JSON array of file paths
3962
+ filesModifiedJson: text2("files_modified_json"),
3963
+ // JSON array of file paths
3964
+ sourceSessionId: text2("source_session_id"),
3965
+ // soft FK to sessions
3966
+ sourceType: text2("source_type", { enum: BRAIN_OBSERVATION_SOURCE_TYPES }).notNull().default("agent"),
3967
+ contentHash: text2("content_hash"),
3968
+ // SHA-256 prefix for dedup
3969
+ discoveryTokens: integer2("discovery_tokens"),
3970
+ // cost to produce this observation
3971
+ createdAt: text2("created_at").notNull().default(sql3`(datetime('now'))`),
3972
+ updatedAt: text2("updated_at")
3973
+ }, (table) => [
3974
+ index2("idx_brain_observations_type").on(table.type),
3975
+ index2("idx_brain_observations_project").on(table.project),
3976
+ index2("idx_brain_observations_created_at").on(table.createdAt),
3977
+ index2("idx_brain_observations_source_type").on(table.sourceType),
3978
+ index2("idx_brain_observations_source_session").on(table.sourceSessionId),
3979
+ index2("idx_brain_observations_content_hash").on(table.contentHash)
3980
+ ]);
3981
+ brainMemoryLinks = sqliteTable2("brain_memory_links", {
3982
+ memoryType: text2("memory_type", { enum: BRAIN_MEMORY_TYPES }).notNull(),
3983
+ memoryId: text2("memory_id").notNull(),
3984
+ taskId: text2("task_id").notNull(),
3985
+ // soft FK to tasks.id in tasks.db
3986
+ linkType: text2("link_type", { enum: BRAIN_LINK_TYPES }).notNull(),
3987
+ createdAt: text2("created_at").notNull().default(sql3`(datetime('now'))`)
3988
+ }, (table) => [
3989
+ primaryKey2({ columns: [table.memoryType, table.memoryId, table.taskId, table.linkType] }),
3990
+ index2("idx_brain_links_task").on(table.taskId),
3991
+ index2("idx_brain_links_memory").on(table.memoryType, table.memoryId)
3992
+ ]);
3993
+ brainSchemaMeta = sqliteTable2("brain_schema_meta", {
3994
+ key: text2("key").primaryKey(),
3995
+ value: text2("value").notNull()
3996
+ });
3997
+ }
3998
+ });
3999
+
4000
+ // src/store/brain-sqlite.ts
4001
+ import { mkdirSync as mkdirSync6 } from "node:fs";
4002
+ import { dirname as dirname6, join as join11 } from "node:path";
4003
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
4004
+ import { readMigrationFiles as readMigrationFiles2 } from "drizzle-orm/migrator";
4005
+ import { drizzle as drizzle2 } from "drizzle-orm/sqlite-proxy";
4006
+ import { migrate as migrate2 } from "drizzle-orm/sqlite-proxy/migrator";
4007
+ function getBrainDbPath(cwd) {
4008
+ return join11(getCleoDirAbsolute(cwd), DB_FILENAME2);
4009
+ }
4010
+ function resolveBrainMigrationsFolder() {
4011
+ const __filename = fileURLToPath2(import.meta.url);
4012
+ const __dirname = dirname6(__filename);
4013
+ return join11(__dirname, "..", "..", "drizzle-brain");
4014
+ }
4015
+ function tableExists2(nativeDb, tableName) {
4016
+ const result = nativeDb.prepare(
4017
+ "SELECT name FROM sqlite_master WHERE type='table' AND name=?"
4018
+ ).get(tableName);
4019
+ return !!result;
4020
+ }
4021
+ async function runBrainMigrations(nativeDb, db) {
4022
+ const migrationsFolder = resolveBrainMigrationsFolder();
4023
+ if (tableExists2(nativeDb, "brain_decisions") && !tableExists2(nativeDb, "__drizzle_migrations")) {
4024
+ const migrations = readMigrationFiles2({ migrationsFolder });
4025
+ const baseline = migrations[0];
4026
+ if (baseline) {
4027
+ nativeDb.exec(`
4028
+ CREATE TABLE IF NOT EXISTS "__drizzle_migrations" (
4029
+ id SERIAL PRIMARY KEY,
4030
+ hash text NOT NULL,
4031
+ created_at numeric
4032
+ )
4033
+ `);
4034
+ nativeDb.exec(
4035
+ `INSERT INTO "__drizzle_migrations" ("hash", "created_at") VALUES ('${baseline.hash}', ${baseline.folderMillis})`
4036
+ );
4037
+ }
4038
+ }
4039
+ await migrate2(db, async (queries) => {
4040
+ nativeDb.prepare("BEGIN IMMEDIATE").run();
4041
+ try {
4042
+ for (const query of queries) {
4043
+ nativeDb.prepare(query).run();
4044
+ }
4045
+ nativeDb.prepare("COMMIT").run();
4046
+ } catch (err) {
4047
+ nativeDb.prepare("ROLLBACK").run();
4048
+ throw err;
4049
+ }
4050
+ }, { migrationsFolder });
4051
+ }
4052
+ async function getBrainDb(cwd) {
4053
+ const requestedPath = getBrainDbPath(cwd);
4054
+ if (_db2 && _dbPath2 !== requestedPath) {
4055
+ resetBrainDbState();
4056
+ }
4057
+ if (_db2) return _db2;
4058
+ if (_initPromise2) return _initPromise2;
4059
+ _initPromise2 = (async () => {
4060
+ const dbPath = requestedPath;
4061
+ _dbPath2 = dbPath;
4062
+ mkdirSync6(dirname6(dbPath), { recursive: true });
4063
+ const nativeDb = openNativeDatabase(dbPath);
4064
+ _nativeDb2 = nativeDb;
4065
+ const callback = createDrizzleCallback(nativeDb);
4066
+ const batchCb = createBatchCallback(nativeDb);
4067
+ const db = drizzle2(callback, batchCb, { schema: brain_schema_exports });
4068
+ await runBrainMigrations(nativeDb, db);
4069
+ nativeDb.exec(
4070
+ `INSERT OR IGNORE INTO brain_schema_meta (key, value) VALUES ('schemaVersion', '${BRAIN_SCHEMA_VERSION}')`
4071
+ );
4072
+ _db2 = db;
4073
+ return db;
4074
+ })();
4075
+ try {
4076
+ return await _initPromise2;
4077
+ } finally {
4078
+ _initPromise2 = null;
4079
+ }
4080
+ }
4081
+ function resetBrainDbState() {
4082
+ if (_nativeDb2) {
4083
+ try {
4084
+ if (_nativeDb2.isOpen) {
4085
+ _nativeDb2.close();
4086
+ }
4087
+ } catch {
4088
+ }
4089
+ _nativeDb2 = null;
4090
+ }
4091
+ _db2 = null;
4092
+ _dbPath2 = null;
4093
+ _initPromise2 = null;
4094
+ }
4095
+ function getBrainNativeDb() {
4096
+ return _nativeDb2;
4097
+ }
4098
+ var DB_FILENAME2, BRAIN_SCHEMA_VERSION, _db2, _nativeDb2, _dbPath2, _initPromise2;
4099
+ var init_brain_sqlite = __esm({
4100
+ "src/store/brain-sqlite.ts"() {
4101
+ "use strict";
4102
+ init_brain_schema();
4103
+ init_paths();
4104
+ init_node_sqlite_adapter();
4105
+ DB_FILENAME2 = "brain.db";
4106
+ BRAIN_SCHEMA_VERSION = "1.0.0";
4107
+ _db2 = null;
4108
+ _nativeDb2 = null;
4109
+ _dbPath2 = null;
4110
+ _initPromise2 = null;
4111
+ }
4112
+ });
4113
+
4114
+ // src/core/memory/brain-search.ts
4115
+ function checkFts5Available(nativeDb) {
4116
+ if (_fts5Available !== null) return _fts5Available;
4117
+ try {
4118
+ nativeDb.prepare("CREATE VIRTUAL TABLE IF NOT EXISTS _fts5_check USING fts5(test)").run();
4119
+ nativeDb.prepare("DROP TABLE IF EXISTS _fts5_check").run();
4120
+ _fts5Available = true;
4121
+ } catch {
4122
+ _fts5Available = false;
4123
+ }
4124
+ return _fts5Available;
4125
+ }
4126
+ function execDDL(nativeDb, sql5) {
4127
+ nativeDb.prepare(sql5).run();
4128
+ }
4129
+ function ensureFts5Tables(nativeDb) {
4130
+ if (!checkFts5Available(nativeDb)) {
4131
+ return false;
4132
+ }
4133
+ execDDL(nativeDb, `
4134
+ CREATE VIRTUAL TABLE IF NOT EXISTS brain_decisions_fts
4135
+ USING fts5(id, decision, rationale, content=brain_decisions, content_rowid=rowid)
4136
+ `);
4137
+ execDDL(nativeDb, `
4138
+ CREATE VIRTUAL TABLE IF NOT EXISTS brain_patterns_fts
4139
+ USING fts5(id, pattern, context, content=brain_patterns, content_rowid=rowid)
4140
+ `);
4141
+ execDDL(nativeDb, `
4142
+ CREATE VIRTUAL TABLE IF NOT EXISTS brain_learnings_fts
4143
+ USING fts5(id, insight, source, content=brain_learnings, content_rowid=rowid)
4144
+ `);
4145
+ execDDL(nativeDb, `
4146
+ CREATE TRIGGER IF NOT EXISTS brain_decisions_ai AFTER INSERT ON brain_decisions BEGIN
4147
+ INSERT INTO brain_decisions_fts(rowid, id, decision, rationale)
4148
+ VALUES (new.rowid, new.id, new.decision, new.rationale);
4149
+ END
4150
+ `);
4151
+ execDDL(nativeDb, `
4152
+ CREATE TRIGGER IF NOT EXISTS brain_decisions_ad AFTER DELETE ON brain_decisions BEGIN
4153
+ INSERT INTO brain_decisions_fts(brain_decisions_fts, rowid, id, decision, rationale)
4154
+ VALUES('delete', old.rowid, old.id, old.decision, old.rationale);
4155
+ END
4156
+ `);
4157
+ execDDL(nativeDb, `
4158
+ CREATE TRIGGER IF NOT EXISTS brain_decisions_au AFTER UPDATE ON brain_decisions BEGIN
4159
+ INSERT INTO brain_decisions_fts(brain_decisions_fts, rowid, id, decision, rationale)
4160
+ VALUES('delete', old.rowid, old.id, old.decision, old.rationale);
4161
+ INSERT INTO brain_decisions_fts(rowid, id, decision, rationale)
4162
+ VALUES (new.rowid, new.id, new.decision, new.rationale);
4163
+ END
4164
+ `);
4165
+ execDDL(nativeDb, `
4166
+ CREATE TRIGGER IF NOT EXISTS brain_patterns_ai AFTER INSERT ON brain_patterns BEGIN
4167
+ INSERT INTO brain_patterns_fts(rowid, id, pattern, context)
4168
+ VALUES (new.rowid, new.id, new.pattern, new.context);
4169
+ END
4170
+ `);
4171
+ execDDL(nativeDb, `
4172
+ CREATE TRIGGER IF NOT EXISTS brain_patterns_ad AFTER DELETE ON brain_patterns BEGIN
4173
+ INSERT INTO brain_patterns_fts(brain_patterns_fts, rowid, id, pattern, context)
4174
+ VALUES('delete', old.rowid, old.id, old.pattern, old.context);
4175
+ END
4176
+ `);
4177
+ execDDL(nativeDb, `
4178
+ CREATE TRIGGER IF NOT EXISTS brain_patterns_au AFTER UPDATE ON brain_patterns BEGIN
4179
+ INSERT INTO brain_patterns_fts(brain_patterns_fts, rowid, id, pattern, context)
4180
+ VALUES('delete', old.rowid, old.id, old.pattern, old.context);
4181
+ INSERT INTO brain_patterns_fts(rowid, id, pattern, context)
4182
+ VALUES (new.rowid, new.id, new.pattern, new.context);
4183
+ END
4184
+ `);
4185
+ execDDL(nativeDb, `
4186
+ CREATE TRIGGER IF NOT EXISTS brain_learnings_ai AFTER INSERT ON brain_learnings BEGIN
4187
+ INSERT INTO brain_learnings_fts(rowid, id, insight, source)
4188
+ VALUES (new.rowid, new.id, new.insight, new.source);
4189
+ END
4190
+ `);
4191
+ execDDL(nativeDb, `
4192
+ CREATE TRIGGER IF NOT EXISTS brain_learnings_ad AFTER DELETE ON brain_learnings BEGIN
4193
+ INSERT INTO brain_learnings_fts(brain_learnings_fts, rowid, id, insight, source)
4194
+ VALUES('delete', old.rowid, old.id, old.insight, old.source);
4195
+ END
4196
+ `);
4197
+ execDDL(nativeDb, `
4198
+ CREATE TRIGGER IF NOT EXISTS brain_learnings_au AFTER UPDATE ON brain_learnings BEGIN
4199
+ INSERT INTO brain_learnings_fts(brain_learnings_fts, rowid, id, insight, source)
4200
+ VALUES('delete', old.rowid, old.id, old.insight, old.source);
4201
+ INSERT INTO brain_learnings_fts(rowid, id, insight, source)
4202
+ VALUES (new.rowid, new.id, new.insight, new.source);
4203
+ END
4204
+ `);
4205
+ execDDL(nativeDb, `
4206
+ CREATE VIRTUAL TABLE IF NOT EXISTS brain_observations_fts
4207
+ USING fts5(id, title, narrative, content=brain_observations, content_rowid=rowid)
4208
+ `);
4209
+ execDDL(nativeDb, `
4210
+ CREATE TRIGGER IF NOT EXISTS brain_observations_ai AFTER INSERT ON brain_observations BEGIN
4211
+ INSERT INTO brain_observations_fts(rowid, id, title, narrative)
4212
+ VALUES (new.rowid, new.id, new.title, new.narrative);
4213
+ END
4214
+ `);
4215
+ execDDL(nativeDb, `
4216
+ CREATE TRIGGER IF NOT EXISTS brain_observations_ad AFTER DELETE ON brain_observations BEGIN
4217
+ INSERT INTO brain_observations_fts(brain_observations_fts, rowid, id, title, narrative)
4218
+ VALUES('delete', old.rowid, old.id, old.title, old.narrative);
4219
+ END
4220
+ `);
4221
+ execDDL(nativeDb, `
4222
+ CREATE TRIGGER IF NOT EXISTS brain_observations_au AFTER UPDATE ON brain_observations BEGIN
4223
+ INSERT INTO brain_observations_fts(brain_observations_fts, rowid, id, title, narrative)
4224
+ VALUES('delete', old.rowid, old.id, old.title, old.narrative);
4225
+ INSERT INTO brain_observations_fts(rowid, id, title, narrative)
4226
+ VALUES (new.rowid, new.id, new.title, new.narrative);
4227
+ END
4228
+ `);
4229
+ return true;
4230
+ }
4231
+ function rebuildFts5Index(nativeDb) {
4232
+ if (!checkFts5Available(nativeDb)) {
4233
+ return;
4234
+ }
4235
+ nativeDb.prepare("INSERT INTO brain_decisions_fts(brain_decisions_fts) VALUES('rebuild')").run();
4236
+ nativeDb.prepare("INSERT INTO brain_patterns_fts(brain_patterns_fts) VALUES('rebuild')").run();
4237
+ nativeDb.prepare("INSERT INTO brain_learnings_fts(brain_learnings_fts) VALUES('rebuild')").run();
4238
+ try {
4239
+ nativeDb.prepare("INSERT INTO brain_observations_fts(brain_observations_fts) VALUES('rebuild')").run();
4240
+ } catch {
4241
+ }
4242
+ }
4243
+ async function searchBrain(projectRoot, query, options) {
4244
+ if (!query || !query.trim()) {
4245
+ return { decisions: [], patterns: [], learnings: [], observations: [] };
4246
+ }
4247
+ await getBrainDb(projectRoot);
4248
+ const nativeDb = getBrainNativeDb();
4249
+ if (!nativeDb) {
4250
+ return { decisions: [], patterns: [], learnings: [], observations: [] };
4251
+ }
4252
+ const limit = options?.limit ?? 10;
4253
+ const tables = options?.tables ?? ["decisions", "patterns", "learnings", "observations"];
4254
+ const ftsAvailable = ensureFts5Tables(nativeDb);
4255
+ if (ftsAvailable) {
4256
+ if (!_fts5Initialized) {
4257
+ _fts5Initialized = true;
4258
+ rebuildFts5Index(nativeDb);
4259
+ }
4260
+ return searchWithFts5(nativeDb, query, tables, limit);
4261
+ }
4262
+ return searchWithLike(nativeDb, query, tables, limit);
4263
+ }
4264
+ function searchWithFts5(nativeDb, query, tables, limit) {
4265
+ const result = {
4266
+ decisions: [],
4267
+ patterns: [],
4268
+ learnings: [],
4269
+ observations: []
4270
+ };
4271
+ const safeQuery = escapeFts5Query(query);
4272
+ if (tables.includes("decisions")) {
4273
+ try {
4274
+ const rows = nativeDb.prepare(`
4275
+ SELECT d.*
4276
+ FROM brain_decisions_fts fts
4277
+ JOIN brain_decisions d ON d.rowid = fts.rowid
4278
+ WHERE brain_decisions_fts MATCH ?
4279
+ ORDER BY bm25(brain_decisions_fts)
4280
+ LIMIT ?
4281
+ `).all(safeQuery, limit);
4282
+ result.decisions = rows;
4283
+ } catch {
4284
+ result.decisions = likeSearchDecisions(nativeDb, query, limit);
4285
+ }
4286
+ }
4287
+ if (tables.includes("patterns")) {
4288
+ try {
4289
+ const rows = nativeDb.prepare(`
4290
+ SELECT p.*
4291
+ FROM brain_patterns_fts fts
4292
+ JOIN brain_patterns p ON p.rowid = fts.rowid
4293
+ WHERE brain_patterns_fts MATCH ?
4294
+ ORDER BY bm25(brain_patterns_fts)
4295
+ LIMIT ?
4296
+ `).all(safeQuery, limit);
4297
+ result.patterns = rows;
4298
+ } catch {
4299
+ result.patterns = likeSearchPatterns(nativeDb, query, limit);
4300
+ }
4301
+ }
4302
+ if (tables.includes("learnings")) {
4303
+ try {
4304
+ const rows = nativeDb.prepare(`
4305
+ SELECT l.*
4306
+ FROM brain_learnings_fts fts
4307
+ JOIN brain_learnings l ON l.rowid = fts.rowid
4308
+ WHERE brain_learnings_fts MATCH ?
4309
+ ORDER BY bm25(brain_learnings_fts)
4310
+ LIMIT ?
4311
+ `).all(safeQuery, limit);
4312
+ result.learnings = rows;
4313
+ } catch {
4314
+ result.learnings = likeSearchLearnings(nativeDb, query, limit);
4315
+ }
4316
+ }
4317
+ if (tables.includes("observations")) {
4318
+ try {
4319
+ const rows = nativeDb.prepare(`
4320
+ SELECT o.*
4321
+ FROM brain_observations_fts fts
4322
+ JOIN brain_observations o ON o.rowid = fts.rowid
4323
+ WHERE brain_observations_fts MATCH ?
4324
+ ORDER BY bm25(brain_observations_fts)
4325
+ LIMIT ?
4326
+ `).all(safeQuery, limit);
4327
+ result.observations = rows;
4328
+ } catch {
4329
+ result.observations = likeSearchObservations(nativeDb, query, limit);
4330
+ }
4331
+ }
4332
+ return result;
4333
+ }
4334
+ function searchWithLike(nativeDb, query, tables, limit) {
4335
+ const result = {
4336
+ decisions: [],
4337
+ patterns: [],
4338
+ learnings: [],
4339
+ observations: []
4340
+ };
4341
+ if (tables.includes("decisions")) {
4342
+ result.decisions = likeSearchDecisions(nativeDb, query, limit);
4343
+ }
4344
+ if (tables.includes("patterns")) {
4345
+ result.patterns = likeSearchPatterns(nativeDb, query, limit);
4346
+ }
4347
+ if (tables.includes("learnings")) {
4348
+ result.learnings = likeSearchLearnings(nativeDb, query, limit);
4349
+ }
4350
+ if (tables.includes("observations")) {
4351
+ result.observations = likeSearchObservations(nativeDb, query, limit);
4352
+ }
4353
+ return result;
4354
+ }
4355
+ function likeSearchDecisions(nativeDb, query, limit) {
4356
+ const likePattern = `%${query}%`;
4357
+ return nativeDb.prepare(`
4358
+ SELECT * FROM brain_decisions
4359
+ WHERE decision LIKE ? OR rationale LIKE ?
4360
+ ORDER BY created_at DESC
4361
+ LIMIT ?
4362
+ `).all(likePattern, likePattern, limit);
4363
+ }
4364
+ function likeSearchPatterns(nativeDb, query, limit) {
4365
+ const likePattern = `%${query}%`;
4366
+ return nativeDb.prepare(`
4367
+ SELECT * FROM brain_patterns
4368
+ WHERE pattern LIKE ? OR context LIKE ?
4369
+ ORDER BY frequency DESC
4370
+ LIMIT ?
4371
+ `).all(likePattern, likePattern, limit);
4372
+ }
4373
+ function likeSearchLearnings(nativeDb, query, limit) {
4374
+ const likePattern = `%${query}%`;
4375
+ return nativeDb.prepare(`
4376
+ SELECT * FROM brain_learnings
4377
+ WHERE insight LIKE ? OR source LIKE ?
4378
+ ORDER BY confidence DESC
4379
+ LIMIT ?
4380
+ `).all(likePattern, likePattern, limit);
4381
+ }
4382
+ function likeSearchObservations(nativeDb, query, limit) {
4383
+ const likePattern = `%${query}%`;
4384
+ return nativeDb.prepare(`
4385
+ SELECT * FROM brain_observations
4386
+ WHERE title LIKE ? OR narrative LIKE ?
4387
+ ORDER BY created_at DESC
4388
+ LIMIT ?
4389
+ `).all(likePattern, likePattern, limit);
4390
+ }
4391
+ function escapeFts5Query(query) {
4392
+ const tokens = query.trim().split(/\s+/).filter(Boolean);
4393
+ if (tokens.length === 0) return '""';
4394
+ return tokens.map((t) => `"${t.replace(/"/g, '""')}"`).join(" ");
4395
+ }
4396
+ var _fts5Available, _fts5Initialized;
4397
+ var init_brain_search = __esm({
4398
+ "src/core/memory/brain-search.ts"() {
4399
+ "use strict";
4400
+ init_brain_sqlite();
4401
+ _fts5Available = null;
4402
+ _fts5Initialized = false;
4403
+ }
4404
+ });
4405
+
4406
+ // src/store/brain-accessor.ts
4407
+ import { eq as eq7, and as and2, gte, desc, asc as asc2 } from "drizzle-orm";
4408
+ async function getBrainAccessor(cwd) {
4409
+ const db = await getBrainDb(cwd);
4410
+ return new BrainDataAccessor(db);
4411
+ }
4412
+ var BrainDataAccessor;
4413
+ var init_brain_accessor = __esm({
4414
+ "src/store/brain-accessor.ts"() {
4415
+ "use strict";
4416
+ init_brain_sqlite();
4417
+ init_brain_schema();
4418
+ BrainDataAccessor = class {
4419
+ constructor(db) {
4420
+ this.db = db;
4421
+ }
4422
+ // =========================================================================
4423
+ // Decisions CRUD
4424
+ // =========================================================================
4425
+ async addDecision(row) {
4426
+ await this.db.insert(brainDecisions).values(row);
4427
+ const result = await this.db.select().from(brainDecisions).where(eq7(brainDecisions.id, row.id));
4428
+ return result[0];
4429
+ }
4430
+ async getDecision(id) {
4431
+ const result = await this.db.select().from(brainDecisions).where(eq7(brainDecisions.id, id));
4432
+ return result[0] ?? null;
4433
+ }
4434
+ async findDecisions(params = {}) {
4435
+ const conditions = [];
4436
+ if (params.type) {
4437
+ conditions.push(eq7(brainDecisions.type, params.type));
4438
+ }
4439
+ if (params.confidence) {
4440
+ conditions.push(eq7(brainDecisions.confidence, params.confidence));
4441
+ }
4442
+ if (params.outcome) {
4443
+ conditions.push(eq7(brainDecisions.outcome, params.outcome));
4444
+ }
4445
+ if (params.contextTaskId) {
4446
+ conditions.push(eq7(brainDecisions.contextTaskId, params.contextTaskId));
4447
+ }
4448
+ let query = this.db.select().from(brainDecisions).orderBy(desc(brainDecisions.createdAt));
4449
+ if (conditions.length > 0) {
4450
+ query = query.where(and2(...conditions));
4451
+ }
4452
+ if (params.limit) {
4453
+ query = query.limit(params.limit);
4454
+ }
4455
+ return query;
4456
+ }
4457
+ async updateDecision(id, updates) {
4458
+ await this.db.update(brainDecisions).set({ ...updates, updatedAt: (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19) }).where(eq7(brainDecisions.id, id));
4459
+ }
4460
+ // =========================================================================
4461
+ // Patterns CRUD
4462
+ // =========================================================================
4463
+ async addPattern(row) {
4464
+ await this.db.insert(brainPatterns).values(row);
4465
+ const result = await this.db.select().from(brainPatterns).where(eq7(brainPatterns.id, row.id));
4466
+ return result[0];
4467
+ }
4468
+ async getPattern(id) {
4469
+ const result = await this.db.select().from(brainPatterns).where(eq7(brainPatterns.id, id));
4470
+ return result[0] ?? null;
4471
+ }
4472
+ async findPatterns(params = {}) {
4473
+ const conditions = [];
4474
+ if (params.type) {
4475
+ conditions.push(eq7(brainPatterns.type, params.type));
4476
+ }
4477
+ if (params.impact) {
4478
+ conditions.push(eq7(brainPatterns.impact, params.impact));
4479
+ }
4480
+ if (params.minFrequency !== void 0) {
4481
+ conditions.push(gte(brainPatterns.frequency, params.minFrequency));
4482
+ }
4483
+ let query = this.db.select().from(brainPatterns).orderBy(desc(brainPatterns.frequency));
4484
+ if (conditions.length > 0) {
4485
+ query = query.where(and2(...conditions));
4486
+ }
4487
+ if (params.limit) {
4488
+ query = query.limit(params.limit);
4489
+ }
4490
+ return query;
4491
+ }
4492
+ async updatePattern(id, updates) {
4493
+ await this.db.update(brainPatterns).set({ ...updates, updatedAt: (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19) }).where(eq7(brainPatterns.id, id));
4494
+ }
4495
+ // =========================================================================
4496
+ // Learnings CRUD
4497
+ // =========================================================================
4498
+ async addLearning(row) {
4499
+ await this.db.insert(brainLearnings).values(row);
4500
+ const result = await this.db.select().from(brainLearnings).where(eq7(brainLearnings.id, row.id));
4501
+ return result[0];
4502
+ }
4503
+ async getLearning(id) {
4504
+ const result = await this.db.select().from(brainLearnings).where(eq7(brainLearnings.id, id));
4505
+ return result[0] ?? null;
4506
+ }
4507
+ async findLearnings(params = {}) {
4508
+ const conditions = [];
4509
+ if (params.minConfidence !== void 0) {
4510
+ conditions.push(gte(brainLearnings.confidence, params.minConfidence));
4511
+ }
4512
+ if (params.actionable !== void 0) {
4513
+ conditions.push(eq7(brainLearnings.actionable, params.actionable));
4514
+ }
4515
+ let query = this.db.select().from(brainLearnings).orderBy(desc(brainLearnings.confidence));
4516
+ if (conditions.length > 0) {
4517
+ query = query.where(and2(...conditions));
4518
+ }
4519
+ if (params.limit) {
4520
+ query = query.limit(params.limit);
4521
+ }
4522
+ return query;
4523
+ }
4524
+ async updateLearning(id, updates) {
4525
+ await this.db.update(brainLearnings).set({ ...updates, updatedAt: (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19) }).where(eq7(brainLearnings.id, id));
4526
+ }
4527
+ // =========================================================================
4528
+ // Observations CRUD
4529
+ // =========================================================================
4530
+ async addObservation(row) {
4531
+ await this.db.insert(brainObservations).values(row);
4532
+ const result = await this.db.select().from(brainObservations).where(eq7(brainObservations.id, row.id));
4533
+ return result[0];
4534
+ }
4535
+ async getObservation(id) {
4536
+ const result = await this.db.select().from(brainObservations).where(eq7(brainObservations.id, id));
4537
+ return result[0] ?? null;
4538
+ }
4539
+ async findObservations(params = {}) {
4540
+ const conditions = [];
4541
+ if (params.type) {
4542
+ conditions.push(eq7(brainObservations.type, params.type));
4543
+ }
4544
+ if (params.project) {
4545
+ conditions.push(eq7(brainObservations.project, params.project));
4546
+ }
4547
+ if (params.sourceType) {
4548
+ conditions.push(eq7(brainObservations.sourceType, params.sourceType));
4549
+ }
4550
+ if (params.sourceSessionId) {
4551
+ conditions.push(eq7(brainObservations.sourceSessionId, params.sourceSessionId));
4552
+ }
4553
+ let query = this.db.select().from(brainObservations).orderBy(desc(brainObservations.createdAt));
4554
+ if (conditions.length > 0) {
4555
+ query = query.where(and2(...conditions));
4556
+ }
4557
+ if (params.limit) {
4558
+ query = query.limit(params.limit);
4559
+ }
4560
+ return query;
4561
+ }
4562
+ async updateObservation(id, updates) {
4563
+ await this.db.update(brainObservations).set({ ...updates, updatedAt: (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19) }).where(eq7(brainObservations.id, id));
4564
+ }
4565
+ // =========================================================================
4566
+ // Memory Links CRUD
4567
+ // =========================================================================
4568
+ async addLink(row) {
4569
+ await this.db.insert(brainMemoryLinks).values(row);
4570
+ }
4571
+ async getLinksForMemory(memoryType, memoryId) {
4572
+ return this.db.select().from(brainMemoryLinks).where(
4573
+ and2(
4574
+ eq7(brainMemoryLinks.memoryType, memoryType),
4575
+ eq7(brainMemoryLinks.memoryId, memoryId)
4576
+ )
4577
+ ).orderBy(asc2(brainMemoryLinks.createdAt));
4578
+ }
4579
+ async getLinksForTask(taskId) {
4580
+ return this.db.select().from(brainMemoryLinks).where(eq7(brainMemoryLinks.taskId, taskId)).orderBy(asc2(brainMemoryLinks.createdAt));
4581
+ }
4582
+ async removeLink(memoryType, memoryId, taskId, linkType) {
4583
+ await this.db.delete(brainMemoryLinks).where(
4584
+ and2(
4585
+ eq7(brainMemoryLinks.memoryType, memoryType),
4586
+ eq7(brainMemoryLinks.memoryId, memoryId),
4587
+ eq7(brainMemoryLinks.taskId, taskId),
4588
+ eq7(brainMemoryLinks.linkType, linkType)
4589
+ )
4590
+ );
4591
+ }
4592
+ };
4593
+ }
4594
+ });
4595
+
4596
+ // src/core/memory/brain-retrieval.ts
4597
+ var brain_retrieval_exports = {};
4598
+ __export(brain_retrieval_exports, {
4599
+ fetchBrainEntries: () => fetchBrainEntries,
4600
+ observeBrain: () => observeBrain,
4601
+ searchBrainCompact: () => searchBrainCompact,
4602
+ timelineBrain: () => timelineBrain
4603
+ });
4604
+ import { createHash as createHash3 } from "node:crypto";
4605
+ async function searchBrainCompact(projectRoot, params) {
4606
+ const { query, limit, tables, dateStart, dateEnd } = params;
4607
+ if (!query || !query.trim()) {
4608
+ return { results: [], total: 0, tokensEstimated: 0 };
4609
+ }
4610
+ const searchResult = await searchBrain(projectRoot, query, {
4611
+ limit: limit ?? 10,
4612
+ tables
4613
+ });
4614
+ let results = [];
4615
+ for (const d of searchResult.decisions) {
4616
+ const raw = d;
4617
+ results.push({
4618
+ id: d.id,
4619
+ type: "decision",
4620
+ title: d.decision.slice(0, 80),
4621
+ date: (d.createdAt ?? raw["created_at"]) || ""
4622
+ });
4623
+ }
4624
+ for (const p of searchResult.patterns) {
4625
+ const raw = p;
4626
+ results.push({
4627
+ id: p.id,
4628
+ type: "pattern",
4629
+ title: p.pattern.slice(0, 80),
4630
+ date: (p.extractedAt ?? raw["extracted_at"]) || ""
4631
+ });
4632
+ }
4633
+ for (const l of searchResult.learnings) {
4634
+ const raw = l;
4635
+ results.push({
4636
+ id: l.id,
4637
+ type: "learning",
4638
+ title: l.insight.slice(0, 80),
4639
+ date: (l.createdAt ?? raw["created_at"]) || ""
4640
+ });
4641
+ }
4642
+ for (const o of searchResult.observations) {
4643
+ const raw = o;
4644
+ results.push({
4645
+ id: o.id,
4646
+ type: "observation",
4647
+ title: o.title.slice(0, 80),
4648
+ date: (o.createdAt ?? raw["created_at"]) || ""
4649
+ });
4650
+ }
4651
+ if (dateStart) {
4652
+ results = results.filter((r) => r.date >= dateStart);
4653
+ }
4654
+ if (dateEnd) {
4655
+ results = results.filter((r) => r.date <= dateEnd);
4656
+ }
4657
+ return {
4658
+ results,
4659
+ total: results.length,
4660
+ tokensEstimated: results.length * 50
4661
+ };
4662
+ }
4663
+ function parseIdPrefix(id) {
4664
+ if (id.startsWith("D-") || /^D\d/.test(id)) return "decision";
4665
+ if (id.startsWith("P-") || /^P\d/.test(id)) return "pattern";
4666
+ if (id.startsWith("L-") || /^L\d/.test(id)) return "learning";
4667
+ if (id.startsWith("O-") || id.startsWith("O") || id.startsWith("CM-")) return "observation";
4668
+ return null;
4669
+ }
4670
+ async function timelineBrain(projectRoot, params) {
4671
+ const { anchor: anchorId, depthBefore = 3, depthAfter = 3 } = params;
4672
+ await getBrainDb(projectRoot);
4673
+ const nativeDb = getBrainNativeDb();
4674
+ if (!nativeDb) {
4675
+ return { anchor: null, before: [], after: [] };
4676
+ }
4677
+ const anchorType = parseIdPrefix(anchorId);
4678
+ if (!anchorType) {
4679
+ return { anchor: null, before: [], after: [] };
4680
+ }
4681
+ const accessor = await getBrainAccessor(projectRoot);
4682
+ let anchorData = null;
4683
+ let anchorDate = null;
4684
+ switch (anchorType) {
4685
+ case "decision": {
4686
+ const row = await accessor.getDecision(anchorId);
4687
+ if (row) {
4688
+ anchorData = row;
4689
+ anchorDate = row.createdAt;
4690
+ }
4691
+ break;
4692
+ }
4693
+ case "pattern": {
4694
+ const row = await accessor.getPattern(anchorId);
4695
+ if (row) {
4696
+ anchorData = row;
4697
+ anchorDate = row.extractedAt;
4698
+ }
4699
+ break;
4700
+ }
4701
+ case "learning": {
4702
+ const row = await accessor.getLearning(anchorId);
4703
+ if (row) {
4704
+ anchorData = row;
4705
+ anchorDate = row.createdAt;
4706
+ }
4707
+ break;
4708
+ }
4709
+ case "observation": {
4710
+ const row = await accessor.getObservation(anchorId);
4711
+ if (row) {
4712
+ anchorData = row;
4713
+ anchorDate = row.createdAt;
4714
+ }
4715
+ break;
4716
+ }
4717
+ }
4718
+ if (!anchorData || !anchorDate) {
4719
+ return { anchor: null, before: [], after: [] };
4720
+ }
4721
+ const beforeRows = nativeDb.prepare(`
4722
+ SELECT id, 'decision' AS type, created_at AS date FROM brain_decisions WHERE created_at < ? AND id != ?
4723
+ UNION ALL
4724
+ SELECT id, 'pattern' AS type, extracted_at AS date FROM brain_patterns WHERE extracted_at < ? AND id != ?
4725
+ UNION ALL
4726
+ SELECT id, 'learning' AS type, created_at AS date FROM brain_learnings WHERE created_at < ? AND id != ?
4727
+ UNION ALL
4728
+ SELECT id, 'observation' AS type, created_at AS date FROM brain_observations WHERE created_at < ? AND id != ?
4729
+ ORDER BY date DESC
4730
+ LIMIT ?
4731
+ `).all(
4732
+ anchorDate,
4733
+ anchorId,
4734
+ anchorDate,
4735
+ anchorId,
4736
+ anchorDate,
4737
+ anchorId,
4738
+ anchorDate,
4739
+ anchorId,
4740
+ depthBefore
4741
+ );
4742
+ const afterRows = nativeDb.prepare(`
4743
+ SELECT id, 'decision' AS type, created_at AS date FROM brain_decisions WHERE created_at > ? AND id != ?
4744
+ UNION ALL
4745
+ SELECT id, 'pattern' AS type, extracted_at AS date FROM brain_patterns WHERE extracted_at > ? AND id != ?
4746
+ UNION ALL
4747
+ SELECT id, 'learning' AS type, created_at AS date FROM brain_learnings WHERE created_at > ? AND id != ?
4748
+ UNION ALL
4749
+ SELECT id, 'observation' AS type, created_at AS date FROM brain_observations WHERE created_at > ? AND id != ?
4750
+ ORDER BY date ASC
4751
+ LIMIT ?
4752
+ `).all(
4753
+ anchorDate,
4754
+ anchorId,
4755
+ anchorDate,
4756
+ anchorId,
4757
+ anchorDate,
4758
+ anchorId,
4759
+ anchorDate,
4760
+ anchorId,
4761
+ depthAfter
4762
+ );
4763
+ return {
4764
+ anchor: { id: anchorId, type: anchorType, data: anchorData },
4765
+ before: beforeRows.map((r) => ({ id: r.id, type: r.type, date: r.date })),
4766
+ after: afterRows.map((r) => ({ id: r.id, type: r.type, date: r.date }))
4767
+ };
4768
+ }
4769
+ async function fetchBrainEntries(projectRoot, params) {
4770
+ const { ids } = params;
4771
+ if (!ids || ids.length === 0) {
4772
+ return { results: [], notFound: [], tokensEstimated: 0 };
4773
+ }
4774
+ const accessor = await getBrainAccessor(projectRoot);
4775
+ const decisionIds = [];
4776
+ const patternIds = [];
4777
+ const learningIds = [];
4778
+ const observationIds = [];
4779
+ const unknownIds = [];
4780
+ for (const id of ids) {
4781
+ const type = parseIdPrefix(id);
4782
+ switch (type) {
4783
+ case "decision":
4784
+ decisionIds.push(id);
4785
+ break;
4786
+ case "pattern":
4787
+ patternIds.push(id);
4788
+ break;
4789
+ case "learning":
4790
+ learningIds.push(id);
4791
+ break;
4792
+ case "observation":
4793
+ observationIds.push(id);
4794
+ break;
4795
+ default:
4796
+ unknownIds.push(id);
4797
+ }
4798
+ }
4799
+ const results = [];
4800
+ const notFound = [...unknownIds];
4801
+ for (const id of decisionIds) {
4802
+ const row = await accessor.getDecision(id);
4803
+ if (row) {
4804
+ results.push({ id, type: "decision", data: row });
4805
+ } else {
4806
+ notFound.push(id);
4807
+ }
4808
+ }
4809
+ for (const id of patternIds) {
4810
+ const row = await accessor.getPattern(id);
4811
+ if (row) {
4812
+ results.push({ id, type: "pattern", data: row });
4813
+ } else {
4814
+ notFound.push(id);
4815
+ }
4816
+ }
4817
+ for (const id of learningIds) {
4818
+ const row = await accessor.getLearning(id);
4819
+ if (row) {
4820
+ results.push({ id, type: "learning", data: row });
4821
+ } else {
4822
+ notFound.push(id);
4823
+ }
4824
+ }
4825
+ for (const id of observationIds) {
4826
+ const row = await accessor.getObservation(id);
4827
+ if (row) {
4828
+ results.push({ id, type: "observation", data: row });
4829
+ } else {
4830
+ notFound.push(id);
4831
+ }
4832
+ }
4833
+ return {
4834
+ results,
4835
+ notFound,
4836
+ tokensEstimated: results.length * 500
4837
+ };
4838
+ }
4839
+ function classifyObservationType(text3) {
4840
+ const lower = text3.toLowerCase();
4841
+ for (const { keywords, type } of TYPE_KEYWORDS) {
4842
+ for (const keyword of keywords) {
4843
+ if (lower.includes(keyword)) {
4844
+ return type;
4845
+ }
4846
+ }
4847
+ }
4848
+ return "discovery";
4849
+ }
4850
+ async function observeBrain(projectRoot, params) {
4851
+ const { text: text3, title: titleParam, type: typeParam, project, sourceSessionId, sourceType } = params;
4852
+ if (!text3 || !text3.trim()) {
4853
+ throw new Error("Observation text is required");
4854
+ }
4855
+ const type = typeParam ?? classifyObservationType(text3);
4856
+ const title = titleParam ?? text3.slice(0, 120);
4857
+ const now = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19);
4858
+ const contentHash = createHash3("sha256").update(title + text3).digest("hex").slice(0, 16);
4859
+ const nativeDb = getBrainNativeDb();
4860
+ if (nativeDb) {
4861
+ const cutoff = new Date(Date.now() - 3e4).toISOString().replace("T", " ").slice(0, 19);
4862
+ const existing = nativeDb.prepare(
4863
+ "SELECT id, type, created_at FROM brain_observations WHERE content_hash = ? AND created_at > ?"
4864
+ ).all(contentHash, cutoff);
4865
+ if (existing.length > 0) {
4866
+ return {
4867
+ id: existing[0].id,
4868
+ type: existing[0].type,
4869
+ createdAt: existing[0].created_at
4870
+ };
4871
+ }
4872
+ }
4873
+ const id = `O-${Date.now().toString(36)}`;
4874
+ const accessor = await getBrainAccessor(projectRoot);
4875
+ const row = await accessor.addObservation({
4876
+ id,
4877
+ type,
4878
+ title,
4879
+ narrative: text3,
4880
+ contentHash,
4881
+ project: project ?? null,
4882
+ sourceSessionId: sourceSessionId ?? null,
4883
+ sourceType: sourceType ?? "agent",
4884
+ createdAt: now
4885
+ });
4886
+ return {
4887
+ id: row.id,
4888
+ type: row.type,
4889
+ createdAt: row.createdAt
4890
+ };
4891
+ }
4892
+ var TYPE_KEYWORDS;
4893
+ var init_brain_retrieval = __esm({
4894
+ "src/core/memory/brain-retrieval.ts"() {
4895
+ "use strict";
4896
+ init_brain_search();
4897
+ init_brain_accessor();
4898
+ init_brain_sqlite();
4899
+ TYPE_KEYWORDS = [
4900
+ { keywords: ["bug", "fix", "error", "crash"], type: "bugfix" },
4901
+ { keywords: ["refactor", "rename", "extract", "move"], type: "refactor" },
4902
+ { keywords: ["add", "create", "implement", "new"], type: "feature" },
4903
+ { keywords: ["decide", "chose", "pick", "instead"], type: "decision" },
4904
+ { keywords: ["update", "change", "modify", "upgrade"], type: "change" }
4905
+ ];
4906
+ }
4907
+ });
4908
+
4909
+ // src/core/memory/brain-links.ts
4910
+ var brain_links_exports = {};
4911
+ __export(brain_links_exports, {
4912
+ bulkLink: () => bulkLink,
4913
+ getLinkedDecisions: () => getLinkedDecisions,
4914
+ getLinkedLearnings: () => getLinkedLearnings,
4915
+ getLinkedPatterns: () => getLinkedPatterns,
4916
+ getMemoryLinks: () => getMemoryLinks,
4917
+ getTaskLinks: () => getTaskLinks,
4918
+ linkMemoryToTask: () => linkMemoryToTask,
4919
+ unlinkMemoryFromTask: () => unlinkMemoryFromTask
4920
+ });
4921
+ async function linkMemoryToTask(projectRoot, memoryType, memoryId, taskId, linkType) {
4922
+ if (!memoryId || !taskId) {
4923
+ throw new Error("memoryId and taskId are required");
4924
+ }
4925
+ const accessor = await getBrainAccessor(projectRoot);
4926
+ const existingLinks = await accessor.getLinksForMemory(memoryType, memoryId);
4927
+ const duplicate = existingLinks.find(
4928
+ (l) => l.taskId === taskId && l.linkType === linkType
4929
+ );
4930
+ if (duplicate) {
4931
+ return duplicate;
4932
+ }
4933
+ await accessor.addLink({
4934
+ memoryType,
4935
+ memoryId,
4936
+ taskId,
4937
+ linkType
4938
+ });
4939
+ const links = await accessor.getLinksForMemory(memoryType, memoryId);
4940
+ return links.find(
4941
+ (l) => l.taskId === taskId && l.linkType === linkType
4942
+ );
4943
+ }
4944
+ async function unlinkMemoryFromTask(projectRoot, memoryType, memoryId, taskId, linkType) {
4945
+ const accessor = await getBrainAccessor(projectRoot);
4946
+ await accessor.removeLink(memoryType, memoryId, taskId, linkType);
4947
+ }
4948
+ async function getTaskLinks(projectRoot, taskId) {
4949
+ const accessor = await getBrainAccessor(projectRoot);
4950
+ return accessor.getLinksForTask(taskId);
4951
+ }
4952
+ async function getMemoryLinks(projectRoot, memoryType, memoryId) {
4953
+ const accessor = await getBrainAccessor(projectRoot);
4954
+ return accessor.getLinksForMemory(memoryType, memoryId);
4955
+ }
4956
+ async function bulkLink(projectRoot, links) {
4957
+ const accessor = await getBrainAccessor(projectRoot);
4958
+ let created = 0;
4959
+ let skipped = 0;
4960
+ for (const link of links) {
4961
+ const existing = await accessor.getLinksForMemory(link.memoryType, link.memoryId);
4962
+ const duplicate = existing.find(
4963
+ (l) => l.taskId === link.taskId && l.linkType === link.linkType
4964
+ );
4965
+ if (duplicate) {
4966
+ skipped++;
4967
+ continue;
4968
+ }
4969
+ await accessor.addLink({
4970
+ memoryType: link.memoryType,
4971
+ memoryId: link.memoryId,
4972
+ taskId: link.taskId,
4973
+ linkType: link.linkType
4974
+ });
4975
+ created++;
4976
+ }
4977
+ return { created, skipped };
4978
+ }
4979
+ async function getLinkedDecisions(projectRoot, taskId) {
4980
+ const accessor = await getBrainAccessor(projectRoot);
4981
+ const links = await accessor.getLinksForTask(taskId);
4982
+ const decisionLinks = links.filter((l) => l.memoryType === "decision");
4983
+ const decisions = [];
4984
+ for (const link of decisionLinks) {
4985
+ const decision = await accessor.getDecision(link.memoryId);
4986
+ if (decision) {
4987
+ decisions.push(decision);
4988
+ }
4989
+ }
4990
+ return decisions;
4991
+ }
4992
+ async function getLinkedPatterns(projectRoot, taskId) {
4993
+ const accessor = await getBrainAccessor(projectRoot);
4994
+ const links = await accessor.getLinksForTask(taskId);
4995
+ const patternLinks = links.filter((l) => l.memoryType === "pattern");
4996
+ const patterns = [];
4997
+ for (const link of patternLinks) {
4998
+ const pattern = await accessor.getPattern(link.memoryId);
4999
+ if (pattern) {
5000
+ patterns.push(pattern);
5001
+ }
5002
+ }
5003
+ return patterns;
5004
+ }
5005
+ async function getLinkedLearnings(projectRoot, taskId) {
5006
+ const accessor = await getBrainAccessor(projectRoot);
5007
+ const links = await accessor.getLinksForTask(taskId);
5008
+ const learningLinks = links.filter((l) => l.memoryType === "learning");
5009
+ const learnings = [];
5010
+ for (const link of learningLinks) {
5011
+ const learning = await accessor.getLearning(link.memoryId);
5012
+ if (learning) {
5013
+ learnings.push(learning);
5014
+ }
5015
+ }
5016
+ return learnings;
5017
+ }
5018
+ var init_brain_links = __esm({
5019
+ "src/core/memory/brain-links.ts"() {
5020
+ "use strict";
5021
+ init_brain_accessor();
5022
+ }
5023
+ });
5024
+
5025
+ // src/core/memory/session-memory.ts
5026
+ var session_memory_exports = {};
5027
+ __export(session_memory_exports, {
5028
+ extractMemoryItems: () => extractMemoryItems,
5029
+ getSessionMemoryContext: () => getSessionMemoryContext,
5030
+ persistSessionMemory: () => persistSessionMemory
5031
+ });
5032
+ function extractMemoryItems(sessionId, debrief) {
5033
+ if (!debrief) return [];
5034
+ const items = [];
5035
+ if (Array.isArray(debrief.decisions)) {
5036
+ for (const d of debrief.decisions) {
5037
+ const decision = d;
5038
+ if (!decision.decision) continue;
5039
+ const text3 = `Decision: ${decision.decision}
5040
+ Rationale: ${decision.rationale ?? "N/A"}`;
5041
+ items.push({
5042
+ text: text3,
5043
+ title: decision.decision.slice(0, 120),
5044
+ type: "decision",
5045
+ sourceSessionId: sessionId,
5046
+ sourceType: "session-debrief",
5047
+ linkTaskId: decision.taskId || void 0
5048
+ });
5049
+ }
5050
+ }
5051
+ const tasksCompleted = debrief.handoff?.tasksCompleted;
5052
+ if (Array.isArray(tasksCompleted) && tasksCompleted.length > 0) {
5053
+ const taskList2 = tasksCompleted.join(", ");
5054
+ const nextSuggested = debrief.handoff?.nextSuggested;
5055
+ const nextPart = Array.isArray(nextSuggested) && nextSuggested.length > 0 ? ` Next suggested: ${nextSuggested.join(", ")}` : "";
5056
+ const text3 = `Session ${sessionId} completed ${tasksCompleted.length} tasks: ${taskList2}.${nextPart}`;
5057
+ items.push({
5058
+ text: text3,
5059
+ title: `Session ${sessionId} summary: ${tasksCompleted.length} tasks completed`.slice(0, 120),
5060
+ type: "change",
5061
+ sourceSessionId: sessionId,
5062
+ sourceType: "session-debrief"
5063
+ });
5064
+ }
5065
+ const note = debrief.handoff?.note;
5066
+ if (typeof note === "string" && note.trim()) {
5067
+ items.push({
5068
+ text: note,
5069
+ title: `Session note: ${note.slice(0, 100)}`.slice(0, 120),
5070
+ type: "discovery",
5071
+ sourceSessionId: sessionId,
5072
+ sourceType: "session-debrief"
5073
+ });
5074
+ }
5075
+ return items;
5076
+ }
5077
+ async function persistSessionMemory(projectRoot, sessionId, debrief) {
5078
+ const result = {
5079
+ observationsCreated: 0,
5080
+ linksCreated: 0,
5081
+ observationIds: [],
5082
+ errors: []
5083
+ };
5084
+ if (!debrief) return result;
5085
+ const items = extractMemoryItems(sessionId, debrief);
5086
+ if (items.length === 0) return result;
5087
+ let observeBrain2;
5088
+ let linkMemoryToTask2;
5089
+ try {
5090
+ const retrieval = await Promise.resolve().then(() => (init_brain_retrieval(), brain_retrieval_exports));
5091
+ observeBrain2 = retrieval.observeBrain;
5092
+ const links = await Promise.resolve().then(() => (init_brain_links(), brain_links_exports));
5093
+ linkMemoryToTask2 = links.linkMemoryToTask;
5094
+ } catch (err) {
5095
+ result.errors.push(`Failed to load brain modules: ${err instanceof Error ? err.message : String(err)}`);
5096
+ return result;
5097
+ }
5098
+ for (const item of items) {
5099
+ let obsResult = null;
5100
+ try {
5101
+ obsResult = await observeBrain2(projectRoot, {
5102
+ text: item.text,
5103
+ title: item.title,
5104
+ type: item.type,
5105
+ sourceSessionId: item.sourceSessionId,
5106
+ sourceType: item.sourceType
5107
+ });
5108
+ result.observationsCreated++;
5109
+ result.observationIds.push(obsResult.id);
5110
+ } catch (err) {
5111
+ result.errors.push(`Failed to create observation: ${err instanceof Error ? err.message : String(err)}`);
5112
+ continue;
5113
+ }
5114
+ if (item.linkTaskId && obsResult) {
5115
+ try {
5116
+ await linkMemoryToTask2(
5117
+ projectRoot,
5118
+ "observation",
5119
+ obsResult.id,
5120
+ item.linkTaskId,
5121
+ "produced_by"
5122
+ );
5123
+ result.linksCreated++;
5124
+ } catch (err) {
5125
+ result.errors.push(`Failed to link observation ${obsResult.id} to task ${item.linkTaskId}: ${err instanceof Error ? err.message : String(err)}`);
5126
+ }
5127
+ }
5128
+ }
5129
+ return result;
5130
+ }
5131
+ async function getSessionMemoryContext(projectRoot, scope, options) {
5132
+ const emptyContext = {
5133
+ recentDecisions: [],
5134
+ relevantPatterns: [],
5135
+ recentObservations: [],
5136
+ tokensEstimated: 0
5137
+ };
5138
+ let searchBrainCompact2;
5139
+ try {
5140
+ const retrieval = await Promise.resolve().then(() => (init_brain_retrieval(), brain_retrieval_exports));
5141
+ searchBrainCompact2 = retrieval.searchBrainCompact;
5142
+ } catch {
5143
+ return emptyContext;
5144
+ }
5145
+ const limit = options?.limit ?? 5;
5146
+ const scopeQuery = scope?.rootTaskId ?? scope?.epicId ?? "";
5147
+ try {
5148
+ const [decisionsResult, patternsResult, observationsResult] = await Promise.all([
5149
+ // Decisions: scope-filtered if we have a task ID, otherwise recent
5150
+ scopeQuery ? searchBrainCompact2(projectRoot, {
5151
+ query: scopeQuery,
5152
+ limit,
5153
+ tables: ["decisions"]
5154
+ }) : Promise.resolve({ results: [], total: 0, tokensEstimated: 0 }),
5155
+ // Patterns: recent patterns
5156
+ searchBrainCompact2(projectRoot, {
5157
+ query: scopeQuery || "pattern",
5158
+ limit: Math.min(limit, 3),
5159
+ tables: ["patterns"]
5160
+ }),
5161
+ // Observations: recent session-debrief observations
5162
+ searchBrainCompact2(projectRoot, {
5163
+ query: scopeQuery || "session",
5164
+ limit,
5165
+ tables: ["observations"]
5166
+ })
5167
+ ]);
5168
+ const tokensEstimated = decisionsResult.tokensEstimated + patternsResult.tokensEstimated + observationsResult.tokensEstimated;
5169
+ return {
5170
+ recentDecisions: decisionsResult.results,
5171
+ relevantPatterns: patternsResult.results,
5172
+ recentObservations: observationsResult.results,
5173
+ tokensEstimated
5174
+ };
5175
+ } catch {
5176
+ return emptyContext;
5177
+ }
5178
+ }
5179
+ var init_session_memory = __esm({
5180
+ "src/core/memory/session-memory.ts"() {
5181
+ "use strict";
5182
+ }
5183
+ });
5184
+
3853
5185
  // src/core/platform.ts
3854
5186
  var platform_exports = {};
3855
5187
  __export(platform_exports, {
@@ -3877,9 +5209,9 @@ __export(platform_exports, {
3877
5209
  });
3878
5210
  import { execFileSync } from "node:child_process";
3879
5211
  import { tmpdir } from "node:os";
3880
- import { join as join11 } from "node:path";
5212
+ import { join as join12 } from "node:path";
3881
5213
  import { existsSync as existsSync11, statSync as statSync2 } from "node:fs";
3882
- import { createHash as createHash3, randomBytes as randomBytes6 } from "node:crypto";
5214
+ import { createHash as createHash4, randomBytes as randomBytes6 } from "node:crypto";
3883
5215
  function detectPlatform() {
3884
5216
  switch (process.platform) {
3885
5217
  case "linux":
@@ -3948,11 +5280,11 @@ function generateRandomHex(bytes = 6) {
3948
5280
  return randomBytes6(bytes).toString("hex");
3949
5281
  }
3950
5282
  function sha256(data) {
3951
- return createHash3("sha256").update(data).digest("hex");
5283
+ return createHash4("sha256").update(data).digest("hex");
3952
5284
  }
3953
5285
  function createTempFilePath(prefix = "cleo-", suffix = ".tmp") {
3954
5286
  const random = generateRandomHex(8);
3955
- return join11(tmpdir(), `${prefix}${random}${suffix}`);
5287
+ return join12(tmpdir(), `${prefix}${random}${suffix}`);
3956
5288
  }
3957
5289
  function getNodeVersionInfo() {
3958
5290
  const version = process.version.replace("v", "");
@@ -4021,7 +5353,7 @@ var init_platform = __esm({
4021
5353
 
4022
5354
  // src/core/migration/preflight.ts
4023
5355
  import { existsSync as existsSync13, readFileSync as readFileSync7, statSync as statSync3 } from "node:fs";
4024
- import { join as join13 } from "node:path";
5356
+ import { join as join14 } from "node:path";
4025
5357
  function checkStorageMigration(cwd) {
4026
5358
  const cleoDir = getCleoDirAbsolute(cwd);
4027
5359
  const details = {
@@ -4036,7 +5368,7 @@ function checkStorageMigration(cwd) {
4036
5368
  tasksDbSize: 0,
4037
5369
  configEngine: null
4038
5370
  };
4039
- const configPath = join13(cleoDir, "config.json");
5371
+ const configPath = join14(cleoDir, "config.json");
4040
5372
  if (existsSync13(configPath)) {
4041
5373
  try {
4042
5374
  const config = JSON.parse(readFileSync7(configPath, "utf-8"));
@@ -4044,7 +5376,7 @@ function checkStorageMigration(cwd) {
4044
5376
  } catch {
4045
5377
  }
4046
5378
  }
4047
- const todoPath = join13(cleoDir, "todo.json");
5379
+ const todoPath = join14(cleoDir, "todo.json");
4048
5380
  if (existsSync13(todoPath)) {
4049
5381
  details.todoJsonExists = true;
4050
5382
  try {
@@ -4053,7 +5385,7 @@ function checkStorageMigration(cwd) {
4053
5385
  } catch {
4054
5386
  }
4055
5387
  }
4056
- const archivePath = join13(cleoDir, "todo-archive.json");
5388
+ const archivePath = join14(cleoDir, "todo-archive.json");
4057
5389
  if (existsSync13(archivePath)) {
4058
5390
  details.archiveJsonExists = true;
4059
5391
  try {
@@ -4062,7 +5394,7 @@ function checkStorageMigration(cwd) {
4062
5394
  } catch {
4063
5395
  }
4064
5396
  }
4065
- const sessionsPath = join13(cleoDir, "sessions.json");
5397
+ const sessionsPath = join14(cleoDir, "sessions.json");
4066
5398
  if (existsSync13(sessionsPath)) {
4067
5399
  details.sessionsJsonExists = true;
4068
5400
  try {
@@ -4071,11 +5403,11 @@ function checkStorageMigration(cwd) {
4071
5403
  } catch {
4072
5404
  }
4073
5405
  }
4074
- const tasksJsonPath = join13(cleoDir, "tasks.json");
5406
+ const tasksJsonPath = join14(cleoDir, "tasks.json");
4075
5407
  if (existsSync13(tasksJsonPath)) {
4076
5408
  details.tasksJsonExists = true;
4077
5409
  }
4078
- const dbPath = join13(cleoDir, "tasks.db");
5410
+ const dbPath = join14(cleoDir, "tasks.db");
4079
5411
  if (existsSync13(dbPath)) {
4080
5412
  details.tasksDbExists = true;
4081
5413
  try {
@@ -4123,17 +5455,17 @@ import {
4123
5455
  existsSync as existsSync14,
4124
5456
  readFileSync as readFileSync8,
4125
5457
  writeFileSync as writeFileSync2,
4126
- mkdirSync as mkdirSync6,
5458
+ mkdirSync as mkdirSync7,
4127
5459
  readdirSync as readdirSync3,
4128
5460
  copyFileSync as copyFileSync2,
4129
5461
  statSync as statSync4,
4130
5462
  rmSync
4131
5463
  } from "node:fs";
4132
- import { join as join14 } from "node:path";
5464
+ import { join as join15 } from "node:path";
4133
5465
  function detectLegacyAgentOutputs(projectRoot, cleoDir) {
4134
- const hasResearchOutputs = existsSync14(join14(projectRoot, "claudedocs", "research-outputs"));
4135
- const hasLegacyAgentOutputs = existsSync14(join14(projectRoot, "claudedocs", "agent-outputs"));
4136
- const hasCanonical = existsSync14(join14(cleoDir, "agent-outputs"));
5466
+ const hasResearchOutputs = existsSync14(join15(projectRoot, "claudedocs", "research-outputs"));
5467
+ const hasLegacyAgentOutputs = existsSync14(join15(projectRoot, "claudedocs", "agent-outputs"));
5468
+ const hasCanonical = existsSync14(join15(cleoDir, "agent-outputs"));
4137
5469
  const legacyPaths = [];
4138
5470
  if (hasResearchOutputs) legacyPaths.push("claudedocs/research-outputs/");
4139
5471
  if (hasLegacyAgentOutputs) legacyPaths.push("claudedocs/agent-outputs/");
@@ -4156,15 +5488,15 @@ function migrateAgentOutputs(projectRoot, cleoDir) {
4156
5488
  summary: "No legacy output directories found"
4157
5489
  };
4158
5490
  }
4159
- const newDir = join14(cleoDir, "agent-outputs");
5491
+ const newDir = join15(cleoDir, "agent-outputs");
4160
5492
  const hadCanonical = detection.hasCanonical;
4161
- mkdirSync6(newDir, { recursive: true });
5493
+ mkdirSync7(newDir, { recursive: true });
4162
5494
  let totalCopied = 0;
4163
5495
  const mergedManifestLines = [];
4164
5496
  const copiedFiles = /* @__PURE__ */ new Set();
4165
5497
  const legacySources = [
4166
- { path: join14(projectRoot, "claudedocs", "research-outputs"), exists: detection.hasResearchOutputs },
4167
- { path: join14(projectRoot, "claudedocs", "agent-outputs"), exists: detection.hasLegacyAgentOutputs }
5498
+ { path: join15(projectRoot, "claudedocs", "research-outputs"), exists: detection.hasResearchOutputs },
5499
+ { path: join15(projectRoot, "claudedocs", "agent-outputs"), exists: detection.hasLegacyAgentOutputs }
4168
5500
  ];
4169
5501
  for (const source of legacySources) {
4170
5502
  if (!source.exists) continue;
@@ -4189,19 +5521,19 @@ function copyDirContents(srcDir, dstDir, manifestLines, copiedFiles) {
4189
5521
  const entries = readdirSync3(srcDir);
4190
5522
  for (const entry of entries) {
4191
5523
  if (entry === "MANIFEST.jsonl") {
4192
- collectManifestLines(join14(srcDir, entry), manifestLines);
5524
+ collectManifestLines(join15(srcDir, entry), manifestLines);
4193
5525
  continue;
4194
5526
  }
4195
- const srcPath = join14(srcDir, entry);
4196
- const dstPath = join14(dstDir, entry);
5527
+ const srcPath = join15(srcDir, entry);
5528
+ const dstPath = join15(dstDir, entry);
4197
5529
  try {
4198
5530
  const st = statSync4(srcPath);
4199
5531
  if (st.isDirectory()) {
4200
- mkdirSync6(dstPath, { recursive: true });
5532
+ mkdirSync7(dstPath, { recursive: true });
4201
5533
  for (const sf of readdirSync3(srcPath)) {
4202
5534
  if (!copiedFiles.has(sf)) {
4203
5535
  try {
4204
- copyFileSync2(join14(srcPath, sf), join14(dstPath, sf));
5536
+ copyFileSync2(join15(srcPath, sf), join15(dstPath, sf));
4205
5537
  copiedFiles.add(sf);
4206
5538
  count2++;
4207
5539
  } catch {
@@ -4233,7 +5565,7 @@ function collectManifestLines(manifestPath, out) {
4233
5565
  }
4234
5566
  }
4235
5567
  function mergeManifests(newDir, hadCanonical, legacyLines) {
4236
- const manifestPath = join14(newDir, "MANIFEST.jsonl");
5568
+ const manifestPath = join15(newDir, "MANIFEST.jsonl");
4237
5569
  const existingLines = [];
4238
5570
  if (hadCanonical && existsSync14(manifestPath)) {
4239
5571
  try {
@@ -4269,7 +5601,7 @@ function mergeManifests(newDir, hadCanonical, legacyLines) {
4269
5601
  return finalLines.length;
4270
5602
  }
4271
5603
  function updateConfigPaths(cleoDir) {
4272
- const configPath = join14(cleoDir, "config.json");
5604
+ const configPath = join15(cleoDir, "config.json");
4273
5605
  if (!existsSync14(configPath)) return;
4274
5606
  try {
4275
5607
  const config = JSON.parse(readFileSync8(configPath, "utf-8"));
@@ -4295,19 +5627,19 @@ function removeLegacyDirs(projectRoot, detection) {
4295
5627
  const removed = [];
4296
5628
  if (detection.hasResearchOutputs) {
4297
5629
  try {
4298
- rmSync(join14(projectRoot, "claudedocs", "research-outputs"), { recursive: true, force: true });
5630
+ rmSync(join15(projectRoot, "claudedocs", "research-outputs"), { recursive: true, force: true });
4299
5631
  removed.push("claudedocs/research-outputs/");
4300
5632
  } catch {
4301
5633
  }
4302
5634
  }
4303
5635
  if (detection.hasLegacyAgentOutputs) {
4304
5636
  try {
4305
- rmSync(join14(projectRoot, "claudedocs", "agent-outputs"), { recursive: true, force: true });
5637
+ rmSync(join15(projectRoot, "claudedocs", "agent-outputs"), { recursive: true, force: true });
4306
5638
  removed.push("claudedocs/agent-outputs/");
4307
5639
  } catch {
4308
5640
  }
4309
5641
  }
4310
- const claudedocsDir = join14(projectRoot, "claudedocs");
5642
+ const claudedocsDir = join15(projectRoot, "claudedocs");
4311
5643
  if (existsSync14(claudedocsDir)) {
4312
5644
  try {
4313
5645
  if (readdirSync3(claudedocsDir).length === 0) {
@@ -4413,15 +5745,15 @@ __export(schema_management_exports, {
4413
5745
  listInstalledSchemas: () => listInstalledSchemas,
4414
5746
  resolveSchemaPath: () => resolveSchemaPath
4415
5747
  });
4416
- import { existsSync as existsSync15, readFileSync as readFileSync9, readdirSync as readdirSync4, mkdirSync as mkdirSync7, copyFileSync as copyFileSync3, renameSync as renameSync5, statSync as statSync5 } from "node:fs";
4417
- import { join as join15 } from "node:path";
5748
+ import { existsSync as existsSync15, readFileSync as readFileSync9, readdirSync as readdirSync4, mkdirSync as mkdirSync8, copyFileSync as copyFileSync3, renameSync as renameSync5, statSync as statSync5 } from "node:fs";
5749
+ import { join as join16 } from "node:path";
4418
5750
  function resolveSchemaPath(schemaName) {
4419
- const globalPath = join15(getCleoSchemasDir(), schemaName);
5751
+ const globalPath = join16(getCleoSchemasDir(), schemaName);
4420
5752
  if (existsSync15(globalPath)) {
4421
5753
  return globalPath;
4422
5754
  }
4423
5755
  const packageRoot = getPackageRoot();
4424
- const bundledPath = join15(packageRoot, "schemas", schemaName);
5756
+ const bundledPath = join16(packageRoot, "schemas", schemaName);
4425
5757
  if (existsSync15(bundledPath)) {
4426
5758
  return bundledPath;
4427
5759
  }
@@ -4445,7 +5777,7 @@ function getSchemaVersion2(schemaName) {
4445
5777
  }
4446
5778
  function listBundledSchemas() {
4447
5779
  const packageRoot = getPackageRoot();
4448
- const schemasDir = join15(packageRoot, "schemas");
5780
+ const schemasDir = join16(packageRoot, "schemas");
4449
5781
  if (!existsSync15(schemasDir)) return [];
4450
5782
  try {
4451
5783
  return readdirSync4(schemasDir).filter((f) => f.endsWith(".schema.json"));
@@ -4469,7 +5801,7 @@ function readVersionFromPath(schemaPath) {
4469
5801
  }
4470
5802
  function ensureGlobalSchemas(_opts) {
4471
5803
  const packageRoot = getPackageRoot();
4472
- const bundledDir = join15(packageRoot, "schemas");
5804
+ const bundledDir = join16(packageRoot, "schemas");
4473
5805
  const globalDir = getCleoSchemasDir();
4474
5806
  const bundledFiles = listBundledSchemas();
4475
5807
  let installed = 0;
@@ -4478,11 +5810,11 @@ function ensureGlobalSchemas(_opts) {
4478
5810
  return { installed: 0, updated: 0, total: 0 };
4479
5811
  }
4480
5812
  if (!existsSync15(globalDir)) {
4481
- mkdirSync7(globalDir, { recursive: true });
5813
+ mkdirSync8(globalDir, { recursive: true });
4482
5814
  }
4483
5815
  for (const file of bundledFiles) {
4484
- const source = join15(bundledDir, file);
4485
- const target = join15(globalDir, file);
5816
+ const source = join16(bundledDir, file);
5817
+ const target = join16(globalDir, file);
4486
5818
  if (!existsSync15(target)) {
4487
5819
  copyFileSync3(source, target);
4488
5820
  installed++;
@@ -4508,15 +5840,15 @@ function checkGlobalSchemas() {
4508
5840
  const stale = [];
4509
5841
  let installedCount = 0;
4510
5842
  const packageRoot = getPackageRoot();
4511
- const bundledDir = join15(packageRoot, "schemas");
5843
+ const bundledDir = join16(packageRoot, "schemas");
4512
5844
  for (const file of bundledFiles) {
4513
- const globalPath = join15(globalDir, file);
5845
+ const globalPath = join16(globalDir, file);
4514
5846
  if (!existsSync15(globalPath)) {
4515
5847
  missing.push(file);
4516
5848
  continue;
4517
5849
  }
4518
5850
  installedCount++;
4519
- const bundledVersion = readVersionFromPath(join15(bundledDir, file));
5851
+ const bundledVersion = readVersionFromPath(join16(bundledDir, file));
4520
5852
  const globalVersion = readVersionFromPath(globalPath);
4521
5853
  if (bundledVersion !== null && bundledVersion !== globalVersion) {
4522
5854
  stale.push(file);
@@ -4537,14 +5869,14 @@ function checkSchemaStaleness() {
4537
5869
  const current = [];
4538
5870
  const missing = [];
4539
5871
  const packageRoot = getPackageRoot();
4540
- const bundledDir = join15(packageRoot, "schemas");
5872
+ const bundledDir = join16(packageRoot, "schemas");
4541
5873
  for (const file of bundledFiles) {
4542
- const globalPath = join15(globalDir, file);
5874
+ const globalPath = join16(globalDir, file);
4543
5875
  if (!existsSync15(globalPath)) {
4544
5876
  missing.push(file);
4545
5877
  continue;
4546
5878
  }
4547
- const bundledVersion = readVersionFromPath(join15(bundledDir, file));
5879
+ const bundledVersion = readVersionFromPath(join16(bundledDir, file));
4548
5880
  const globalVersion = readVersionFromPath(globalPath);
4549
5881
  if (bundledVersion !== null && bundledVersion !== globalVersion) {
4550
5882
  stale.push(file);
@@ -4564,7 +5896,7 @@ function listInstalledSchemas() {
4564
5896
  return [];
4565
5897
  }
4566
5898
  return files.map((name) => {
4567
- const fullPath = join15(globalDir, name);
5899
+ const fullPath = join16(globalDir, name);
4568
5900
  return {
4569
5901
  name,
4570
5902
  path: fullPath,
@@ -4573,7 +5905,7 @@ function listInstalledSchemas() {
4573
5905
  });
4574
5906
  }
4575
5907
  async function cleanProjectSchemas(projectRoot) {
4576
- const projectSchemasDir = join15(projectRoot, ".cleo", "schemas");
5908
+ const projectSchemasDir = join16(projectRoot, ".cleo", "schemas");
4577
5909
  if (!existsSync15(projectSchemasDir)) {
4578
5910
  return { cleaned: false };
4579
5911
  }
@@ -4586,10 +5918,10 @@ async function cleanProjectSchemas(projectRoot) {
4586
5918
  return { cleaned: false };
4587
5919
  }
4588
5920
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
4589
- const backupDir = join15(projectRoot, ".cleo", "backups", "schemas");
4590
- const backupTarget = join15(backupDir, `schemas-${timestamp}`);
5921
+ const backupDir = join16(projectRoot, ".cleo", "backups", "schemas");
5922
+ const backupTarget = join16(backupDir, `schemas-${timestamp}`);
4591
5923
  if (!existsSync15(backupDir)) {
4592
- mkdirSync7(backupDir, { recursive: true });
5924
+ mkdirSync8(backupDir, { recursive: true });
4593
5925
  }
4594
5926
  renameSync5(projectSchemasDir, backupTarget);
4595
5927
  return { cleaned: true };
@@ -4609,7 +5941,7 @@ __export(schema_integrity_exports, {
4609
5941
  readSchemaVersionFromFile: () => readSchemaVersionFromFile
4610
5942
  });
4611
5943
  import { existsSync as existsSync16, readFileSync as readFileSync10 } from "node:fs";
4612
- import { join as join16 } from "node:path";
5944
+ import { join as join17 } from "node:path";
4613
5945
  function readSchemaVersionFromFile(schemaName) {
4614
5946
  return getSchemaVersion2(schemaName);
4615
5947
  }
@@ -4710,28 +6042,28 @@ var init_schema_integrity = __esm({
4710
6042
  INTEGRITY_TARGETS = [
4711
6043
  {
4712
6044
  label: "config.json",
4713
- filePath: (d) => join16(d, "config.json"),
6045
+ filePath: (d) => join17(d, "config.json"),
4714
6046
  schemaName: "config.schema.json",
4715
6047
  required: true,
4716
6048
  versionKey: "schemaVersion"
4717
6049
  },
4718
6050
  {
4719
6051
  label: "project-info.json",
4720
- filePath: (d) => join16(d, "project-info.json"),
6052
+ filePath: (d) => join17(d, "project-info.json"),
4721
6053
  schemaName: "project-info.schema.json",
4722
6054
  required: false,
4723
6055
  versionKey: "schemaVersion"
4724
6056
  },
4725
6057
  {
4726
6058
  label: "project-context.json",
4727
- filePath: (d) => join16(d, "project-context.json"),
6059
+ filePath: (d) => join17(d, "project-context.json"),
4728
6060
  schemaName: "project-context.schema.json",
4729
6061
  required: false,
4730
6062
  versionKey: "schemaVersion"
4731
6063
  },
4732
6064
  {
4733
6065
  label: ".context-state.json",
4734
- filePath: (d) => join16(d, ".context-state.json"),
6066
+ filePath: (d) => join17(d, ".context-state.json"),
4735
6067
  schemaName: "context-state.schema.json",
4736
6068
  required: false,
4737
6069
  versionKey: "version"
@@ -4746,9 +6078,9 @@ __export(project_detect_exports, {
4746
6078
  detectProjectType: () => detectProjectType
4747
6079
  });
4748
6080
  import { existsSync as existsSync17, readdirSync as readdirSync5 } from "node:fs";
4749
- import { join as join17 } from "node:path";
6081
+ import { join as join18 } from "node:path";
4750
6082
  function detectProjectType(projectDir) {
4751
- const exists = (f) => existsSync17(join17(projectDir, f));
6083
+ const exists = (f) => existsSync17(join18(projectDir, f));
4752
6084
  const info = {
4753
6085
  type: "unknown",
4754
6086
  testFramework: "unknown",
@@ -4837,9 +6169,9 @@ __export(scaffold_exports, {
4837
6169
  });
4838
6170
  import { mkdir as mkdir4, access, writeFile as writeFile3, readFile as readFile3 } from "node:fs/promises";
4839
6171
  import { constants as fsConstants, existsSync as existsSync18, readFileSync as readFileSync11, statSync as statSync6 } from "node:fs";
4840
- import { join as join18, resolve as resolve5, dirname as dirname6 } from "node:path";
4841
- import { fileURLToPath as fileURLToPath2 } from "node:url";
4842
- import { createHash as createHash4 } from "node:crypto";
6172
+ import { join as join19, resolve as resolve5, dirname as dirname7 } from "node:path";
6173
+ import { fileURLToPath as fileURLToPath3 } from "node:url";
6174
+ import { createHash as createHash5 } from "node:crypto";
4843
6175
  import { execFile as execFile3 } from "node:child_process";
4844
6176
  import { promisify as promisify3 } from "node:util";
4845
6177
  async function fileExists(path) {
@@ -4860,7 +6192,7 @@ async function stripCLEOBlocks(filePath) {
4860
6192
  if (stripped !== content) await writeFile3(filePath, stripped, "utf8");
4861
6193
  }
4862
6194
  async function removeCleoFromRootGitignore(projectRoot) {
4863
- const rootGitignorePath = join18(projectRoot, ".gitignore");
6195
+ const rootGitignorePath = join19(projectRoot, ".gitignore");
4864
6196
  if (!await fileExists(rootGitignorePath)) {
4865
6197
  return { removed: false };
4866
6198
  }
@@ -4877,16 +6209,16 @@ async function removeCleoFromRootGitignore(projectRoot) {
4877
6209
  return { removed: true };
4878
6210
  }
4879
6211
  function generateProjectHash(projectPath) {
4880
- return createHash4("sha256").update(projectPath).digest("hex").substring(0, 12);
6212
+ return createHash5("sha256").update(projectPath).digest("hex").substring(0, 12);
4881
6213
  }
4882
6214
  function getPackageRoot() {
4883
- const thisFile = fileURLToPath2(import.meta.url);
4884
- return resolve5(dirname6(thisFile), "..", "..");
6215
+ const thisFile = fileURLToPath3(import.meta.url);
6216
+ return resolve5(dirname7(thisFile), "..", "..");
4885
6217
  }
4886
6218
  function getGitignoreContent() {
4887
6219
  try {
4888
6220
  const packageRoot = getPackageRoot();
4889
- const templatePath = join18(packageRoot, "templates", "cleo-gitignore");
6221
+ const templatePath = join19(packageRoot, "templates", "cleo-gitignore");
4890
6222
  if (existsSync18(templatePath)) {
4891
6223
  return readFileSync11(templatePath, "utf-8");
4892
6224
  }
@@ -4896,7 +6228,7 @@ function getGitignoreContent() {
4896
6228
  }
4897
6229
  function getCleoVersion() {
4898
6230
  try {
4899
- const pkgPath = join18(getPackageRoot(), "package.json");
6231
+ const pkgPath = join19(getPackageRoot(), "package.json");
4900
6232
  const pkg = JSON.parse(readFileSync11(pkgPath, "utf-8"));
4901
6233
  return pkg.version ?? "0.0.0";
4902
6234
  } catch {
@@ -4934,7 +6266,7 @@ async function ensureCleoStructure(projectRoot) {
4934
6266
  const alreadyExists = existsSync18(cleoDir);
4935
6267
  await mkdir4(cleoDir, { recursive: true });
4936
6268
  for (const subdir of REQUIRED_CLEO_SUBDIRS) {
4937
- await mkdir4(join18(cleoDir, subdir), { recursive: true });
6269
+ await mkdir4(join19(cleoDir, subdir), { recursive: true });
4938
6270
  }
4939
6271
  return {
4940
6272
  action: alreadyExists ? "skipped" : "created",
@@ -4944,7 +6276,7 @@ async function ensureCleoStructure(projectRoot) {
4944
6276
  }
4945
6277
  async function ensureGitignore(projectRoot) {
4946
6278
  const cleoDir = getCleoDirAbsolute(projectRoot);
4947
- const gitignorePath = join18(cleoDir, ".gitignore");
6279
+ const gitignorePath = join19(cleoDir, ".gitignore");
4948
6280
  const templateContent = getGitignoreContent();
4949
6281
  if (existsSync18(gitignorePath)) {
4950
6282
  const existing = readFileSync11(gitignorePath, "utf-8");
@@ -4971,7 +6303,7 @@ async function ensureConfig(projectRoot, opts) {
4971
6303
  }
4972
6304
  async function ensureProjectInfo(projectRoot, opts) {
4973
6305
  const cleoDir = getCleoDirAbsolute(projectRoot);
4974
- const projectInfoPath = join18(cleoDir, "project-info.json");
6306
+ const projectInfoPath = join19(cleoDir, "project-info.json");
4975
6307
  if (existsSync18(projectInfoPath) && !opts?.force) {
4976
6308
  return { action: "skipped", path: projectInfoPath, details: "Already exists" };
4977
6309
  }
@@ -5012,7 +6344,7 @@ async function ensureProjectInfo(projectRoot, opts) {
5012
6344
  }
5013
6345
  async function ensureProjectContext(projectRoot, opts) {
5014
6346
  const cleoDir = getCleoDirAbsolute(projectRoot);
5015
- const contextPath = join18(cleoDir, "project-context.json");
6347
+ const contextPath = join19(cleoDir, "project-context.json");
5016
6348
  const staleDays = opts?.staleDays ?? 30;
5017
6349
  if (existsSync18(contextPath) && !opts?.force) {
5018
6350
  try {
@@ -5042,7 +6374,7 @@ async function ensureProjectContext(projectRoot, opts) {
5042
6374
  }
5043
6375
  async function ensureCleoGitRepo(projectRoot) {
5044
6376
  const cleoDir = getCleoDirAbsolute(projectRoot);
5045
- const cleoGitDir = join18(cleoDir, ".git");
6377
+ const cleoGitDir = join19(cleoDir, ".git");
5046
6378
  if (existsSync18(cleoGitDir)) {
5047
6379
  return { action: "skipped", path: cleoGitDir, details: "Already initialized" };
5048
6380
  }
@@ -5058,7 +6390,7 @@ async function ensureCleoGitRepo(projectRoot) {
5058
6390
  }
5059
6391
  async function ensureSqliteDb(projectRoot) {
5060
6392
  const cleoDir = getCleoDirAbsolute(projectRoot);
5061
- const dbPath = join18(cleoDir, "tasks.db");
6393
+ const dbPath = join19(cleoDir, "tasks.db");
5062
6394
  if (existsSync18(dbPath)) {
5063
6395
  return { action: "skipped", path: dbPath, details: "tasks.db already exists" };
5064
6396
  }
@@ -5088,7 +6420,7 @@ function checkCleoStructure(projectRoot) {
5088
6420
  };
5089
6421
  }
5090
6422
  for (const subdir of REQUIRED_CLEO_SUBDIRS) {
5091
- if (!existsSync18(join18(cleoDir, subdir))) {
6423
+ if (!existsSync18(join19(cleoDir, subdir))) {
5092
6424
  missing.push(subdir);
5093
6425
  }
5094
6426
  }
@@ -5113,7 +6445,7 @@ function checkCleoStructure(projectRoot) {
5113
6445
  }
5114
6446
  function checkGitignore(projectRoot) {
5115
6447
  const cleoDir = getCleoDirAbsolute(projectRoot);
5116
- const gitignorePath = join18(cleoDir, ".gitignore");
6448
+ const gitignorePath = join19(cleoDir, ".gitignore");
5117
6449
  if (!existsSync18(gitignorePath)) {
5118
6450
  return {
5119
6451
  id: "cleo_gitignore",
@@ -5172,7 +6504,7 @@ function checkConfig(projectRoot) {
5172
6504
  }
5173
6505
  function checkProjectInfo(projectRoot) {
5174
6506
  const cleoDir = getCleoDirAbsolute(projectRoot);
5175
- const infoPath = join18(cleoDir, "project-info.json");
6507
+ const infoPath = join19(cleoDir, "project-info.json");
5176
6508
  if (!existsSync18(infoPath)) {
5177
6509
  return {
5178
6510
  id: "cleo_project_info",
@@ -5218,7 +6550,7 @@ function checkProjectInfo(projectRoot) {
5218
6550
  }
5219
6551
  function checkProjectContext(projectRoot, staleDays = 30) {
5220
6552
  const cleoDir = getCleoDirAbsolute(projectRoot);
5221
- const contextPath = join18(cleoDir, "project-context.json");
6553
+ const contextPath = join19(cleoDir, "project-context.json");
5222
6554
  if (!existsSync18(contextPath)) {
5223
6555
  return {
5224
6556
  id: "cleo_project_context",
@@ -5275,7 +6607,7 @@ function checkProjectContext(projectRoot, staleDays = 30) {
5275
6607
  }
5276
6608
  function checkCleoGitRepo(projectRoot) {
5277
6609
  const cleoDir = getCleoDirAbsolute(projectRoot);
5278
- const cleoGitDir = join18(cleoDir, ".git");
6610
+ const cleoGitDir = join19(cleoDir, ".git");
5279
6611
  if (!existsSync18(cleoGitDir)) {
5280
6612
  return {
5281
6613
  id: "cleo_git_repo",
@@ -5297,7 +6629,7 @@ function checkCleoGitRepo(projectRoot) {
5297
6629
  }
5298
6630
  function checkSqliteDb(projectRoot) {
5299
6631
  const cleoDir = getCleoDirAbsolute(projectRoot);
5300
- const dbPath = join18(cleoDir, "tasks.db");
6632
+ const dbPath = join19(cleoDir, "tasks.db");
5301
6633
  if (!existsSync18(dbPath)) {
5302
6634
  return {
5303
6635
  id: "sqlite_db",
@@ -5390,11 +6722,11 @@ backups/
5390
6722
  // src/core/validation/doctor/checks.ts
5391
6723
  import { existsSync as existsSync19, readFileSync as readFileSync12, accessSync, constants, statSync as statSync7 } from "node:fs";
5392
6724
  import { execFileSync as execFileSync2 } from "node:child_process";
5393
- import { join as join19 } from "node:path";
6725
+ import { join as join20 } from "node:path";
5394
6726
  import { homedir as homedir2 } from "node:os";
5395
6727
  function checkCleoGitignore(projectRoot) {
5396
6728
  const root = projectRoot ?? process.cwd();
5397
- const gitignorePath = join19(root, ".cleo", ".gitignore");
6729
+ const gitignorePath = join20(root, ".cleo", ".gitignore");
5398
6730
  if (!existsSync19(gitignorePath)) {
5399
6731
  return {
5400
6732
  id: "cleo_gitignore",
@@ -5424,8 +6756,8 @@ function checkCleoGitignore(projectRoot) {
5424
6756
  } catch {
5425
6757
  try {
5426
6758
  const templatePaths = [
5427
- join19(root, "templates", "cleo-gitignore"),
5428
- join19(homedir2(), ".cleo", "templates", "cleo-gitignore")
6759
+ join20(root, "templates", "cleo-gitignore"),
6760
+ join20(homedir2(), ".cleo", "templates", "cleo-gitignore")
5429
6761
  ];
5430
6762
  for (const tp of templatePaths) {
5431
6763
  if (existsSync19(tp)) {
@@ -5466,7 +6798,7 @@ function detectStorageEngine(_projectRoot) {
5466
6798
  }
5467
6799
  function checkVitalFilesTracked(projectRoot) {
5468
6800
  const root = projectRoot ?? process.cwd();
5469
- const gitDir = join19(root, ".git");
6801
+ const gitDir = join20(root, ".git");
5470
6802
  if (!existsSync19(gitDir)) {
5471
6803
  return {
5472
6804
  id: "vital_files_tracked",
@@ -5481,7 +6813,7 @@ function checkVitalFilesTracked(projectRoot) {
5481
6813
  const vitalFiles = CORE_PROTECTED_FILES.map((f) => `.cleo/${f}`);
5482
6814
  const untracked = [];
5483
6815
  for (const file of vitalFiles) {
5484
- const fullPath = join19(root, file);
6816
+ const fullPath = join20(root, file);
5485
6817
  if (!existsSync19(fullPath)) continue;
5486
6818
  try {
5487
6819
  execFileSync2("git", ["ls-files", "--error-unmatch", file], {
@@ -5513,7 +6845,7 @@ function checkVitalFilesTracked(projectRoot) {
5513
6845
  }
5514
6846
  function checkCoreFilesNotIgnored(projectRoot) {
5515
6847
  const root = projectRoot ?? process.cwd();
5516
- const gitDir = join19(root, ".git");
6848
+ const gitDir = join20(root, ".git");
5517
6849
  if (!existsSync19(gitDir)) {
5518
6850
  return {
5519
6851
  id: "core_files_not_ignored",
@@ -5527,7 +6859,7 @@ function checkCoreFilesNotIgnored(projectRoot) {
5527
6859
  const ignoredFiles = [];
5528
6860
  for (const file of CORE_PROTECTED_FILES) {
5529
6861
  const relPath = `.cleo/${file}`;
5530
- const fullPath = join19(root, relPath);
6862
+ const fullPath = join20(root, relPath);
5531
6863
  if (!existsSync19(fullPath)) continue;
5532
6864
  try {
5533
6865
  execFileSync2("git", ["check-ignore", "-q", relPath], {
@@ -5559,7 +6891,7 @@ function checkCoreFilesNotIgnored(projectRoot) {
5559
6891
  }
5560
6892
  function checkLegacyAgentOutputs(projectRoot) {
5561
6893
  const root = projectRoot ?? process.cwd();
5562
- const cleoDir = join19(root, ".cleo");
6894
+ const cleoDir = join20(root, ".cleo");
5563
6895
  const detection = detectLegacyAgentOutputs(root, cleoDir);
5564
6896
  if (detection.hasLegacy) {
5565
6897
  return {
@@ -5632,10 +6964,10 @@ __export(hooks_exports, {
5632
6964
  });
5633
6965
  import { chmod, mkdir as mkdir5, copyFile as copyFile2, readFile as readFile4 } from "node:fs/promises";
5634
6966
  import { existsSync as existsSync20 } from "node:fs";
5635
- import { join as join20 } from "node:path";
6967
+ import { join as join21 } from "node:path";
5636
6968
  async function ensureGitHooks(projectRoot, opts) {
5637
- const gitDir = join20(projectRoot, ".git");
5638
- const gitHooksDir = join20(gitDir, "hooks");
6969
+ const gitDir = join21(projectRoot, ".git");
6970
+ const gitHooksDir = join21(gitDir, "hooks");
5639
6971
  if (!existsSync20(gitDir)) {
5640
6972
  return {
5641
6973
  action: "skipped",
@@ -5644,7 +6976,7 @@ async function ensureGitHooks(projectRoot, opts) {
5644
6976
  };
5645
6977
  }
5646
6978
  const packageRoot = getPackageRoot();
5647
- const sourceDir = join20(packageRoot, "templates", "git-hooks");
6979
+ const sourceDir = join21(packageRoot, "templates", "git-hooks");
5648
6980
  if (!existsSync20(sourceDir)) {
5649
6981
  return {
5650
6982
  action: "skipped",
@@ -5657,8 +6989,8 @@ async function ensureGitHooks(projectRoot, opts) {
5657
6989
  let installedCount = 0;
5658
6990
  const errors = [];
5659
6991
  for (const hook of MANAGED_HOOKS) {
5660
- const sourcePath = join20(sourceDir, hook);
5661
- const destPath = join20(gitHooksDir, hook);
6992
+ const sourcePath = join21(sourceDir, hook);
6993
+ const destPath = join21(gitHooksDir, hook);
5662
6994
  if (!existsSync20(sourcePath)) {
5663
6995
  continue;
5664
6996
  }
@@ -5694,13 +7026,13 @@ async function ensureGitHooks(projectRoot, opts) {
5694
7026
  };
5695
7027
  }
5696
7028
  async function checkGitHooks(projectRoot) {
5697
- const gitHooksDir = join20(projectRoot, ".git", "hooks");
7029
+ const gitHooksDir = join21(projectRoot, ".git", "hooks");
5698
7030
  const packageRoot = getPackageRoot();
5699
- const sourceDir = join20(packageRoot, "templates", "git-hooks");
7031
+ const sourceDir = join21(packageRoot, "templates", "git-hooks");
5700
7032
  const results = [];
5701
7033
  for (const hook of MANAGED_HOOKS) {
5702
- const sourcePath = join20(sourceDir, hook);
5703
- const installedPath = join20(gitHooksDir, hook);
7034
+ const sourcePath = join21(sourceDir, hook);
7035
+ const installedPath = join21(gitHooksDir, hook);
5704
7036
  const result = {
5705
7037
  hook,
5706
7038
  installed: false,
@@ -5748,18 +7080,18 @@ __export(injection_exports, {
5748
7080
  });
5749
7081
  import { mkdir as mkdir6, writeFile as writeFile4, rm } from "node:fs/promises";
5750
7082
  import { existsSync as existsSync21, readFileSync as readFileSync13 } from "node:fs";
5751
- import { join as join21, basename as basename3 } from "node:path";
7083
+ import { join as join22, basename as basename3 } from "node:path";
5752
7084
  import { homedir as homedir3 } from "node:os";
5753
7085
  function getInjectionTemplateContent() {
5754
7086
  const packageRoot = getPackageRoot();
5755
- const packageTemplatePath = join21(packageRoot, "templates", "CLEO-INJECTION.md");
7087
+ const packageTemplatePath = join22(packageRoot, "templates", "CLEO-INJECTION.md");
5756
7088
  if (existsSync21(packageTemplatePath)) {
5757
7089
  return readFileSync13(packageTemplatePath, "utf-8");
5758
7090
  }
5759
7091
  return null;
5760
7092
  }
5761
7093
  async function removeStaleAgentInjection(projectRoot) {
5762
- const stalePath = join21(projectRoot, ".cleo", "templates", "AGENT-INJECTION.md");
7094
+ const stalePath = join22(projectRoot, ".cleo", "templates", "AGENT-INJECTION.md");
5763
7095
  if (!existsSync21(stalePath)) return false;
5764
7096
  await rm(stalePath, { force: true });
5765
7097
  return true;
@@ -5771,7 +7103,7 @@ async function ensureInjection(projectRoot) {
5771
7103
  } catch {
5772
7104
  return {
5773
7105
  action: "skipped",
5774
- path: join21(projectRoot, "AGENTS.md"),
7106
+ path: join22(projectRoot, "AGENTS.md"),
5775
7107
  details: "@cleocode/caamp not installed, skipping injection"
5776
7108
  };
5777
7109
  }
@@ -5780,16 +7112,16 @@ async function ensureInjection(projectRoot) {
5780
7112
  if (providers.length === 0) {
5781
7113
  return {
5782
7114
  action: "skipped",
5783
- path: join21(projectRoot, "AGENTS.md"),
7115
+ path: join22(projectRoot, "AGENTS.md"),
5784
7116
  details: "No AI agent providers detected, skipping injection"
5785
7117
  };
5786
7118
  }
5787
7119
  const actions = [];
5788
7120
  for (const provider of providers) {
5789
- const instructFile = join21(projectRoot, provider.pathProject, provider.instructFile);
7121
+ const instructFile = join22(projectRoot, provider.pathProject, provider.instructFile);
5790
7122
  await stripCLEOBlocks(instructFile);
5791
7123
  }
5792
- await stripCLEOBlocks(join21(projectRoot, "AGENTS.md"));
7124
+ await stripCLEOBlocks(join22(projectRoot, "AGENTS.md"));
5793
7125
  const removedStale = await removeStaleAgentInjection(projectRoot);
5794
7126
  if (removedStale) {
5795
7127
  actions.push("removed deprecated AGENT-INJECTION.md");
@@ -5800,9 +7132,9 @@ async function ensureInjection(projectRoot) {
5800
7132
  const fileName = basename3(filePath);
5801
7133
  actions.push(`${fileName} (${action})`);
5802
7134
  }
5803
- const agentsMdPath = join21(projectRoot, "AGENTS.md");
7135
+ const agentsMdPath = join22(projectRoot, "AGENTS.md");
5804
7136
  const agentsMdLines = ["@~/.cleo/templates/CLEO-INJECTION.md"];
5805
- const projectContextPath = join21(projectRoot, ".cleo", "project-context.json");
7137
+ const projectContextPath = join22(projectRoot, ".cleo", "project-context.json");
5806
7138
  if (existsSync21(projectContextPath)) {
5807
7139
  agentsMdLines.push("@.cleo/project-context.json");
5808
7140
  }
@@ -5810,17 +7142,17 @@ async function ensureInjection(projectRoot) {
5810
7142
  actions.push(`AGENTS.md CLEO content (${agentsAction})`);
5811
7143
  const content = getInjectionTemplateContent();
5812
7144
  if (content) {
5813
- const globalTemplatesDir = join21(getCleoHome(), "templates");
7145
+ const globalTemplatesDir = join22(getCleoHome(), "templates");
5814
7146
  await mkdir6(globalTemplatesDir, { recursive: true });
5815
- const globalPath = join21(globalTemplatesDir, "CLEO-INJECTION.md");
7147
+ const globalPath = join22(globalTemplatesDir, "CLEO-INJECTION.md");
5816
7148
  if (!existsSync21(globalPath)) {
5817
7149
  await writeFile4(globalPath, content);
5818
7150
  actions.push("installed global CLEO-INJECTION.md");
5819
7151
  }
5820
7152
  }
5821
7153
  try {
5822
- const globalAgentsDir = join21(homedir3(), ".agents");
5823
- const globalAgentsMd = join21(globalAgentsDir, "AGENTS.md");
7154
+ const globalAgentsDir = join22(homedir3(), ".agents");
7155
+ const globalAgentsMd = join22(globalAgentsDir, "AGENTS.md");
5824
7156
  await mkdir6(globalAgentsDir, { recursive: true });
5825
7157
  await inject(globalAgentsMd, "@~/.cleo/templates/CLEO-INJECTION.md");
5826
7158
  } catch {
@@ -5832,7 +7164,7 @@ async function ensureInjection(projectRoot) {
5832
7164
  };
5833
7165
  }
5834
7166
  function checkInjection(projectRoot) {
5835
- const agentsMdPath = join21(projectRoot, "AGENTS.md");
7167
+ const agentsMdPath = join22(projectRoot, "AGENTS.md");
5836
7168
  if (!existsSync21(agentsMdPath)) {
5837
7169
  return {
5838
7170
  id: "injection_health",
@@ -5885,7 +7217,7 @@ function checkInjection(projectRoot) {
5885
7217
  const missing = [];
5886
7218
  for (const ref of refs) {
5887
7219
  const rawPath = ref.slice(1).trim();
5888
- const resolvedPath = rawPath.startsWith("~/") ? join21(homedir3(), rawPath.slice(2)) : join21(projectRoot, rawPath);
7220
+ const resolvedPath = rawPath.startsWith("~/") ? join22(homedir3(), rawPath.slice(2)) : join22(projectRoot, rawPath);
5889
7221
  if (!existsSync21(resolvedPath)) {
5890
7222
  missing.push(rawPath);
5891
7223
  }
@@ -5901,7 +7233,7 @@ function checkInjection(projectRoot) {
5901
7233
  };
5902
7234
  }
5903
7235
  }
5904
- const claudeMdPath = join21(projectRoot, "CLAUDE.md");
7236
+ const claudeMdPath = join22(projectRoot, "CLAUDE.md");
5905
7237
  if (existsSync21(claudeMdPath)) {
5906
7238
  try {
5907
7239
  const claudeContent = readFileSync13(claudeMdPath, "utf-8");
@@ -5956,19 +7288,19 @@ __export(health_exports, {
5956
7288
  runDoctorFixes: () => runDoctorFixes
5957
7289
  });
5958
7290
  import { existsSync as existsSync22, readFileSync as readFileSync14, statSync as statSync8 } from "node:fs";
5959
- import { join as join22 } from "node:path";
7291
+ import { join as join23 } from "node:path";
5960
7292
  import { execFile as execFile4 } from "node:child_process";
5961
7293
  import { promisify as promisify4 } from "node:util";
5962
7294
  import { homedir as homedir4 } from "node:os";
5963
7295
  function getSystemHealth(projectRoot, opts) {
5964
- const cleoDir = join22(projectRoot, ".cleo");
7296
+ const cleoDir = join23(projectRoot, ".cleo");
5965
7297
  const checks = [];
5966
7298
  if (existsSync22(cleoDir)) {
5967
7299
  checks.push({ name: "cleo_dir", status: "pass", message: ".cleo directory exists" });
5968
7300
  } else {
5969
7301
  checks.push({ name: "cleo_dir", status: "fail", message: ".cleo directory not found" });
5970
7302
  }
5971
- const dbPath = join22(cleoDir, "tasks.db");
7303
+ const dbPath = join23(cleoDir, "tasks.db");
5972
7304
  if (existsSync22(dbPath)) {
5973
7305
  try {
5974
7306
  const dbSize = statSync8(dbPath).size;
@@ -5983,7 +7315,7 @@ function getSystemHealth(projectRoot, opts) {
5983
7315
  } else {
5984
7316
  checks.push({ name: "tasks_db", status: "fail", message: "tasks.db not found" });
5985
7317
  }
5986
- const configPath = join22(cleoDir, "config.json");
7318
+ const configPath = join23(cleoDir, "config.json");
5987
7319
  if (existsSync22(configPath)) {
5988
7320
  try {
5989
7321
  JSON.parse(readFileSync14(configPath, "utf-8"));
@@ -5995,7 +7327,7 @@ function getSystemHealth(projectRoot, opts) {
5995
7327
  checks.push({ name: "config_json", status: "warn", message: "config.json not found" });
5996
7328
  }
5997
7329
  if (existsSync22(dbPath)) {
5998
- const staleFiles = STALE_JSON_FILES.filter((f) => existsSync22(join22(cleoDir, f)));
7330
+ const staleFiles = STALE_JSON_FILES.filter((f) => existsSync22(join23(cleoDir, f)));
5999
7331
  if (staleFiles.length > 0) {
6000
7332
  checks.push({
6001
7333
  name: "stale_json",
@@ -6005,13 +7337,13 @@ function getSystemHealth(projectRoot, opts) {
6005
7337
  }
6006
7338
  }
6007
7339
  if (opts?.detailed) {
6008
- const logPath = join22(cleoDir, "todo-log.jsonl");
7340
+ const logPath = join23(cleoDir, "todo-log.jsonl");
6009
7341
  if (existsSync22(logPath)) {
6010
7342
  checks.push({ name: "log_file", status: "pass", message: "todo-log.jsonl exists" });
6011
7343
  } else {
6012
7344
  checks.push({ name: "log_file", status: "warn", message: "todo-log.jsonl not found" });
6013
7345
  }
6014
- const backupDir = join22(cleoDir, ".backups");
7346
+ const backupDir = join23(cleoDir, ".backups");
6015
7347
  if (existsSync22(backupDir)) {
6016
7348
  checks.push({ name: "backups_dir", status: "pass", message: ".backups directory exists" });
6017
7349
  } else {
@@ -6020,7 +7352,7 @@ function getSystemHealth(projectRoot, opts) {
6020
7352
  }
6021
7353
  let version = "unknown";
6022
7354
  try {
6023
- const pkgPath = join22(projectRoot, "package.json");
7355
+ const pkgPath = join23(projectRoot, "package.json");
6024
7356
  if (existsSync22(pkgPath)) {
6025
7357
  const pkg = JSON.parse(readFileSync14(pkgPath, "utf-8"));
6026
7358
  version = pkg.version || "unknown";
@@ -6056,8 +7388,8 @@ async function getSystemDiagnostics(projectRoot, opts) {
6056
7388
  details: preflight.summary
6057
7389
  });
6058
7390
  }
6059
- const cleoDir = join22(projectRoot, ".cleo");
6060
- const dbPath = join22(cleoDir, "tasks.db");
7391
+ const cleoDir = join23(projectRoot, ".cleo");
7392
+ const dbPath = join23(cleoDir, "tasks.db");
6061
7393
  if (existsSync22(dbPath)) {
6062
7394
  try {
6063
7395
  const accessor = await getAccessor(projectRoot);
@@ -6181,14 +7513,14 @@ async function coreDoctorReport(projectRoot) {
6181
7513
  status: gitPath ? "ok" : "warning",
6182
7514
  message: gitPath ? `git found: ${gitPath}` : "git not found (optional, needed for version control features)"
6183
7515
  });
6184
- const cleoDir = join22(projectRoot, ".cleo");
7516
+ const cleoDir = join23(projectRoot, ".cleo");
6185
7517
  const dirExists = existsSync22(cleoDir);
6186
7518
  checks.push({
6187
7519
  check: "project_dir",
6188
7520
  status: dirExists ? "ok" : "error",
6189
7521
  message: dirExists ? `Project dir: ${cleoDir}` : `Project dir not found: ${cleoDir}. Run: cleo init`
6190
7522
  });
6191
- const dbPath = join22(cleoDir, "tasks.db");
7523
+ const dbPath = join23(cleoDir, "tasks.db");
6192
7524
  const dbExists2 = existsSync22(dbPath);
6193
7525
  const dbSize = await fileSize(dbPath);
6194
7526
  checks.push({
@@ -6232,14 +7564,14 @@ async function coreDoctorReport(projectRoot) {
6232
7564
  } catch {
6233
7565
  }
6234
7566
  }
6235
- const configPath = join22(cleoDir, "config.json");
7567
+ const configPath = join23(cleoDir, "config.json");
6236
7568
  const configExists = existsSync22(configPath);
6237
7569
  checks.push({
6238
7570
  check: "config_file",
6239
7571
  status: configExists ? "ok" : "warning",
6240
7572
  message: configExists ? "config.json present" : "config.json not found (using defaults)"
6241
7573
  });
6242
- const staleJsonFiles = STALE_JSON_FILES.filter((f) => existsSync22(join22(cleoDir, f)));
7574
+ const staleJsonFiles = STALE_JSON_FILES.filter((f) => existsSync22(join23(cleoDir, f)));
6243
7575
  if (dbExists2 && staleJsonFiles.length > 0) {
6244
7576
  checks.push({
6245
7577
  check: "stale_json",
@@ -6248,14 +7580,14 @@ async function coreDoctorReport(projectRoot) {
6248
7580
  details: { files: staleJsonFiles }
6249
7581
  });
6250
7582
  }
6251
- const logPath = join22(cleoDir, "todo-log.jsonl");
7583
+ const logPath = join23(cleoDir, "todo-log.jsonl");
6252
7584
  const logExists = existsSync22(logPath);
6253
7585
  checks.push({
6254
7586
  check: "log_file",
6255
7587
  status: logExists ? "ok" : "warning",
6256
7588
  message: logExists ? "log file present" : "log file not found"
6257
7589
  });
6258
- const rootGitignorePath = join22(projectRoot, ".gitignore");
7590
+ const rootGitignorePath = join23(projectRoot, ".gitignore");
6259
7591
  if (existsSync22(rootGitignorePath)) {
6260
7592
  try {
6261
7593
  const gitignoreContent = readFileSync14(rootGitignorePath, "utf-8");
@@ -6277,7 +7609,7 @@ async function coreDoctorReport(projectRoot) {
6277
7609
  checks.push(mapCheckResult(checkVitalFilesTracked(projectRoot)));
6278
7610
  checks.push(mapCheckResult(checkCoreFilesNotIgnored(projectRoot)));
6279
7611
  checks.push(mapCheckResult(checkLegacyAgentOutputs(projectRoot)));
6280
- const cleoGitHeadExists = existsSync22(join22(cleoDir, ".git", "HEAD"));
7612
+ const cleoGitHeadExists = existsSync22(join23(cleoDir, ".git", "HEAD"));
6281
7613
  checks.push({
6282
7614
  check: "cleo_git_repo",
6283
7615
  status: cleoGitHeadExists ? "ok" : "warning",
@@ -6289,7 +7621,7 @@ async function coreDoctorReport(projectRoot) {
6289
7621
  checks.push(mapCheckResult(checkProjectInfo(projectRoot)));
6290
7622
  checks.push(mapCheckResult(checkProjectContext(projectRoot)));
6291
7623
  checks.push(mapCheckResult(checkInjection(projectRoot)));
6292
- const agentDefPath = join22(homedir4(), ".agents", "agents", "cleo-subagent");
7624
+ const agentDefPath = join23(homedir4(), ".agents", "agents", "cleo-subagent");
6293
7625
  checks.push({
6294
7626
  check: "agent_definition",
6295
7627
  status: existsSync22(agentDefPath) ? "ok" : "warning",
@@ -6397,11 +7729,11 @@ __export(mcp_exports, {
6397
7729
  generateMcpServerEntry: () => generateMcpServerEntry
6398
7730
  });
6399
7731
  import { readFileSync as readFileSync20 } from "node:fs";
6400
- import { join as join29 } from "node:path";
7732
+ import { join as join30 } from "node:path";
6401
7733
  import { homedir as homedir6 } from "node:os";
6402
7734
  function detectEnvMode() {
6403
- const versionPath = join29(
6404
- process.env["CLEO_HOME"] ?? join29(homedir6(), ".cleo"),
7735
+ const versionPath = join30(
7736
+ process.env["CLEO_HOME"] ?? join30(homedir6(), ".cleo"),
6405
7737
  "VERSION"
6406
7738
  );
6407
7739
  let content;
@@ -6429,7 +7761,7 @@ function generateMcpServerEntry(env) {
6429
7761
  if (env.mode === "dev-ts" && env.source) {
6430
7762
  return {
6431
7763
  command: "node",
6432
- args: [join29(env.source, "dist", "mcp", "index.js")],
7764
+ args: [join30(env.source, "dist", "mcp", "index.js")],
6433
7765
  env: {}
6434
7766
  };
6435
7767
  }
@@ -6467,21 +7799,21 @@ __export(registry_exports, {
6467
7799
  readRegistry: () => readRegistry,
6468
7800
  readRegistryRequired: () => readRegistryRequired
6469
7801
  });
6470
- import { createHash as createHash5 } from "node:crypto";
6471
- import { join as join30 } from "node:path";
7802
+ import { createHash as createHash6 } from "node:crypto";
7803
+ import { join as join31 } from "node:path";
6472
7804
  import { mkdir as mkdir7, access as access2, readFile as readFile6 } from "node:fs/promises";
6473
7805
  import { z } from "zod";
6474
7806
  function getNexusHome() {
6475
- return process.env["NEXUS_HOME"] ?? join30(getCleoHome(), "nexus");
7807
+ return process.env["NEXUS_HOME"] ?? join31(getCleoHome(), "nexus");
6476
7808
  }
6477
7809
  function getNexusCacheDir() {
6478
- return process.env["NEXUS_CACHE_DIR"] ?? join30(getNexusHome(), "cache");
7810
+ return process.env["NEXUS_CACHE_DIR"] ?? join31(getNexusHome(), "cache");
6479
7811
  }
6480
7812
  function getRegistryPath() {
6481
- return process.env["NEXUS_REGISTRY_FILE"] ?? join30(getCleoHome(), "projects-registry.json");
7813
+ return process.env["NEXUS_REGISTRY_FILE"] ?? join31(getCleoHome(), "projects-registry.json");
6482
7814
  }
6483
7815
  function generateProjectHash2(projectPath) {
6484
- const hash = createHash5("sha256").update(projectPath).digest("hex");
7816
+ const hash = createHash6("sha256").update(projectPath).digest("hex");
6485
7817
  return hash.substring(0, 12);
6486
7818
  }
6487
7819
  async function readRegistry() {
@@ -6520,7 +7852,7 @@ async function nexusInit() {
6520
7852
  }
6521
7853
  async function isCleoProject(projectPath) {
6522
7854
  try {
6523
- await access2(join30(projectPath, ".cleo", "todo.json"));
7855
+ await access2(join31(projectPath, ".cleo", "todo.json"));
6524
7856
  return true;
6525
7857
  } catch {
6526
7858
  return false;
@@ -6530,9 +7862,9 @@ async function readProjectMeta(projectPath) {
6530
7862
  try {
6531
7863
  let raw;
6532
7864
  try {
6533
- raw = await readFile6(join30(projectPath, ".cleo", "tasks.json"), "utf-8");
7865
+ raw = await readFile6(join31(projectPath, ".cleo", "tasks.json"), "utf-8");
6534
7866
  } catch {
6535
- raw = await readFile6(join30(projectPath, ".cleo", "todo.json"), "utf-8");
7867
+ raw = await readFile6(join31(projectPath, ".cleo", "todo.json"), "utf-8");
6536
7868
  }
6537
7869
  const data = JSON.parse(raw);
6538
7870
  const tasks2 = data.tasks ?? [];
@@ -7025,7 +8357,7 @@ __export(session_grade_exports, {
7025
8357
  gradeSession: () => gradeSession,
7026
8358
  readGrades: () => readGrades
7027
8359
  });
7028
- import { join as join48 } from "node:path";
8360
+ import { join as join49 } from "node:path";
7029
8361
  import { existsSync as existsSync47 } from "node:fs";
7030
8362
  import { readFile as readFile9, appendFile, mkdir as mkdir9 } from "node:fs/promises";
7031
8363
  async function gradeSession(sessionId, cwd) {
@@ -7206,9 +8538,9 @@ function detectDuplicateCreates(entries) {
7206
8538
  async function appendGradeResult(result, cwd) {
7207
8539
  try {
7208
8540
  const cleoDir = getCleoDirAbsolute(cwd);
7209
- const metricsDir = join48(cleoDir, "metrics");
8541
+ const metricsDir = join49(cleoDir, "metrics");
7210
8542
  await mkdir9(metricsDir, { recursive: true });
7211
- const gradesPath = join48(metricsDir, "GRADES.jsonl");
8543
+ const gradesPath = join49(metricsDir, "GRADES.jsonl");
7212
8544
  const line = JSON.stringify({ ...result, evaluator: "auto" }) + "\n";
7213
8545
  await appendFile(gradesPath, line, "utf8");
7214
8546
  } catch {
@@ -7217,7 +8549,7 @@ async function appendGradeResult(result, cwd) {
7217
8549
  async function readGrades(sessionId, cwd) {
7218
8550
  try {
7219
8551
  const cleoDir = getCleoDirAbsolute(cwd);
7220
- const gradesPath = join48(cleoDir, "metrics", "GRADES.jsonl");
8552
+ const gradesPath = join49(cleoDir, "metrics", "GRADES.jsonl");
7221
8553
  if (!existsSync47(gradesPath)) return [];
7222
8554
  const content = await readFile9(gradesPath, "utf8");
7223
8555
  const results = content.split("\n").filter((l) => l.trim()).map((l) => JSON.parse(l));
@@ -7341,8 +8673,14 @@ var QUERY_OPERATIONS = {
7341
8673
  // Pattern memory statistics
7342
8674
  "learning.search",
7343
8675
  // Search BRAIN learning memory
7344
- "learning.stats"
8676
+ "learning.stats",
7345
8677
  // Learning memory statistics
8678
+ "brain.search",
8679
+ // 3-layer retrieval step 1: search index
8680
+ "brain.timeline",
8681
+ // 3-layer retrieval step 2: context around anchor
8682
+ "brain.fetch"
8683
+ // 3-layer retrieval step 3: full details for filtered IDs
7346
8684
  ],
7347
8685
  // ── Canonical: check (validate alias) ──────────────────────────────
7348
8686
  check: [
@@ -7681,8 +9019,10 @@ var MUTATE_OPERATIONS = {
7681
9019
  // Archive old entries
7682
9020
  "pattern.store",
7683
9021
  // Store BRAIN pattern memory
7684
- "learning.store"
9022
+ "learning.store",
7685
9023
  // Store BRAIN learning memory
9024
+ "brain.observe"
9025
+ // Save observation to brain.db
7686
9026
  ],
7687
9027
  // ── Canonical: check (validate alias) ──────────────────────────────
7688
9028
  check: [
@@ -13798,6 +15138,12 @@ async function computeBriefing(projectRoot, options = {}) {
13798
15138
  scopeTaskIds
13799
15139
  });
13800
15140
  const pipelineStage = computePipelineStage(current);
15141
+ let memoryContext;
15142
+ try {
15143
+ const { getSessionMemoryContext: getSessionMemoryContext2 } = await Promise.resolve().then(() => (init_session_memory(), session_memory_exports));
15144
+ memoryContext = await getSessionMemoryContext2(projectRoot, scopeFilter);
15145
+ } catch {
15146
+ }
13801
15147
  const warnings = [];
13802
15148
  if (currentTaskInfo?.blockedBy?.length) {
13803
15149
  warnings.push(
@@ -13812,7 +15158,8 @@ async function computeBriefing(projectRoot, options = {}) {
13812
15158
  blockedTasks,
13813
15159
  activeEpics,
13814
15160
  ...pipelineStage && { pipelineStage },
13815
- ...warnings.length > 0 && { warnings }
15161
+ ...warnings.length > 0 && { warnings },
15162
+ ...memoryContext && { memoryContext }
13816
15163
  };
13817
15164
  }
13818
15165
  function parseScope(scopeStr, current) {
@@ -14518,7 +15865,23 @@ async function sessionResume(projectRoot, sessionId) {
14518
15865
  taskData.lastUpdated = now;
14519
15866
  await accessor.saveTaskFile(taskData);
14520
15867
  await accessor.saveSessions(sessions2);
14521
- return { success: true, data: session };
15868
+ let memoryContext;
15869
+ try {
15870
+ const { getSessionMemoryContext: getSessionMemoryContext2 } = await Promise.resolve().then(() => (init_session_memory(), session_memory_exports));
15871
+ const scopeType = session.scope?.type;
15872
+ const rootTaskId = session.scope?.rootTaskId;
15873
+ memoryContext = await getSessionMemoryContext2(projectRoot, {
15874
+ type: scopeType ?? "global",
15875
+ rootTaskId,
15876
+ epicId: rootTaskId
15877
+ });
15878
+ } catch {
15879
+ }
15880
+ const enrichedSession = {
15881
+ ...session,
15882
+ ...memoryContext && { memoryContext }
15883
+ };
15884
+ return { success: true, data: enrichedSession };
14522
15885
  } catch {
14523
15886
  return engineError("E_NOT_INITIALIZED", "Task database not initialized");
14524
15887
  }
@@ -14768,7 +16131,7 @@ async function sessionChainShow(projectRoot, sessionId) {
14768
16131
  init_platform();
14769
16132
  init_data_accessor();
14770
16133
  import { readFileSync as readFileSync19, existsSync as existsSync28, readdirSync as readdirSync7 } from "node:fs";
14771
- import { join as join28, basename as basename5 } from "node:path";
16134
+ import { join as join29, basename as basename5 } from "node:path";
14772
16135
 
14773
16136
  // src/core/stats/index.ts
14774
16137
  init_json();
@@ -14897,11 +16260,11 @@ init_paths();
14897
16260
  init_json();
14898
16261
  init_paths();
14899
16262
  import { readFileSync as readFileSync6, existsSync as existsSync12 } from "node:fs";
14900
- import { join as join12 } from "node:path";
16263
+ import { join as join13 } from "node:path";
14901
16264
  async function generateInjection(projectRoot, accessor) {
14902
16265
  let version = "unknown";
14903
16266
  try {
14904
- const pkgPath = join12(projectRoot, "package.json");
16267
+ const pkgPath = join13(projectRoot, "package.json");
14905
16268
  if (existsSync12(pkgPath)) {
14906
16269
  const pkg = JSON.parse(readFileSync6(pkgPath, "utf-8"));
14907
16270
  version = pkg.version || "unknown";
@@ -15009,23 +16372,23 @@ init_paths();
15009
16372
  // src/core/system/backup.ts
15010
16373
  init_errors();
15011
16374
  init_exit_codes();
15012
- import { readFileSync as readFileSync15, writeFileSync as writeFileSync3, existsSync as existsSync23, mkdirSync as mkdirSync8 } from "node:fs";
15013
- import { join as join23 } from "node:path";
16375
+ import { readFileSync as readFileSync15, writeFileSync as writeFileSync3, existsSync as existsSync23, mkdirSync as mkdirSync9 } from "node:fs";
16376
+ import { join as join24 } from "node:path";
15014
16377
  function createBackup2(projectRoot, opts) {
15015
- const cleoDir = join23(projectRoot, ".cleo");
16378
+ const cleoDir = join24(projectRoot, ".cleo");
15016
16379
  const btype = opts?.type || "snapshot";
15017
16380
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
15018
16381
  const backupId = `${btype}-${timestamp.replace(/[:.]/g, "-")}`;
15019
- const backupDir = join23(cleoDir, "backups", btype);
16382
+ const backupDir = join24(cleoDir, "backups", btype);
15020
16383
  if (!existsSync23(backupDir)) {
15021
- mkdirSync8(backupDir, { recursive: true });
16384
+ mkdirSync9(backupDir, { recursive: true });
15022
16385
  }
15023
16386
  const filesToBackup = ["todo.json", "todo-archive.json", "sessions.json", "config.json", "todo-log.jsonl"];
15024
16387
  const backedUp = [];
15025
16388
  for (const file of filesToBackup) {
15026
- const src = join23(cleoDir, file);
16389
+ const src = join24(cleoDir, file);
15027
16390
  if (existsSync23(src)) {
15028
- const dest = join23(backupDir, `${file}.${backupId}`);
16391
+ const dest = join24(backupDir, `${file}.${backupId}`);
15029
16392
  try {
15030
16393
  const content = readFileSync15(src, "utf-8");
15031
16394
  writeFileSync3(dest, content, "utf-8");
@@ -15034,7 +16397,7 @@ function createBackup2(projectRoot, opts) {
15034
16397
  }
15035
16398
  }
15036
16399
  }
15037
- const metaPath = join23(backupDir, `${backupId}.meta.json`);
16400
+ const metaPath = join24(backupDir, `${backupId}.meta.json`);
15038
16401
  try {
15039
16402
  writeFileSync3(metaPath, JSON.stringify({
15040
16403
  backupId,
@@ -15051,15 +16414,15 @@ function restoreBackup(projectRoot, params) {
15051
16414
  if (!params.backupId) {
15052
16415
  throw new CleoError(2 /* INVALID_INPUT */, "backupId is required");
15053
16416
  }
15054
- const cleoDir = join23(projectRoot, ".cleo");
16417
+ const cleoDir = join24(projectRoot, ".cleo");
15055
16418
  const backupTypes = ["snapshot", "safety", "migration"];
15056
16419
  let metaPath = null;
15057
16420
  let backupDir = null;
15058
16421
  for (const btype of backupTypes) {
15059
- const candidateMeta = join23(cleoDir, "backups", btype, `${params.backupId}.meta.json`);
16422
+ const candidateMeta = join24(cleoDir, "backups", btype, `${params.backupId}.meta.json`);
15060
16423
  if (existsSync23(candidateMeta)) {
15061
16424
  metaPath = candidateMeta;
15062
- backupDir = join23(cleoDir, "backups", btype);
16425
+ backupDir = join24(cleoDir, "backups", btype);
15063
16426
  break;
15064
16427
  }
15065
16428
  }
@@ -15074,11 +16437,11 @@ function restoreBackup(projectRoot, params) {
15074
16437
  }
15075
16438
  const restored = [];
15076
16439
  for (const file of meta.files ?? []) {
15077
- const backupFile = join23(backupDir, `${file}.${params.backupId}`);
16440
+ const backupFile = join24(backupDir, `${file}.${params.backupId}`);
15078
16441
  if (existsSync23(backupFile)) {
15079
16442
  try {
15080
16443
  const content = readFileSync15(backupFile, "utf-8");
15081
- writeFileSync3(join23(cleoDir, file), content, "utf-8");
16444
+ writeFileSync3(join24(cleoDir, file), content, "utf-8");
15082
16445
  restored.push(file);
15083
16446
  } catch {
15084
16447
  }
@@ -15096,9 +16459,9 @@ function restoreBackup(projectRoot, params) {
15096
16459
  init_errors();
15097
16460
  init_exit_codes();
15098
16461
  import { readFileSync as readFileSync16, existsSync as existsSync24 } from "node:fs";
15099
- import { join as join24 } from "node:path";
16462
+ import { join as join25 } from "node:path";
15100
16463
  function getMigrationStatus(projectRoot, opts) {
15101
- const taskPath = join24(projectRoot, ".cleo", "tasks.json");
16464
+ const taskPath = join25(projectRoot, ".cleo", "tasks.json");
15102
16465
  let currentVersion = "unknown";
15103
16466
  if (existsSync24(taskPath)) {
15104
16467
  try {
@@ -15123,17 +16486,17 @@ function getMigrationStatus(projectRoot, opts) {
15123
16486
  init_errors();
15124
16487
  init_exit_codes();
15125
16488
  import { readFileSync as readFileSync17, writeFileSync as writeFileSync4, existsSync as existsSync25, readdirSync as readdirSync6, unlinkSync as unlinkSync4 } from "node:fs";
15126
- import { join as join25 } from "node:path";
16489
+ import { join as join26 } from "node:path";
15127
16490
  function cleanupSystem(projectRoot, params) {
15128
16491
  if (!params.target) {
15129
16492
  throw new CleoError(2 /* INVALID_INPUT */, "target is required (sessions|backups|logs|archive)");
15130
16493
  }
15131
- const cleoDir = join25(projectRoot, ".cleo");
16494
+ const cleoDir = join26(projectRoot, ".cleo");
15132
16495
  const dryRun = params.dryRun ?? false;
15133
16496
  const items = [];
15134
16497
  switch (params.target) {
15135
16498
  case "sessions": {
15136
- const sessPath = join25(cleoDir, "sessions.json");
16499
+ const sessPath = join26(cleoDir, "sessions.json");
15137
16500
  if (existsSync25(sessPath)) {
15138
16501
  try {
15139
16502
  const data = JSON.parse(readFileSync17(sessPath, "utf-8"));
@@ -15160,14 +16523,14 @@ function cleanupSystem(projectRoot, params) {
15160
16523
  break;
15161
16524
  }
15162
16525
  case "backups": {
15163
- const backupBaseDir = join25(cleoDir, "backups");
16526
+ const backupBaseDir = join26(cleoDir, "backups");
15164
16527
  if (existsSync25(backupBaseDir)) {
15165
16528
  for (const typeDir of readdirSync6(backupBaseDir)) {
15166
- const fullDir = join25(backupBaseDir, typeDir);
16529
+ const fullDir = join26(backupBaseDir, typeDir);
15167
16530
  try {
15168
16531
  for (const file of readdirSync6(fullDir)) {
15169
16532
  if (file.endsWith(".meta.json")) {
15170
- const metaFilePath = join25(fullDir, file);
16533
+ const metaFilePath = join26(fullDir, file);
15171
16534
  try {
15172
16535
  const meta = JSON.parse(readFileSync17(metaFilePath, "utf-8"));
15173
16536
  if (params.olderThan && meta.timestamp < params.olderThan) {
@@ -15177,7 +16540,7 @@ function cleanupSystem(projectRoot, params) {
15177
16540
  for (const bf of readdirSync6(fullDir)) {
15178
16541
  if (bf.includes(meta.backupId)) {
15179
16542
  try {
15180
- unlinkSync4(join25(fullDir, bf));
16543
+ unlinkSync4(join26(fullDir, bf));
15181
16544
  } catch {
15182
16545
  }
15183
16546
  }
@@ -15202,7 +16565,7 @@ function cleanupSystem(projectRoot, params) {
15202
16565
  items.push(file);
15203
16566
  if (!dryRun) {
15204
16567
  try {
15205
- unlinkSync4(join25(cleoDir, file));
16568
+ unlinkSync4(join26(cleoDir, file));
15206
16569
  } catch {
15207
16570
  }
15208
16571
  }
@@ -15221,13 +16584,13 @@ function cleanupSystem(projectRoot, params) {
15221
16584
  init_errors();
15222
16585
  init_exit_codes();
15223
16586
  import { readFileSync as readFileSync18, writeFileSync as writeFileSync5, existsSync as existsSync26 } from "node:fs";
15224
- import { join as join26 } from "node:path";
16587
+ import { join as join27 } from "node:path";
15225
16588
  function safestop(projectRoot, opts) {
15226
16589
  const dryRun = opts?.dryRun ?? false;
15227
16590
  const reason = opts?.reason ?? "Manual safestop";
15228
16591
  let sessionEnded = false;
15229
16592
  if (!dryRun && !opts?.noSessionEnd) {
15230
- const sessPath = join26(projectRoot, ".cleo", "sessions.json");
16593
+ const sessPath = join27(projectRoot, ".cleo", "sessions.json");
15231
16594
  if (existsSync26(sessPath)) {
15232
16595
  try {
15233
16596
  const data = JSON.parse(readFileSync18(sessPath, "utf-8"));
@@ -15258,7 +16621,7 @@ init_sequence();
15258
16621
  // src/core/system/runtime.ts
15259
16622
  import { existsSync as existsSync27 } from "node:fs";
15260
16623
  import { readFile as readFile5 } from "node:fs/promises";
15261
- import { basename as basename4, join as join27 } from "node:path";
16624
+ import { basename as basename4, join as join28 } from "node:path";
15262
16625
  import { homedir as homedir5 } from "node:os";
15263
16626
  import { execFile as execFile5 } from "node:child_process";
15264
16627
  import { promisify as promisify5 } from "node:util";
@@ -15292,7 +16655,7 @@ function getExpectedNaming(channel) {
15292
16655
  }
15293
16656
  }
15294
16657
  async function parseVersionFile(dataRoot) {
15295
- const versionPath = join27(dataRoot, "VERSION");
16658
+ const versionPath = join28(dataRoot, "VERSION");
15296
16659
  if (!existsSync27(versionPath)) return null;
15297
16660
  let content;
15298
16661
  try {
@@ -15322,9 +16685,9 @@ async function parseVersionFile(dataRoot) {
15322
16685
  async function getPackageInfo(sourceDir) {
15323
16686
  const candidates = [];
15324
16687
  if (sourceDir && sourceDir !== "unknown" && sourceDir !== "npm") {
15325
- candidates.push(join27(sourceDir, "package.json"));
16688
+ candidates.push(join28(sourceDir, "package.json"));
15326
16689
  }
15327
- candidates.push(join27(process.cwd(), "package.json"));
16690
+ candidates.push(join28(process.cwd(), "package.json"));
15328
16691
  for (const candidate of candidates) {
15329
16692
  try {
15330
16693
  const raw = await readFile5(candidate, "utf-8");
@@ -15350,7 +16713,7 @@ async function getRuntimeDiagnostics(options) {
15350
16713
  const scriptPath = process.argv[1] ?? "";
15351
16714
  const invocationName = basename4(scriptPath || process.argv0 || "cleo");
15352
16715
  const envChannel = normalizeChannel(process.env["CLEO_CHANNEL"]);
15353
- const dataRoot = process.env["CLEO_HOME"] ?? join27(homedir5(), ".cleo");
16716
+ const dataRoot = process.env["CLEO_HOME"] ?? join28(homedir5(), ".cleo");
15354
16717
  const versionInfo = await parseVersionFile(dataRoot);
15355
16718
  const packageInfo = await getPackageInfo(versionInfo?.source);
15356
16719
  const channel = envChannel ?? detectFromInvocation(invocationName) ?? normalizeChannel(versionInfo?.version.includes("-beta") ? "beta" : void 0) ?? detectFromDataRoot(dataRoot) ?? normalizeChannel(versionInfo?.mode.startsWith("dev") ? "dev" : void 0) ?? "stable";
@@ -15565,9 +16928,9 @@ async function systemLog(projectRoot, filters) {
15565
16928
  }
15566
16929
  async function queryAuditLogSqlite(projectRoot, filters) {
15567
16930
  try {
15568
- const { join: join52 } = await import("node:path");
16931
+ const { join: join53 } = await import("node:path");
15569
16932
  const { existsSync: existsSync51 } = await import("node:fs");
15570
- const dbPath = join52(projectRoot, ".cleo", "tasks.db");
16933
+ const dbPath = join53(projectRoot, ".cleo", "tasks.db");
15571
16934
  if (!existsSync51(dbPath)) return null;
15572
16935
  const { getDb: getDb2 } = await Promise.resolve().then(() => (init_sqlite(), sqlite_exports));
15573
16936
  const { auditLog: auditLog2 } = await Promise.resolve().then(() => (init_schema(), schema_exports));
@@ -15663,32 +17026,32 @@ function queryAuditLogJsonl(projectRoot, filters) {
15663
17026
  }
15664
17027
  function systemContext(projectRoot, params) {
15665
17028
  try {
15666
- const cleoDir = join28(projectRoot, ".cleo");
17029
+ const cleoDir = join29(projectRoot, ".cleo");
15667
17030
  let stateFile;
15668
17031
  if (params?.session) {
15669
- const sessionFile = join28(cleoDir, "context-states", `context-state-${params.session}.json`);
15670
- stateFile = existsSync28(sessionFile) ? sessionFile : join28(cleoDir, ".context-state.json");
17032
+ const sessionFile = join29(cleoDir, "context-states", `context-state-${params.session}.json`);
17033
+ stateFile = existsSync28(sessionFile) ? sessionFile : join29(cleoDir, ".context-state.json");
15671
17034
  } else {
15672
- const currentSessionPath = join28(cleoDir, ".current-session");
17035
+ const currentSessionPath = join29(cleoDir, ".current-session");
15673
17036
  if (existsSync28(currentSessionPath)) {
15674
17037
  const currentSession = readFileSync19(currentSessionPath, "utf-8").trim();
15675
17038
  if (currentSession) {
15676
- const sessionFile = join28(cleoDir, "context-states", `context-state-${currentSession}.json`);
15677
- stateFile = existsSync28(sessionFile) ? sessionFile : join28(cleoDir, ".context-state.json");
17039
+ const sessionFile = join29(cleoDir, "context-states", `context-state-${currentSession}.json`);
17040
+ stateFile = existsSync28(sessionFile) ? sessionFile : join29(cleoDir, ".context-state.json");
15678
17041
  } else {
15679
- stateFile = join28(cleoDir, ".context-state.json");
17042
+ stateFile = join29(cleoDir, ".context-state.json");
15680
17043
  }
15681
17044
  } else {
15682
- stateFile = join28(cleoDir, ".context-state.json");
17045
+ stateFile = join29(cleoDir, ".context-state.json");
15683
17046
  }
15684
17047
  }
15685
17048
  const sessions2 = [];
15686
- const statesDir = join28(cleoDir, "context-states");
17049
+ const statesDir = join29(cleoDir, "context-states");
15687
17050
  if (existsSync28(statesDir)) {
15688
17051
  for (const file of readdirSync7(statesDir)) {
15689
17052
  if (file.startsWith("context-state-") && file.endsWith(".json")) {
15690
17053
  try {
15691
- const state = JSON.parse(readFileSync19(join28(statesDir, file), "utf-8"));
17054
+ const state = JSON.parse(readFileSync19(join29(statesDir, file), "utf-8"));
15692
17055
  sessions2.push({
15693
17056
  file: basename5(file),
15694
17057
  sessionId: state.sessionId ?? null,
@@ -15701,7 +17064,7 @@ function systemContext(projectRoot, params) {
15701
17064
  }
15702
17065
  }
15703
17066
  }
15704
- const singletonFile = join28(cleoDir, ".context-state.json");
17067
+ const singletonFile = join29(cleoDir, ".context-state.json");
15705
17068
  if (existsSync28(singletonFile)) {
15706
17069
  try {
15707
17070
  const state = JSON.parse(readFileSync19(singletonFile, "utf-8"));
@@ -15949,18 +17312,18 @@ init_schema_management();
15949
17312
  init_injection();
15950
17313
  import { mkdir as mkdir8, copyFile as copyFile3, symlink, lstat, unlink as unlink3 } from "node:fs/promises";
15951
17314
  import { existsSync as existsSync29, readFileSync as readFileSync21, readdirSync as readdirSync8 } from "node:fs";
15952
- import { join as join31, dirname as dirname7, basename as basename6 } from "node:path";
17315
+ import { join as join32, dirname as dirname8, basename as basename6 } from "node:path";
15953
17316
  import { readFile as readFile7 } from "node:fs/promises";
15954
17317
  import { homedir as homedir7 } from "node:os";
15955
17318
  async function initAgentDefinition(created, warnings) {
15956
17319
  const packageRoot = getPackageRoot();
15957
- const agentSourceDir = join31(packageRoot, "agents", "cleo-subagent");
17320
+ const agentSourceDir = join32(packageRoot, "agents", "cleo-subagent");
15958
17321
  if (!existsSync29(agentSourceDir)) {
15959
17322
  warnings.push("agents/cleo-subagent/ not found in package, skipping agent definition install");
15960
17323
  return;
15961
17324
  }
15962
- const globalAgentsDir = join31(homedir7(), ".agents", "agents", "cleo-subagent");
15963
- await mkdir8(dirname7(globalAgentsDir), { recursive: true });
17325
+ const globalAgentsDir = join32(homedir7(), ".agents", "agents", "cleo-subagent");
17326
+ await mkdir8(dirname8(globalAgentsDir), { recursive: true });
15964
17327
  try {
15965
17328
  try {
15966
17329
  const stat2 = await lstat(globalAgentsDir);
@@ -15976,7 +17339,7 @@ async function initAgentDefinition(created, warnings) {
15976
17339
  await mkdir8(globalAgentsDir, { recursive: true });
15977
17340
  const files = readdirSync8(agentSourceDir);
15978
17341
  for (const file of files) {
15979
- await copyFile3(join31(agentSourceDir, file), join31(globalAgentsDir, file));
17342
+ await copyFile3(join32(agentSourceDir, file), join32(globalAgentsDir, file));
15980
17343
  }
15981
17344
  created.push("agent: cleo-subagent (copied)");
15982
17345
  } catch (copyErr) {
@@ -16028,12 +17391,12 @@ async function initCoreSkills(created, warnings) {
16028
17391
  const packageRoot = getPackageRoot();
16029
17392
  let ctSkillsRoot = null;
16030
17393
  try {
16031
- const bundledPath = join31(packageRoot, "packages", "ct-skills");
16032
- if (existsSync29(join31(bundledPath, "skills.json"))) {
17394
+ const bundledPath = join32(packageRoot, "packages", "ct-skills");
17395
+ if (existsSync29(join32(bundledPath, "skills.json"))) {
16033
17396
  ctSkillsRoot = bundledPath;
16034
17397
  } else {
16035
- const ctSkillsPath = join31(packageRoot, "node_modules", "@cleocode", "ct-skills");
16036
- if (existsSync29(join31(ctSkillsPath, "skills.json"))) {
17398
+ const ctSkillsPath = join32(packageRoot, "node_modules", "@cleocode", "ct-skills");
17399
+ if (existsSync29(join32(ctSkillsPath, "skills.json"))) {
16037
17400
  ctSkillsRoot = ctSkillsPath;
16038
17401
  }
16039
17402
  }
@@ -16048,13 +17411,13 @@ async function initCoreSkills(created, warnings) {
16048
17411
  } catch {
16049
17412
  warnings.push("Failed to register skill library with CAAMP");
16050
17413
  }
16051
- const catalogPath = join31(ctSkillsRoot, "skills.json");
17414
+ const catalogPath = join32(ctSkillsRoot, "skills.json");
16052
17415
  const catalog2 = JSON.parse(readFileSync21(catalogPath, "utf-8"));
16053
17416
  const skills = catalog2.skills ?? [];
16054
17417
  const coreSkills = skills.filter((s) => s.tier <= 2);
16055
17418
  const installed = [];
16056
17419
  for (const skill of coreSkills) {
16057
- const skillSourceDir = dirname7(join31(ctSkillsRoot, skill.path));
17420
+ const skillSourceDir = dirname8(join32(ctSkillsRoot, skill.path));
16058
17421
  if (!existsSync29(skillSourceDir)) {
16059
17422
  continue;
16060
17423
  }
@@ -16131,7 +17494,7 @@ async function initProject(opts = {}) {
16131
17494
  }
16132
17495
  try {
16133
17496
  const { getDb: getDb2 } = await Promise.resolve().then(() => (init_sqlite(), sqlite_exports));
16134
- await getDb2(join31(cleoDir, ".."));
17497
+ await getDb2(join32(cleoDir, ".."));
16135
17498
  created.push("tasks.db");
16136
17499
  } catch (err) {
16137
17500
  created.push(`tasks.db (deferred: ${err instanceof Error ? err.message : String(err)})`);
@@ -16144,7 +17507,7 @@ async function initProject(opts = {}) {
16144
17507
  created.push(".gitignore");
16145
17508
  }
16146
17509
  } else {
16147
- const gitignorePath = join31(cleoDir, ".gitignore");
17510
+ const gitignorePath = join32(cleoDir, ".gitignore");
16148
17511
  if (existsSync29(gitignorePath)) {
16149
17512
  skipped.push(".gitignore");
16150
17513
  } else {
@@ -16156,12 +17519,12 @@ async function initProject(opts = {}) {
16156
17519
  }
16157
17520
  }
16158
17521
  }
16159
- const legacySequencePath = join31(cleoDir, ".sequence");
17522
+ const legacySequencePath = join32(cleoDir, ".sequence");
16160
17523
  try {
16161
17524
  await unlink3(legacySequencePath);
16162
17525
  } catch {
16163
17526
  }
16164
- const legacySequenceJsonPath = join31(cleoDir, ".sequence.json");
17527
+ const legacySequenceJsonPath = join32(cleoDir, ".sequence.json");
16165
17528
  try {
16166
17529
  await unlink3(legacySequenceJsonPath);
16167
17530
  } catch {
@@ -16256,8 +17619,8 @@ async function initProject(opts = {}) {
16256
17619
  async function getVersion(projectRoot) {
16257
17620
  const root = projectRoot ?? getProjectRoot();
16258
17621
  const versionPaths = [
16259
- join31(root, "VERSION"),
16260
- join31(root, "..", "VERSION")
17622
+ join32(root, "VERSION"),
17623
+ join32(root, "..", "VERSION")
16261
17624
  ];
16262
17625
  for (const versionPath of versionPaths) {
16263
17626
  try {
@@ -16269,7 +17632,7 @@ async function getVersion(projectRoot) {
16269
17632
  } catch {
16270
17633
  }
16271
17634
  }
16272
- const pkg = await readJson(join31(root, "package.json"));
17635
+ const pkg = await readJson(join32(root, "package.json"));
16273
17636
  if (pkg?.version) {
16274
17637
  return { version: pkg.version };
16275
17638
  }
@@ -16316,17 +17679,17 @@ init_paths();
16316
17679
  init_schema();
16317
17680
  init_sqlite();
16318
17681
  init_schema();
16319
- import { eq as eq10 } from "drizzle-orm";
17682
+ import { eq as eq11 } from "drizzle-orm";
16320
17683
 
16321
17684
  // src/core/lifecycle/stage-artifacts.ts
16322
17685
  import { existsSync as existsSync31 } from "node:fs";
16323
17686
  import { readFile as readFile8, writeFile as writeFile5 } from "node:fs/promises";
16324
- import { dirname as dirname8, join as join33, relative } from "node:path";
17687
+ import { dirname as dirname9, join as join34, relative } from "node:path";
16325
17688
 
16326
17689
  // src/core/lifecycle/rcasd-paths.ts
16327
17690
  init_paths();
16328
- import { join as join32 } from "node:path";
16329
- import { existsSync as existsSync30, mkdirSync as mkdirSync9, readdirSync as readdirSync9 } from "node:fs";
17691
+ import { join as join33 } from "node:path";
17692
+ import { existsSync as existsSync30, mkdirSync as mkdirSync10, readdirSync as readdirSync9 } from "node:fs";
16330
17693
  var STAGE_SUBDIRS = {
16331
17694
  research: "research",
16332
17695
  consensus: "consensus",
@@ -16343,16 +17706,16 @@ function normalizeEpicId(dirName) {
16343
17706
  }
16344
17707
  function getEpicDir(epicId, cwd) {
16345
17708
  const normalized = normalizeEpicId(epicId);
16346
- return join32(getCleoDirAbsolute(cwd), DEFAULT_DIR, normalized);
17709
+ return join33(getCleoDirAbsolute(cwd), DEFAULT_DIR, normalized);
16347
17710
  }
16348
17711
  function getStagePath(epicId, stage, cwd) {
16349
17712
  const subdir = STAGE_SUBDIRS[stage] ?? stage;
16350
- return join32(getEpicDir(epicId, cwd), subdir);
17713
+ return join33(getEpicDir(epicId, cwd), subdir);
16351
17714
  }
16352
17715
  function ensureStagePath(epicId, stage, cwd) {
16353
17716
  const path = getStagePath(epicId, stage, cwd);
16354
17717
  if (!existsSync30(path)) {
16355
- mkdirSync9(path, { recursive: true });
17718
+ mkdirSync10(path, { recursive: true });
16356
17719
  }
16357
17720
  return path;
16358
17721
  }
@@ -16728,10 +18091,10 @@ function toWorkspaceRelative(path, cwd) {
16728
18091
  function buildRelatedLinks(epicId, stage, absolutePath, cwd) {
16729
18092
  const prereqs = STAGE_PREREQUISITES[stage] ?? [];
16730
18093
  const related = [{ type: "task", id: epicId }];
16731
- const artifactDir = dirname8(absolutePath);
18094
+ const artifactDir = dirname9(absolutePath);
16732
18095
  for (const prereq of prereqs) {
16733
18096
  const prereqDir = getStagePath(epicId, prereq, cwd);
16734
- const prereqFile = join33(prereqDir, `${epicId}-${stageSlug(prereq)}.md`);
18097
+ const prereqFile = join34(prereqDir, `${epicId}-${stageSlug(prereq)}.md`);
16735
18098
  if (!existsSync31(prereqFile)) {
16736
18099
  continue;
16737
18100
  }
@@ -16745,7 +18108,7 @@ function buildRelatedLinks(epicId, stage, absolutePath, cwd) {
16745
18108
  async function ensureStageArtifact(epicId, stage, cwd) {
16746
18109
  const stageDir = ensureStagePath(epicId, stage, cwd);
16747
18110
  const fileName = `${epicId}-${stageSlug(stage)}.md`;
16748
- const absolutePath = join33(stageDir, fileName);
18111
+ const absolutePath = join34(stageDir, fileName);
16749
18112
  const outputFile = toWorkspaceRelative(absolutePath, cwd);
16750
18113
  const currentContent = existsSync31(absolutePath) ? await readFile8(absolutePath, "utf-8") : buildDefaultBody(epicId, stage);
16751
18114
  const related = buildRelatedLinks(epicId, stage, absolutePath, cwd);
@@ -16766,7 +18129,7 @@ async function ensureStageArtifact(epicId, stage, cwd) {
16766
18129
  init_sqlite();
16767
18130
  init_schema();
16768
18131
  init_paths();
16769
- import { eq as eq7, like } from "drizzle-orm";
18132
+ import { eq as eq8, like } from "drizzle-orm";
16770
18133
  import { relative as relative2, basename as basename7 } from "node:path";
16771
18134
  async function recordEvidence(epicId, stage, uri, type, options) {
16772
18135
  const now = (/* @__PURE__ */ new Date()).toISOString();
@@ -16811,12 +18174,12 @@ async function linkProvenance(epicId, stage, filePath, cwd) {
16811
18174
  init_sqlite();
16812
18175
  init_schema();
16813
18176
  import { readFileSync as readFileSync23, readdirSync as readdirSync10, writeFileSync as writeFileSync6, existsSync as existsSync32 } from "node:fs";
16814
- import { join as join35 } from "node:path";
16815
- import { eq as eq8 } from "drizzle-orm";
18177
+ import { join as join36 } from "node:path";
18178
+ import { eq as eq9 } from "drizzle-orm";
16816
18179
 
16817
18180
  // src/core/adrs/parse.ts
16818
18181
  import { readFileSync as readFileSync22 } from "node:fs";
16819
- import { join as join34 } from "node:path";
18182
+ import { join as join35 } from "node:path";
16820
18183
  function extractAdrId(filename) {
16821
18184
  const match = filename.match(/^(ADR-\d+)/);
16822
18185
  return match ? match[1] : filename.replace(".md", "");
@@ -16838,7 +18201,7 @@ function extractTitle(content) {
16838
18201
  return match ? match[1].trim() : "Untitled";
16839
18202
  }
16840
18203
  function parseAdrFile(filePath, projectRoot) {
16841
- const absolutePath = filePath.startsWith("/") ? filePath : join34(projectRoot, filePath);
18204
+ const absolutePath = filePath.startsWith("/") ? filePath : join35(projectRoot, filePath);
16842
18205
  const content = readFileSync22(absolutePath, "utf-8");
16843
18206
  const filename = filePath.split("/").pop();
16844
18207
  return {
@@ -16861,7 +18224,7 @@ function collectAdrFiles(dir) {
16861
18224
  const results = [];
16862
18225
  for (const entry of readdirSync10(dir, { withFileTypes: true })) {
16863
18226
  if (entry.isDirectory()) {
16864
- const sub = join35(dir, entry.name);
18227
+ const sub = join36(dir, entry.name);
16865
18228
  for (const f of readdirSync10(sub)) {
16866
18229
  if (f.endsWith(".md") && /^ADR-\d+/.test(f)) {
16867
18230
  results.push({ file: f, relPath: `${entry.name}/${f}` });
@@ -16874,7 +18237,7 @@ function collectAdrFiles(dir) {
16874
18237
  return results.sort((a, b) => a.file.localeCompare(b.file));
16875
18238
  }
16876
18239
  async function syncAdrsToDb(projectRoot) {
16877
- const adrsDir = join35(projectRoot, ".cleo", "adrs");
18240
+ const adrsDir = join36(projectRoot, ".cleo", "adrs");
16878
18241
  const result = { inserted: 0, updated: 0, skipped: 0, errors: [] };
16879
18242
  if (!existsSync32(adrsDir)) {
16880
18243
  return result;
@@ -16886,7 +18249,7 @@ async function syncAdrsToDb(projectRoot) {
16886
18249
  const manifestEntries2 = [];
16887
18250
  for (const { file, relPath } of activeFiles) {
16888
18251
  try {
16889
- const filePath = join35(adrsDir, relPath);
18252
+ const filePath = join36(adrsDir, relPath);
16890
18253
  const record = parseAdrFile(filePath, projectRoot);
16891
18254
  const fm = record.frontmatter;
16892
18255
  const dbRelPath = `.cleo/adrs/${relPath}`;
@@ -16912,15 +18275,15 @@ async function syncAdrsToDb(projectRoot) {
16912
18275
  topics: fm.Topics ?? null,
16913
18276
  updatedAt: now
16914
18277
  };
16915
- const existing = await db.select({ id: architectureDecisions.id }).from(architectureDecisions).where(eq8(architectureDecisions.id, record.id)).all();
18278
+ const existing = await db.select({ id: architectureDecisions.id }).from(architectureDecisions).where(eq9(architectureDecisions.id, record.id)).all();
16916
18279
  if (existing.length > 0) {
16917
- await db.update(architectureDecisions).set(rowBase).where(eq8(architectureDecisions.id, record.id));
18280
+ await db.update(architectureDecisions).set(rowBase).where(eq9(architectureDecisions.id, record.id));
16918
18281
  result.updated++;
16919
18282
  } else {
16920
18283
  await db.insert(architectureDecisions).values({ ...rowBase, createdAt: now });
16921
18284
  result.inserted++;
16922
18285
  }
16923
- await db.delete(adrTaskLinks).where(eq8(adrTaskLinks.adrId, record.id));
18286
+ await db.delete(adrTaskLinks).where(eq9(adrTaskLinks.adrId, record.id));
16924
18287
  if (fm["Related Tasks"]) {
16925
18288
  for (const taskId of parseTaskIds(fm["Related Tasks"])) {
16926
18289
  await db.insert(adrTaskLinks).values({ adrId: record.id, taskId, linkType: "related" });
@@ -16932,7 +18295,7 @@ async function syncAdrsToDb(projectRoot) {
16932
18295
  }
16933
18296
  for (const { relPath } of allFiles) {
16934
18297
  try {
16935
- const filePath = join35(adrsDir, relPath);
18298
+ const filePath = join36(adrsDir, relPath);
16936
18299
  const record = parseAdrFile(filePath, projectRoot);
16937
18300
  const fm = record.frontmatter;
16938
18301
  const entry = {
@@ -16960,7 +18323,7 @@ async function syncAdrsToDb(projectRoot) {
16960
18323
  }
16961
18324
  }
16962
18325
  writeFileSync6(
16963
- join35(adrsDir, "MANIFEST.jsonl"),
18326
+ join36(adrsDir, "MANIFEST.jsonl"),
16964
18327
  manifestEntries2.map((e) => JSON.stringify(e)).join("\n") + "\n",
16965
18328
  "utf-8"
16966
18329
  );
@@ -16971,8 +18334,8 @@ async function syncAdrsToDb(projectRoot) {
16971
18334
  init_sqlite();
16972
18335
  init_schema();
16973
18336
  import { readdirSync as readdirSync11, readFileSync as readFileSync24, existsSync as existsSync33 } from "node:fs";
16974
- import { join as join36 } from "node:path";
16975
- import { eq as eq9, and as and2 } from "drizzle-orm";
18337
+ import { join as join37 } from "node:path";
18338
+ import { eq as eq10, and as and3 } from "drizzle-orm";
16976
18339
  function parseTaskIds2(raw) {
16977
18340
  if (!raw) return [];
16978
18341
  return raw.split(",").map((t) => t.trim()).filter((t) => /^T\d{1,5}$/.test(t));
@@ -16981,7 +18344,7 @@ function findAdrsForTask(adrsDir, taskId) {
16981
18344
  if (!existsSync33(adrsDir)) return [];
16982
18345
  return readdirSync11(adrsDir).filter((f) => f.endsWith(".md") && /^ADR-\d+/.test(f)).filter((file) => {
16983
18346
  try {
16984
- const content = readFileSync24(join36(adrsDir, file), "utf-8");
18347
+ const content = readFileSync24(join37(adrsDir, file), "utf-8");
16985
18348
  const relatedTasksMatch = content.match(/^\*\*Related Tasks\*\*:\s*(.+)$/m);
16986
18349
  if (!relatedTasksMatch) return false;
16987
18350
  const taskIds = parseTaskIds2(relatedTasksMatch[1]);
@@ -16989,7 +18352,7 @@ function findAdrsForTask(adrsDir, taskId) {
16989
18352
  } catch {
16990
18353
  return false;
16991
18354
  }
16992
- }).map((f) => join36(adrsDir, f));
18355
+ }).map((f) => join37(adrsDir, f));
16993
18356
  }
16994
18357
  async function linkPipelineAdr(projectRoot, taskId) {
16995
18358
  const result = {
@@ -16998,7 +18361,7 @@ async function linkPipelineAdr(projectRoot, taskId) {
16998
18361
  skipped: 0,
16999
18362
  errors: []
17000
18363
  };
17001
- const adrsDir = join36(projectRoot, ".cleo", "adrs");
18364
+ const adrsDir = join37(projectRoot, ".cleo", "adrs");
17002
18365
  const matchingFiles = findAdrsForTask(adrsDir, taskId);
17003
18366
  if (matchingFiles.length === 0) {
17004
18367
  return result;
@@ -17012,7 +18375,7 @@ async function linkPipelineAdr(projectRoot, taskId) {
17012
18375
  const fm = record.frontmatter;
17013
18376
  const content = readFileSync24(filePath, "utf-8");
17014
18377
  const relativePath = `.cleo/adrs/${filename}`;
17015
- const existing = await db.select({ id: architectureDecisions.id }).from(architectureDecisions).where(eq9(architectureDecisions.id, record.id)).all();
18378
+ const existing = await db.select({ id: architectureDecisions.id }).from(architectureDecisions).where(eq10(architectureDecisions.id, record.id)).all();
17016
18379
  const rowBase = {
17017
18380
  id: record.id,
17018
18381
  title: record.title,
@@ -17032,15 +18395,15 @@ async function linkPipelineAdr(projectRoot, taskId) {
17032
18395
  updatedAt: now
17033
18396
  };
17034
18397
  if (existing.length > 0) {
17035
- await db.update(architectureDecisions).set(rowBase).where(eq9(architectureDecisions.id, record.id));
18398
+ await db.update(architectureDecisions).set(rowBase).where(eq10(architectureDecisions.id, record.id));
17036
18399
  } else {
17037
18400
  await db.insert(architectureDecisions).values({ ...rowBase, createdAt: now });
17038
18401
  }
17039
18402
  result.synced++;
17040
18403
  await db.delete(adrTaskLinks).where(
17041
- and2(
17042
- eq9(adrTaskLinks.adrId, record.id),
17043
- eq9(adrTaskLinks.taskId, taskId)
18404
+ and3(
18405
+ eq10(adrTaskLinks.adrId, record.id),
18406
+ eq10(adrTaskLinks.taskId, taskId)
17044
18407
  )
17045
18408
  );
17046
18409
  await db.insert(adrTaskLinks).values({ adrId: record.id, taskId, linkType: "implements" });
@@ -17049,7 +18412,7 @@ async function linkPipelineAdr(projectRoot, taskId) {
17049
18412
  const relatedIds = fm["Related ADRs"].split(",").map((r) => r.trim()).filter((r) => /^ADR-\d+$/.test(r));
17050
18413
  for (const toId of relatedIds) {
17051
18414
  try {
17052
- const targetExists = await db.select({ id: architectureDecisions.id }).from(architectureDecisions).where(eq9(architectureDecisions.id, toId)).all();
18415
+ const targetExists = await db.select({ id: architectureDecisions.id }).from(architectureDecisions).where(eq10(architectureDecisions.id, toId)).all();
17053
18416
  if (targetExists.length > 0) {
17054
18417
  await db.insert(adrRelations).values({ fromAdrId: record.id, toAdrId: toId, relationType: "related" }).onConflictDoNothing();
17055
18418
  }
@@ -17071,7 +18434,7 @@ async function getLifecycleStatus(epicId, cwd) {
17071
18434
  const pipelineResult = await db.select({
17072
18435
  pipeline: lifecyclePipelines,
17073
18436
  task: tasks
17074
- }).from(lifecyclePipelines).innerJoin(tasks, eq10(lifecyclePipelines.taskId, tasks.id)).where(eq10(lifecyclePipelines.taskId, epicId)).limit(1);
18437
+ }).from(lifecyclePipelines).innerJoin(tasks, eq11(lifecyclePipelines.taskId, tasks.id)).where(eq11(lifecyclePipelines.taskId, epicId)).limit(1);
17075
18438
  if (pipelineResult.length === 0) {
17076
18439
  return {
17077
18440
  epicId,
@@ -17084,7 +18447,7 @@ async function getLifecycleStatus(epicId, cwd) {
17084
18447
  }
17085
18448
  const task = pipelineResult[0].task;
17086
18449
  const pipelineId = `pipeline-${epicId}`;
17087
- const stageRows = await db.select().from(lifecycleStages).where(eq10(lifecycleStages.pipelineId, pipelineId)).orderBy(lifecycleStages.sequence);
18450
+ const stageRows = await db.select().from(lifecycleStages).where(eq11(lifecycleStages.pipelineId, pipelineId)).orderBy(lifecycleStages.sequence);
17088
18451
  const stageDataMap = /* @__PURE__ */ new Map();
17089
18452
  for (const row of stageRows) {
17090
18453
  let parsedChain;
@@ -17154,7 +18517,7 @@ async function getLifecycleStatus(epicId, cwd) {
17154
18517
  async function getLifecycleHistory(epicId, cwd) {
17155
18518
  const db = await getDb(cwd);
17156
18519
  const pipelineId = `pipeline-${epicId}`;
17157
- const stages = await db.select().from(lifecycleStages).where(eq10(lifecycleStages.pipelineId, pipelineId));
18520
+ const stages = await db.select().from(lifecycleStages).where(eq11(lifecycleStages.pipelineId, pipelineId));
17158
18521
  if (stages.length === 0) {
17159
18522
  return { epicId, history: [] };
17160
18523
  }
@@ -17184,7 +18547,7 @@ async function getLifecycleHistory(epicId, cwd) {
17184
18547
  }
17185
18548
  const stageIds = stages.map((s) => s.id);
17186
18549
  if (stageIds.length > 0) {
17187
- const gateResults = await db.select().from(lifecycleGateResults).where(eq10(lifecycleGateResults.stageId, stageIds[0]));
18550
+ const gateResults = await db.select().from(lifecycleGateResults).where(eq11(lifecycleGateResults.stageId, stageIds[0]));
17188
18551
  for (const gate of gateResults) {
17189
18552
  const stageName = stageIdToName.get(gate.stageId);
17190
18553
  if (stageName) {
@@ -17197,7 +18560,7 @@ async function getLifecycleHistory(epicId, cwd) {
17197
18560
  }
17198
18561
  }
17199
18562
  for (let i = 1; i < stageIds.length; i++) {
17200
- const additionalGates = await db.select().from(lifecycleGateResults).where(eq10(lifecycleGateResults.stageId, stageIds[i]));
18563
+ const additionalGates = await db.select().from(lifecycleGateResults).where(eq11(lifecycleGateResults.stageId, stageIds[i]));
17201
18564
  for (const gate of additionalGates) {
17202
18565
  const stageName = stageIdToName.get(gate.stageId);
17203
18566
  if (stageName) {
@@ -17217,13 +18580,13 @@ async function getLifecycleHistory(epicId, cwd) {
17217
18580
  async function getLifecycleGates(epicId, cwd) {
17218
18581
  const db = await getDb(cwd);
17219
18582
  const pipelineId = `pipeline-${epicId}`;
17220
- const stages = await db.select().from(lifecycleStages).where(eq10(lifecycleStages.pipelineId, pipelineId));
18583
+ const stages = await db.select().from(lifecycleStages).where(eq11(lifecycleStages.pipelineId, pipelineId));
17221
18584
  if (stages.length === 0) {
17222
18585
  return {};
17223
18586
  }
17224
18587
  const gates = {};
17225
18588
  for (const stage of stages) {
17226
- const gateRows = await db.select().from(lifecycleGateResults).where(eq10(lifecycleGateResults.stageId, stage.id));
18589
+ const gateRows = await db.select().from(lifecycleGateResults).where(eq11(lifecycleGateResults.stageId, stage.id));
17227
18590
  if (gateRows.length > 0) {
17228
18591
  gates[stage.stageName] = {};
17229
18592
  for (const gateRow of gateRows) {
@@ -17295,7 +18658,7 @@ async function ensureLifecycleContext(epicId, stageName, cwd, options) {
17295
18658
  getNativeDb2().prepare(
17296
18659
  `INSERT OR IGNORE INTO tasks (id, title, status, priority, created_at) VALUES (?, ?, 'pending', 'medium', datetime('now'))`
17297
18660
  ).run(epicId, `Task ${epicId}`);
17298
- const existingPipeline = await db.select().from(lifecyclePipelines).where(eq10(lifecyclePipelines.id, pipelineId)).limit(1).all();
18661
+ const existingPipeline = await db.select().from(lifecyclePipelines).where(eq11(lifecyclePipelines.id, pipelineId)).limit(1).all();
17299
18662
  if (existingPipeline.length === 0) {
17300
18663
  await db.insert(lifecyclePipelines).values({
17301
18664
  id: pipelineId,
@@ -17305,7 +18668,7 @@ async function ensureLifecycleContext(epicId, stageName, cwd, options) {
17305
18668
  startedAt: options.now
17306
18669
  }).run();
17307
18670
  }
17308
- const existingStage = await db.select().from(lifecycleStages).where(eq10(lifecycleStages.id, stageId)).limit(1).all();
18671
+ const existingStage = await db.select().from(lifecycleStages).where(eq11(lifecycleStages.id, stageId)).limit(1).all();
17309
18672
  if (existingStage.length === 0) {
17310
18673
  const sequence = isValidStage(stageName) ? STAGE_ORDER[stageName] : 0;
17311
18674
  await db.insert(lifecycleStages).values({
@@ -17318,7 +18681,7 @@ async function ensureLifecycleContext(epicId, stageName, cwd, options) {
17318
18681
  }).run();
17319
18682
  }
17320
18683
  if (options.updateCurrentStage) {
17321
- await db.update(lifecyclePipelines).set({ currentStageId: stageId }).where(eq10(lifecyclePipelines.id, pipelineId)).run();
18684
+ await db.update(lifecyclePipelines).set({ currentStageId: stageId }).where(eq11(lifecyclePipelines.id, pipelineId)).run();
17322
18685
  }
17323
18686
  return { db, pipelineId, stageId };
17324
18687
  }
@@ -17348,7 +18711,7 @@ async function recordStageProgress(epicId, stage, status, notes, cwd) {
17348
18711
  status,
17349
18712
  related: artifact.related
17350
18713
  };
17351
- const existingStage = await db.select().from(lifecycleStages).where(eq10(lifecycleStages.id, stageId)).limit(1).all();
18714
+ const existingStage = await db.select().from(lifecycleStages).where(eq11(lifecycleStages.id, stageId)).limit(1).all();
17352
18715
  const sequence = STAGE_ORDER[stage];
17353
18716
  const stageValues = {
17354
18717
  status,
@@ -17375,7 +18738,7 @@ async function recordStageProgress(epicId, stage, status, notes, cwd) {
17375
18738
  provenanceChainJson: JSON.stringify(provenanceChain)
17376
18739
  }).run();
17377
18740
  } else {
17378
- await db.update(lifecycleStages).set(stageValues).where(eq10(lifecycleStages.id, stageId)).run();
18741
+ await db.update(lifecycleStages).set(stageValues).where(eq11(lifecycleStages.id, stageId)).run();
17379
18742
  }
17380
18743
  if (status === "completed") {
17381
18744
  await linkProvenance(epicId, stageName, artifact.absolutePath, cwd);
@@ -17407,7 +18770,7 @@ async function resetStage(epicId, stage, reason, cwd) {
17407
18770
  skippedAt: null,
17408
18771
  skipReason: null,
17409
18772
  notesJson: JSON.stringify([`Reset: ${reason}`])
17410
- }).where(eq10(lifecycleStages.id, stageId)).run();
18773
+ }).where(eq11(lifecycleStages.id, stageId)).run();
17411
18774
  return { epicId, stage, reason };
17412
18775
  }
17413
18776
  async function passGate(epicId, gateName, agent, notes, cwd) {
@@ -17419,7 +18782,7 @@ async function passGate(epicId, gateName, agent, notes, cwd) {
17419
18782
  stageStatusOnCreate: "in_progress",
17420
18783
  updateCurrentStage: true
17421
18784
  });
17422
- const existingGate = await db.select().from(lifecycleGateResults).where(eq10(lifecycleGateResults.id, gateId)).limit(1).all();
18785
+ const existingGate = await db.select().from(lifecycleGateResults).where(eq11(lifecycleGateResults.id, gateId)).limit(1).all();
17423
18786
  const gateValues = {
17424
18787
  id: gateId,
17425
18788
  stageId,
@@ -17431,7 +18794,7 @@ async function passGate(epicId, gateName, agent, notes, cwd) {
17431
18794
  reason: null
17432
18795
  };
17433
18796
  if (existingGate.length > 0) {
17434
- await db.update(lifecycleGateResults).set(gateValues).where(eq10(lifecycleGateResults.id, gateId)).run();
18797
+ await db.update(lifecycleGateResults).set(gateValues).where(eq11(lifecycleGateResults.id, gateId)).run();
17435
18798
  } else {
17436
18799
  await db.insert(lifecycleGateResults).values(gateValues).run();
17437
18800
  }
@@ -17446,7 +18809,7 @@ async function failGate(epicId, gateName, reason, cwd) {
17446
18809
  stageStatusOnCreate: "in_progress",
17447
18810
  updateCurrentStage: true
17448
18811
  });
17449
- const existingGate = await db.select().from(lifecycleGateResults).where(eq10(lifecycleGateResults.id, gateId)).limit(1).all();
18812
+ const existingGate = await db.select().from(lifecycleGateResults).where(eq11(lifecycleGateResults.id, gateId)).limit(1).all();
17450
18813
  const gateValues = {
17451
18814
  id: gateId,
17452
18815
  stageId,
@@ -17458,7 +18821,7 @@ async function failGate(epicId, gateName, reason, cwd) {
17458
18821
  reason: reason ?? null
17459
18822
  };
17460
18823
  if (existingGate.length > 0) {
17461
- await db.update(lifecycleGateResults).set(gateValues).where(eq10(lifecycleGateResults.id, gateId)).run();
18824
+ await db.update(lifecycleGateResults).set(gateValues).where(eq11(lifecycleGateResults.id, gateId)).run();
17462
18825
  } else {
17463
18826
  await db.insert(lifecycleGateResults).values(gateValues).run();
17464
18827
  }
@@ -17607,9 +18970,9 @@ init_platform();
17607
18970
  // src/core/validation/validate-ops.ts
17608
18971
  init_paths();
17609
18972
  init_data_accessor();
17610
- import { readFileSync as readFileSync26, existsSync as existsSync34, appendFileSync as appendFileSync3, mkdirSync as mkdirSync10 } from "node:fs";
18973
+ import { readFileSync as readFileSync26, existsSync as existsSync34, appendFileSync as appendFileSync3, mkdirSync as mkdirSync11 } from "node:fs";
17611
18974
  import { execFileSync as execFileSync3 } from "node:child_process";
17612
- import { join as join37, dirname as dirname9, resolve as resolve6 } from "node:path";
18975
+ import { join as join38, dirname as dirname10, resolve as resolve6 } from "node:path";
17613
18976
 
17614
18977
  // src/core/validation/schema-validator.ts
17615
18978
  init_validation_schemas();
@@ -17826,7 +19189,7 @@ init_json();
17826
19189
  init_status_registry();
17827
19190
 
17828
19191
  // src/core/repair.ts
17829
- import { isNull as isNull2, sql as sql3 } from "drizzle-orm";
19192
+ import { isNull as isNull2, sql as sql4 } from "drizzle-orm";
17830
19193
 
17831
19194
  // src/core/validation/validate-ops.ts
17832
19195
  function readJsonFile2(filePath) {
@@ -17846,7 +19209,7 @@ async function coreValidateSchema(type, data, projectRoot) {
17846
19209
  throw new Error(`Unknown schema type: ${type}. Valid types: ${validTypes.join(", ")}`);
17847
19210
  }
17848
19211
  if (type === "config") {
17849
- const filePath = join37(projectRoot, ".cleo", "config.json");
19212
+ const filePath = join38(projectRoot, ".cleo", "config.json");
17850
19213
  if (!existsSync34(filePath)) {
17851
19214
  throw new Error("File not found: .cleo/config.json");
17852
19215
  }
@@ -18058,7 +19421,7 @@ function coreValidateOutput(filePath, taskId, projectRoot) {
18058
19421
  };
18059
19422
  }
18060
19423
  function parseComplianceEntries(projectRoot) {
18061
- const compliancePath = join37(projectRoot, ".cleo", "metrics", "COMPLIANCE.jsonl");
19424
+ const compliancePath = join38(projectRoot, ".cleo", "metrics", "COMPLIANCE.jsonl");
18062
19425
  if (!existsSync34(compliancePath)) {
18063
19426
  return [];
18064
19427
  }
@@ -18122,10 +19485,10 @@ function coreComplianceRecord(taskId, result, protocol, violations, projectRoot)
18122
19485
  if (!validResults.includes(result)) {
18123
19486
  throw new Error(`Invalid result: ${result}. Valid: ${validResults.join(", ")}`);
18124
19487
  }
18125
- const compliancePath = join37(projectRoot, ".cleo", "metrics", "COMPLIANCE.jsonl");
18126
- const dir = dirname9(compliancePath);
19488
+ const compliancePath = join38(projectRoot, ".cleo", "metrics", "COMPLIANCE.jsonl");
19489
+ const dir = dirname10(compliancePath);
18127
19490
  if (!existsSync34(dir)) {
18128
- mkdirSync10(dir, { recursive: true });
19491
+ mkdirSync11(dir, { recursive: true });
18129
19492
  }
18130
19493
  const entry = {
18131
19494
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
@@ -18144,8 +19507,8 @@ function coreComplianceRecord(taskId, result, protocol, violations, projectRoot)
18144
19507
  };
18145
19508
  }
18146
19509
  function coreTestStatus(projectRoot) {
18147
- const testDir = join37(projectRoot, "tests");
18148
- const mcpTestDir = join37(projectRoot, "src", "mcp", "__tests__");
19510
+ const testDir = join38(projectRoot, "tests");
19511
+ const mcpTestDir = join38(projectRoot, "src", "mcp", "__tests__");
18149
19512
  const hasBatsTests = existsSync34(testDir);
18150
19513
  const hasMcpTests = existsSync34(mcpTestDir);
18151
19514
  return {
@@ -18289,8 +19652,8 @@ async function coreCoherenceCheck(projectRoot) {
18289
19652
  };
18290
19653
  }
18291
19654
  function coreTestRun(params, projectRoot) {
18292
- const hasVitest = existsSync34(join37(projectRoot, "node_modules", ".bin", "vitest"));
18293
- const hasBats = existsSync34(join37(projectRoot, "tests"));
19655
+ const hasVitest = existsSync34(join38(projectRoot, "node_modules", ".bin", "vitest"));
19656
+ const hasBats = existsSync34(join38(projectRoot, "tests"));
18294
19657
  if (!hasVitest && !hasBats) {
18295
19658
  return {
18296
19659
  ran: false,
@@ -18336,7 +19699,7 @@ function coreTestRun(params, projectRoot) {
18336
19699
  }
18337
19700
  }
18338
19701
  function coreTestCoverage(projectRoot) {
18339
- const coveragePath = join37(projectRoot, "coverage", "coverage-summary.json");
19702
+ const coveragePath = join38(projectRoot, "coverage", "coverage-summary.json");
18340
19703
  if (!existsSync34(coveragePath)) {
18341
19704
  return {
18342
19705
  available: false,
@@ -18985,12 +20348,12 @@ async function getUnblockOpportunities(cwd, accessor) {
18985
20348
  // src/core/orchestration/parallel.ts
18986
20349
  init_errors();
18987
20350
  init_exit_codes();
18988
- import { readFileSync as readFileSync27, writeFileSync as writeFileSync7, existsSync as existsSync35, mkdirSync as mkdirSync11 } from "node:fs";
18989
- import { join as join38, dirname as dirname10 } from "node:path";
20351
+ import { readFileSync as readFileSync27, writeFileSync as writeFileSync7, existsSync as existsSync35, mkdirSync as mkdirSync12 } from "node:fs";
20352
+ import { join as join39, dirname as dirname11 } from "node:path";
18990
20353
  init_json();
18991
20354
  init_paths();
18992
20355
  function getParallelStatePath(projectRoot) {
18993
- return join38(projectRoot, ".cleo", "parallel-state.json");
20356
+ return join39(projectRoot, ".cleo", "parallel-state.json");
18994
20357
  }
18995
20358
  function readParallelState(projectRoot) {
18996
20359
  const statePath = getParallelStatePath(projectRoot);
@@ -19003,8 +20366,8 @@ function readParallelState(projectRoot) {
19003
20366
  }
19004
20367
  function writeParallelState(state, projectRoot) {
19005
20368
  const statePath = getParallelStatePath(projectRoot);
19006
- const dir = dirname10(statePath);
19007
- if (!existsSync35(dir)) mkdirSync11(dir, { recursive: true });
20369
+ const dir = dirname11(statePath);
20370
+ if (!existsSync35(dir)) mkdirSync12(dir, { recursive: true });
19008
20371
  writeFileSync7(statePath, JSON.stringify(state, null, 2), "utf-8");
19009
20372
  }
19010
20373
  async function startParallelExecution(epicId, wave, cwd, accessor) {
@@ -19141,7 +20504,7 @@ async function validateSpawnReadiness(taskId, cwd, accessor) {
19141
20504
  init_json();
19142
20505
  init_paths();
19143
20506
  import { readFileSync as readFileSync28, existsSync as existsSync36 } from "node:fs";
19144
- import { join as join39 } from "node:path";
20507
+ import { join as join40 } from "node:path";
19145
20508
  async function buildBrainState(projectRoot, opts, accessor) {
19146
20509
  const speed = opts?.speed || "fast";
19147
20510
  const brain = {
@@ -19209,7 +20572,7 @@ async function buildBrainState(projectRoot, opts, accessor) {
19209
20572
  blockedBy: b.depends || []
19210
20573
  }));
19211
20574
  try {
19212
- const decisionLogPath = join39(projectRoot, ".cleo", "decision-log.jsonl");
20575
+ const decisionLogPath = join40(projectRoot, ".cleo", "decision-log.jsonl");
19213
20576
  if (existsSync36(decisionLogPath)) {
19214
20577
  const content = readFileSync28(decisionLogPath, "utf-8").trim();
19215
20578
  if (content) {
@@ -19231,7 +20594,7 @@ async function buildBrainState(projectRoot, opts, accessor) {
19231
20594
  } catch {
19232
20595
  }
19233
20596
  try {
19234
- const contextStatePath = join39(projectRoot, ".cleo", ".context-state.json");
20597
+ const contextStatePath = join40(projectRoot, ".cleo", ".context-state.json");
19235
20598
  if (existsSync36(contextStatePath)) {
19236
20599
  const state = JSON.parse(readFileSync28(contextStatePath, "utf-8"));
19237
20600
  const percentage = state.contextWindow?.percentage ?? 0;
@@ -19685,8 +21048,8 @@ async function orchestrateCheck(projectRoot) {
19685
21048
 
19686
21049
  // src/core/memory/engine-compat.ts
19687
21050
  init_paths();
19688
- import { readFileSync as readFileSync32, writeFileSync as writeFileSync10, appendFileSync as appendFileSync6, existsSync as existsSync40, mkdirSync as mkdirSync14 } from "node:fs";
19689
- import { resolve as resolve7, dirname as dirname11 } from "node:path";
21051
+ import { readFileSync as readFileSync32, writeFileSync as writeFileSync10, appendFileSync as appendFileSync6, existsSync as existsSync40, mkdirSync as mkdirSync15 } from "node:fs";
21052
+ import { resolve as resolve7, dirname as dirname12 } from "node:path";
19690
21053
 
19691
21054
  // src/core/memory/index.ts
19692
21055
  init_json();
@@ -19695,123 +21058,32 @@ init_errors();
19695
21058
  init_exit_codes();
19696
21059
  init_paths();
19697
21060
 
19698
- // src/store/brain-accessor.ts
19699
- import { eq as eq11, and as and3, gte, desc, asc as asc2 } from "drizzle-orm";
19700
-
19701
- // src/store/brain-sqlite.ts
19702
- import { readMigrationFiles as readMigrationFiles2 } from "drizzle-orm/migrator";
19703
- import { drizzle as drizzle2 } from "drizzle-orm/sqlite-proxy";
19704
- import { migrate as migrate2 } from "drizzle-orm/sqlite-proxy/migrator";
19705
-
19706
- // src/store/brain-schema.ts
19707
- import {
19708
- sqliteTable as sqliteTable2,
19709
- text as text2,
19710
- integer as integer2,
19711
- real,
19712
- index as index2,
19713
- primaryKey as primaryKey2
19714
- } from "drizzle-orm/sqlite-core";
19715
- import { sql as sql4 } from "drizzle-orm";
19716
- var BRAIN_DECISION_TYPES = ["architecture", "technical", "process", "strategic", "tactical"];
19717
- var BRAIN_CONFIDENCE_LEVELS = ["low", "medium", "high"];
19718
- var BRAIN_OUTCOME_TYPES = ["success", "failure", "mixed", "pending"];
19719
- var BRAIN_PATTERN_TYPES = ["workflow", "blocker", "success", "failure", "optimization"];
19720
- var BRAIN_IMPACT_LEVELS = ["low", "medium", "high"];
19721
- var BRAIN_LINK_TYPES = ["produced_by", "applies_to", "informed_by", "contradicts"];
19722
- var BRAIN_MEMORY_TYPES = ["decision", "pattern", "learning"];
19723
- var brainDecisions = sqliteTable2("brain_decisions", {
19724
- id: text2("id").primaryKey(),
19725
- type: text2("type", { enum: BRAIN_DECISION_TYPES }).notNull(),
19726
- decision: text2("decision").notNull(),
19727
- rationale: text2("rationale").notNull(),
19728
- confidence: text2("confidence", { enum: BRAIN_CONFIDENCE_LEVELS }).notNull(),
19729
- outcome: text2("outcome", { enum: BRAIN_OUTCOME_TYPES }),
19730
- alternativesJson: text2("alternatives_json"),
19731
- contextEpicId: text2("context_epic_id"),
19732
- // soft FK to tasks.id in tasks.db
19733
- contextTaskId: text2("context_task_id"),
19734
- // soft FK to tasks.id in tasks.db
19735
- contextPhase: text2("context_phase"),
19736
- createdAt: text2("created_at").notNull().default(sql4`(datetime('now'))`),
19737
- updatedAt: text2("updated_at")
19738
- }, (table) => [
19739
- index2("idx_brain_decisions_type").on(table.type),
19740
- index2("idx_brain_decisions_confidence").on(table.confidence),
19741
- index2("idx_brain_decisions_outcome").on(table.outcome),
19742
- index2("idx_brain_decisions_context_epic").on(table.contextEpicId),
19743
- index2("idx_brain_decisions_context_task").on(table.contextTaskId)
19744
- ]);
19745
- var brainPatterns = sqliteTable2("brain_patterns", {
19746
- id: text2("id").primaryKey(),
19747
- type: text2("type", { enum: BRAIN_PATTERN_TYPES }).notNull(),
19748
- pattern: text2("pattern").notNull(),
19749
- context: text2("context").notNull(),
19750
- frequency: integer2("frequency").notNull().default(1),
19751
- successRate: real("success_rate"),
19752
- impact: text2("impact", { enum: BRAIN_IMPACT_LEVELS }),
19753
- antiPattern: text2("anti_pattern"),
19754
- mitigation: text2("mitigation"),
19755
- examplesJson: text2("examples_json").default("[]"),
19756
- extractedAt: text2("extracted_at").notNull().default(sql4`(datetime('now'))`),
19757
- updatedAt: text2("updated_at")
19758
- }, (table) => [
19759
- index2("idx_brain_patterns_type").on(table.type),
19760
- index2("idx_brain_patterns_impact").on(table.impact),
19761
- index2("idx_brain_patterns_frequency").on(table.frequency)
19762
- ]);
19763
- var brainLearnings = sqliteTable2("brain_learnings", {
19764
- id: text2("id").primaryKey(),
19765
- insight: text2("insight").notNull(),
19766
- source: text2("source").notNull(),
19767
- confidence: real("confidence").notNull(),
19768
- // 0.0-1.0
19769
- actionable: integer2("actionable", { mode: "boolean" }).notNull().default(false),
19770
- application: text2("application"),
19771
- applicableTypesJson: text2("applicable_types_json"),
19772
- createdAt: text2("created_at").notNull().default(sql4`(datetime('now'))`),
19773
- updatedAt: text2("updated_at")
19774
- }, (table) => [
19775
- index2("idx_brain_learnings_confidence").on(table.confidence),
19776
- index2("idx_brain_learnings_actionable").on(table.actionable)
19777
- ]);
19778
- var brainMemoryLinks = sqliteTable2("brain_memory_links", {
19779
- memoryType: text2("memory_type", { enum: BRAIN_MEMORY_TYPES }).notNull(),
19780
- memoryId: text2("memory_id").notNull(),
19781
- taskId: text2("task_id").notNull(),
19782
- // soft FK to tasks.id in tasks.db
19783
- linkType: text2("link_type", { enum: BRAIN_LINK_TYPES }).notNull(),
19784
- createdAt: text2("created_at").notNull().default(sql4`(datetime('now'))`)
19785
- }, (table) => [
19786
- primaryKey2({ columns: [table.memoryType, table.memoryId, table.taskId, table.linkType] }),
19787
- index2("idx_brain_links_task").on(table.taskId),
19788
- index2("idx_brain_links_memory").on(table.memoryType, table.memoryId)
19789
- ]);
19790
- var brainSchemaMeta = sqliteTable2("brain_schema_meta", {
19791
- key: text2("key").primaryKey(),
19792
- value: text2("value").notNull()
19793
- });
19794
-
19795
- // src/store/brain-sqlite.ts
19796
- init_paths();
19797
- init_node_sqlite_adapter();
19798
-
19799
21061
  // src/core/memory/decisions.ts
21062
+ init_brain_accessor();
21063
+ init_brain_sqlite();
21064
+ init_brain_schema();
19800
21065
  import { desc as desc2 } from "drizzle-orm";
19801
21066
 
21067
+ // src/core/memory/brain-migration.ts
21068
+ init_brain_accessor();
21069
+
21070
+ // src/core/memory/index.ts
21071
+ init_brain_search();
21072
+ init_brain_links();
21073
+
19802
21074
  // src/core/memory/patterns.ts
19803
21075
  import { randomBytes as randomBytes7 } from "node:crypto";
19804
- import { readFileSync as readFileSync30, writeFileSync as writeFileSync8, appendFileSync as appendFileSync4, mkdirSync as mkdirSync12, existsSync as existsSync38 } from "node:fs";
19805
- import { join as join40 } from "node:path";
21076
+ import { readFileSync as readFileSync30, writeFileSync as writeFileSync8, appendFileSync as appendFileSync4, mkdirSync as mkdirSync13, existsSync as existsSync38 } from "node:fs";
21077
+ import { join as join41 } from "node:path";
19806
21078
  function getMemoryDir(projectRoot) {
19807
- const memDir = join40(projectRoot, ".cleo", "memory");
21079
+ const memDir = join41(projectRoot, ".cleo", "memory");
19808
21080
  if (!existsSync38(memDir)) {
19809
- mkdirSync12(memDir, { recursive: true });
21081
+ mkdirSync13(memDir, { recursive: true });
19810
21082
  }
19811
21083
  return memDir;
19812
21084
  }
19813
21085
  function getPatternsPath(projectRoot) {
19814
- return join40(getMemoryDir(projectRoot), "patterns.jsonl");
21086
+ return join41(getMemoryDir(projectRoot), "patterns.jsonl");
19815
21087
  }
19816
21088
  function generatePatternId() {
19817
21089
  return `P${randomBytes7(4).toString("hex")}`;
@@ -19928,17 +21200,17 @@ function patternStats(projectRoot) {
19928
21200
 
19929
21201
  // src/core/memory/learnings.ts
19930
21202
  import { randomBytes as randomBytes8 } from "node:crypto";
19931
- import { readFileSync as readFileSync31, writeFileSync as writeFileSync9, appendFileSync as appendFileSync5, mkdirSync as mkdirSync13, existsSync as existsSync39 } from "node:fs";
19932
- import { join as join41 } from "node:path";
21203
+ import { readFileSync as readFileSync31, writeFileSync as writeFileSync9, appendFileSync as appendFileSync5, mkdirSync as mkdirSync14, existsSync as existsSync39 } from "node:fs";
21204
+ import { join as join42 } from "node:path";
19933
21205
  function getMemoryDir2(projectRoot) {
19934
- const memDir = join41(projectRoot, ".cleo", "memory");
21206
+ const memDir = join42(projectRoot, ".cleo", "memory");
19935
21207
  if (!existsSync39(memDir)) {
19936
- mkdirSync13(memDir, { recursive: true });
21208
+ mkdirSync14(memDir, { recursive: true });
19937
21209
  }
19938
21210
  return memDir;
19939
21211
  }
19940
21212
  function getLearningsPath(projectRoot) {
19941
- return join41(getMemoryDir2(projectRoot), "learnings.jsonl");
21213
+ return join42(getMemoryDir2(projectRoot), "learnings.jsonl");
19942
21214
  }
19943
21215
  function generateLearningId() {
19944
21216
  return `L${randomBytes8(4).toString("hex")}`;
@@ -20051,6 +21323,7 @@ function learningStats(projectRoot) {
20051
21323
  }
20052
21324
 
20053
21325
  // src/core/memory/index.ts
21326
+ init_brain_retrieval();
20054
21327
  function filterManifestEntries(entries, filter) {
20055
21328
  let filtered = entries;
20056
21329
  if (filter.taskId) {
@@ -20084,6 +21357,7 @@ function filterManifestEntries(entries, filter) {
20084
21357
  }
20085
21358
 
20086
21359
  // src/core/memory/engine-compat.ts
21360
+ init_brain_retrieval();
20087
21361
  function getManifestPath2(projectRoot) {
20088
21362
  return getManifestPath(projectRoot);
20089
21363
  }
@@ -20278,9 +21552,9 @@ function memoryManifestAppend(entry, projectRoot) {
20278
21552
  return { success: false, error: { code: "E_VALIDATION_FAILED", message: `Invalid manifest entry: ${errors.join(", ")}` } };
20279
21553
  }
20280
21554
  const manifestPath = getManifestPath2(projectRoot);
20281
- const dir = dirname11(manifestPath);
21555
+ const dir = dirname12(manifestPath);
20282
21556
  if (!existsSync40(dir)) {
20283
- mkdirSync14(dir, { recursive: true });
21557
+ mkdirSync15(dir, { recursive: true });
20284
21558
  }
20285
21559
  const serialized = JSON.stringify(entry);
20286
21560
  appendFileSync6(manifestPath, serialized + "\n", "utf-8");
@@ -20299,9 +21573,9 @@ function memoryManifestArchive(beforeDate, projectRoot) {
20299
21573
  if (toArchive.length === 0) {
20300
21574
  return { success: true, data: { archived: 0, remaining: entries.length, message: "No entries found before the specified date" } };
20301
21575
  }
20302
- const archiveDir = dirname11(archivePath);
21576
+ const archiveDir = dirname12(archivePath);
20303
21577
  if (!existsSync40(archiveDir)) {
20304
- mkdirSync14(archiveDir, { recursive: true });
21578
+ mkdirSync15(archiveDir, { recursive: true });
20305
21579
  }
20306
21580
  const archiveContent = toArchive.map((e) => JSON.stringify(e)).join("\n") + "\n";
20307
21581
  appendFileSync6(archivePath, archiveContent, "utf-8");
@@ -20408,7 +21682,7 @@ function memoryInject(protocolType, params, projectRoot) {
20408
21682
  if (!protocolContent) {
20409
21683
  return {
20410
21684
  success: false,
20411
- error: { code: "E_NOT_FOUND", message: `Protocol '${protocolType}' not found in protocols/, skills/_shared/, or agents/cleo-subagent/protocols/` }
21685
+ error: { code: "E_NOT_FOUND", message: `Protocol '${protocolType}' not found in src/protocols/, skills/_shared/, or agents/cleo-subagent/protocols/` }
20412
21686
  };
20413
21687
  }
20414
21688
  return {
@@ -20478,6 +21752,59 @@ function memoryLearningStats(projectRoot) {
20478
21752
  return { success: false, error: { code: "E_LEARNING_STATS", message: error instanceof Error ? error.message : String(error) } };
20479
21753
  }
20480
21754
  }
21755
+ async function memoryBrainSearch(params, projectRoot) {
21756
+ try {
21757
+ const root = resolveRoot(projectRoot);
21758
+ const result = await searchBrainCompact(root, {
21759
+ query: params.query,
21760
+ limit: params.limit,
21761
+ tables: params.tables,
21762
+ dateStart: params.dateStart,
21763
+ dateEnd: params.dateEnd
21764
+ });
21765
+ return { success: true, data: result };
21766
+ } catch (error) {
21767
+ return { success: false, error: { code: "E_BRAIN_SEARCH", message: error instanceof Error ? error.message : String(error) } };
21768
+ }
21769
+ }
21770
+ async function memoryBrainTimeline(params, projectRoot) {
21771
+ try {
21772
+ const root = resolveRoot(projectRoot);
21773
+ const result = await timelineBrain(root, {
21774
+ anchor: params.anchor,
21775
+ depthBefore: params.depthBefore,
21776
+ depthAfter: params.depthAfter
21777
+ });
21778
+ return { success: true, data: result };
21779
+ } catch (error) {
21780
+ return { success: false, error: { code: "E_BRAIN_TIMELINE", message: error instanceof Error ? error.message : String(error) } };
21781
+ }
21782
+ }
21783
+ async function memoryBrainFetch(params, projectRoot) {
21784
+ try {
21785
+ const root = resolveRoot(projectRoot);
21786
+ const result = await fetchBrainEntries(root, { ids: params.ids });
21787
+ return { success: true, data: result };
21788
+ } catch (error) {
21789
+ return { success: false, error: { code: "E_BRAIN_FETCH", message: error instanceof Error ? error.message : String(error) } };
21790
+ }
21791
+ }
21792
+ async function memoryBrainObserve(params, projectRoot) {
21793
+ try {
21794
+ const root = resolveRoot(projectRoot);
21795
+ const result = await observeBrain(root, {
21796
+ text: params.text,
21797
+ title: params.title,
21798
+ type: params.type,
21799
+ project: params.project,
21800
+ sourceSessionId: params.sourceSessionId,
21801
+ sourceType: params.sourceType
21802
+ });
21803
+ return { success: true, data: result };
21804
+ } catch (error) {
21805
+ return { success: false, error: { code: "E_BRAIN_OBSERVE", message: error instanceof Error ? error.message : String(error) } };
21806
+ }
21807
+ }
20481
21808
 
20482
21809
  // src/dispatch/engines/release-engine.ts
20483
21810
  init_platform();
@@ -20486,11 +21813,11 @@ init_data_accessor();
20486
21813
  // src/core/release/release-manifest.ts
20487
21814
  init_json();
20488
21815
  init_paths();
20489
- import { existsSync as existsSync41, mkdirSync as mkdirSync15 } from "node:fs";
21816
+ import { existsSync as existsSync41, mkdirSync as mkdirSync16 } from "node:fs";
20490
21817
  import { execFileSync as execFileSync4 } from "node:child_process";
20491
- import { dirname as dirname12, join as join42 } from "node:path";
21818
+ import { dirname as dirname13, join as join43 } from "node:path";
20492
21819
  function getReleasesPath(cwd) {
20493
- return join42(getCleoDirAbsolute(cwd), "releases.json");
21820
+ return join43(getCleoDirAbsolute(cwd), "releases.json");
20494
21821
  }
20495
21822
  async function readReleases(cwd) {
20496
21823
  const data = await readJson(getReleasesPath(cwd));
@@ -20498,9 +21825,9 @@ async function readReleases(cwd) {
20498
21825
  }
20499
21826
  async function writeReleases(index3, cwd) {
20500
21827
  const releasesPath = getReleasesPath(cwd);
20501
- const dir = dirname12(releasesPath);
21828
+ const dir = dirname13(releasesPath);
20502
21829
  if (!existsSync41(dir)) {
20503
- mkdirSync15(dir, { recursive: true });
21830
+ mkdirSync16(dir, { recursive: true });
20504
21831
  }
20505
21832
  await saveJson(releasesPath, index3);
20506
21833
  }
@@ -20767,7 +22094,7 @@ async function rollbackRelease(version, reason, cwd) {
20767
22094
  };
20768
22095
  }
20769
22096
  async function readPushPolicy(cwd) {
20770
- const configPath = join42(getCleoDirAbsolute(cwd), "config.json");
22097
+ const configPath = join43(getCleoDirAbsolute(cwd), "config.json");
20771
22098
  const config = await readJson(configPath);
20772
22099
  if (!config) return void 0;
20773
22100
  const release2 = config.release;
@@ -20983,7 +22310,7 @@ async function releasePush(version, remote, projectRoot, opts) {
20983
22310
  // src/dispatch/engines/template-parser.ts
20984
22311
  init_platform();
20985
22312
  import { readFileSync as readFileSync33, readdirSync as readdirSync12, existsSync as existsSync42 } from "fs";
20986
- import { join as join43 } from "path";
22313
+ import { join as join44 } from "path";
20987
22314
  import { parse as parseYaml } from "yaml";
20988
22315
  var SUFFIX_PATTERNS = ["_report", "_request", "_question"];
20989
22316
  function deriveSubcommand(filename) {
@@ -20998,7 +22325,7 @@ function deriveSubcommand(filename) {
20998
22325
  return firstWord.toLowerCase();
20999
22326
  }
21000
22327
  function parseTemplateFile(templateDir, filename) {
21001
- const filePath = join43(templateDir, filename);
22328
+ const filePath = join44(templateDir, filename);
21002
22329
  const raw = readFileSync33(filePath, "utf-8");
21003
22330
  const parsed = parseYaml(raw);
21004
22331
  const name = typeof parsed.name === "string" ? parsed.name : filename;
@@ -21048,7 +22375,7 @@ function parseTemplateFile(templateDir, filename) {
21048
22375
  };
21049
22376
  }
21050
22377
  function parseIssueTemplates(projectRoot) {
21051
- const templateDir = join43(projectRoot, ".github", "ISSUE_TEMPLATE");
22378
+ const templateDir = join44(projectRoot, ".github", "ISSUE_TEMPLATE");
21052
22379
  if (!existsSync42(templateDir)) {
21053
22380
  return engineError("E_NOT_FOUND", `Issue template directory not found: ${templateDir}`);
21054
22381
  }
@@ -21654,8 +22981,9 @@ var SessionHandler = class {
21654
22981
  if (endResult.success && endResult.data) {
21655
22982
  const sessionId = endResult.data.sessionId;
21656
22983
  if (sessionId) {
22984
+ let debriefResult = null;
21657
22985
  try {
21658
- await sessionComputeDebrief(this.projectRoot, sessionId, {
22986
+ debriefResult = await sessionComputeDebrief(this.projectRoot, sessionId, {
21659
22987
  note: params?.note,
21660
22988
  nextAction: params?.nextAction
21661
22989
  });
@@ -21668,6 +22996,13 @@ var SessionHandler = class {
21668
22996
  } catch {
21669
22997
  }
21670
22998
  }
22999
+ if (debriefResult?.success && debriefResult.data) {
23000
+ try {
23001
+ const { persistSessionMemory: persistSessionMemory2 } = await Promise.resolve().then(() => (init_session_memory(), session_memory_exports));
23002
+ await persistSessionMemory2(this.projectRoot, sessionId, debriefResult.data);
23003
+ } catch {
23004
+ }
23005
+ }
21671
23006
  }
21672
23007
  unbindSession();
21673
23008
  }
@@ -21956,12 +23291,12 @@ init_logger();
21956
23291
 
21957
23292
  // src/core/adrs/validate.ts
21958
23293
  import { readFileSync as readFileSync34, readdirSync as readdirSync13, existsSync as existsSync43 } from "node:fs";
21959
- import { join as join44 } from "node:path";
23294
+ import { join as join45 } from "node:path";
21960
23295
  import AjvModule3 from "ajv";
21961
23296
  var Ajv3 = AjvModule3.default ?? AjvModule3;
21962
23297
  async function validateAllAdrs(projectRoot) {
21963
- const adrsDir = join44(projectRoot, ".cleo", "adrs");
21964
- const schemaPath = join44(projectRoot, "schemas", "adr-frontmatter.schema.json");
23298
+ const adrsDir = join45(projectRoot, ".cleo", "adrs");
23299
+ const schemaPath = join45(projectRoot, "schemas", "adr-frontmatter.schema.json");
21965
23300
  if (!existsSync43(schemaPath)) {
21966
23301
  return {
21967
23302
  valid: false,
@@ -21975,7 +23310,7 @@ async function validateAllAdrs(projectRoot) {
21975
23310
  const schema = JSON.parse(readFileSync34(schemaPath, "utf-8"));
21976
23311
  const ajv = new Ajv3({ allErrors: true });
21977
23312
  const validate = ajv.compile(schema);
21978
- const files = readdirSync13(adrsDir).filter((f) => f.endsWith(".md") && f.startsWith("ADR-")).map((f) => join44(adrsDir, f));
23313
+ const files = readdirSync13(adrsDir).filter((f) => f.endsWith(".md") && f.startsWith("ADR-")).map((f) => join45(adrsDir, f));
21979
23314
  const errors = [];
21980
23315
  for (const filePath of files) {
21981
23316
  const record = parseAdrFile(filePath, projectRoot);
@@ -21995,14 +23330,14 @@ async function validateAllAdrs(projectRoot) {
21995
23330
 
21996
23331
  // src/core/adrs/list.ts
21997
23332
  import { readdirSync as readdirSync14, existsSync as existsSync44 } from "node:fs";
21998
- import { join as join45 } from "node:path";
23333
+ import { join as join46 } from "node:path";
21999
23334
  async function listAdrs(projectRoot, opts) {
22000
- const adrsDir = join45(projectRoot, ".cleo", "adrs");
23335
+ const adrsDir = join46(projectRoot, ".cleo", "adrs");
22001
23336
  if (!existsSync44(adrsDir)) {
22002
23337
  return { adrs: [], total: 0 };
22003
23338
  }
22004
23339
  const files = readdirSync14(adrsDir).filter((f) => f.endsWith(".md") && f.startsWith("ADR-")).sort();
22005
- const records = files.map((f) => parseAdrFile(join45(adrsDir, f), projectRoot));
23340
+ const records = files.map((f) => parseAdrFile(join46(adrsDir, f), projectRoot));
22006
23341
  const filtered = records.filter((r) => {
22007
23342
  if (opts?.status && r.frontmatter.Status !== opts.status) return false;
22008
23343
  if (opts?.since && r.frontmatter.Date < opts.since) return false;
@@ -22022,19 +23357,19 @@ async function listAdrs(projectRoot, opts) {
22022
23357
 
22023
23358
  // src/core/adrs/show.ts
22024
23359
  import { existsSync as existsSync45, readdirSync as readdirSync15 } from "node:fs";
22025
- import { join as join46 } from "node:path";
23360
+ import { join as join47 } from "node:path";
22026
23361
  async function showAdr(projectRoot, adrId) {
22027
- const adrsDir = join46(projectRoot, ".cleo", "adrs");
23362
+ const adrsDir = join47(projectRoot, ".cleo", "adrs");
22028
23363
  if (!existsSync45(adrsDir)) return null;
22029
23364
  const files = readdirSync15(adrsDir).filter((f) => f.startsWith(adrId) && f.endsWith(".md"));
22030
23365
  if (files.length === 0) return null;
22031
- const filePath = join46(adrsDir, files[0]);
23366
+ const filePath = join47(adrsDir, files[0]);
22032
23367
  return parseAdrFile(filePath, projectRoot);
22033
23368
  }
22034
23369
 
22035
23370
  // src/core/adrs/find.ts
22036
23371
  import { readdirSync as readdirSync16, existsSync as existsSync46 } from "node:fs";
22037
- import { join as join47 } from "node:path";
23372
+ import { join as join48 } from "node:path";
22038
23373
  function normalise(s) {
22039
23374
  return s.toLowerCase().replace(/[^a-z0-9\s]/g, " ").replace(/\s+/g, " ").trim();
22040
23375
  }
@@ -22051,7 +23386,7 @@ function matchedTerms(target, terms) {
22051
23386
  return terms.filter((term) => t.includes(term));
22052
23387
  }
22053
23388
  async function findAdrs(projectRoot, query, opts) {
22054
- const adrsDir = join47(projectRoot, ".cleo", "adrs");
23389
+ const adrsDir = join48(projectRoot, ".cleo", "adrs");
22055
23390
  if (!existsSync46(adrsDir)) {
22056
23391
  return { adrs: [], query, total: 0 };
22057
23392
  }
@@ -22061,7 +23396,7 @@ async function findAdrs(projectRoot, query, opts) {
22061
23396
  const filterKeywords = opts?.keywords ? parseTags(opts.keywords) : null;
22062
23397
  const results = [];
22063
23398
  for (const file of files) {
22064
- const record = parseAdrFile(join47(adrsDir, file), projectRoot);
23399
+ const record = parseAdrFile(join48(adrsDir, file), projectRoot);
22065
23400
  const fm = record.frontmatter;
22066
23401
  if (opts?.status && fm.Status !== opts.status) continue;
22067
23402
  if (filterTopics && filterTopics.length > 0) {
@@ -22613,6 +23948,47 @@ var MemoryHandler = class {
22613
23948
  const result = memoryLearningStats(this.projectRoot);
22614
23949
  return this.wrapEngineResult(result, "query", "memory", operation, startTime);
22615
23950
  }
23951
+ // BRAIN retrieval query operations (T5131-T5135)
23952
+ case "brain.search": {
23953
+ const query = params?.query;
23954
+ if (!query) {
23955
+ return this.errorResponse("query", "memory", operation, "E_INVALID_INPUT", "query is required", startTime);
23956
+ }
23957
+ const result = await memoryBrainSearch(
23958
+ {
23959
+ query,
23960
+ limit: params?.limit,
23961
+ tables: params?.tables,
23962
+ dateStart: params?.dateStart,
23963
+ dateEnd: params?.dateEnd
23964
+ },
23965
+ this.projectRoot
23966
+ );
23967
+ return this.wrapEngineResult(result, "query", "memory", operation, startTime);
23968
+ }
23969
+ case "brain.timeline": {
23970
+ const anchor = params?.anchor;
23971
+ if (!anchor) {
23972
+ return this.errorResponse("query", "memory", operation, "E_INVALID_INPUT", "anchor is required", startTime);
23973
+ }
23974
+ const result = await memoryBrainTimeline(
23975
+ {
23976
+ anchor,
23977
+ depthBefore: params?.depthBefore,
23978
+ depthAfter: params?.depthAfter
23979
+ },
23980
+ this.projectRoot
23981
+ );
23982
+ return this.wrapEngineResult(result, "query", "memory", operation, startTime);
23983
+ }
23984
+ case "brain.fetch": {
23985
+ const ids = params?.ids;
23986
+ if (!ids || !Array.isArray(ids) || ids.length === 0) {
23987
+ return this.errorResponse("query", "memory", operation, "E_INVALID_INPUT", "ids is required (non-empty array)", startTime);
23988
+ }
23989
+ const result = await memoryBrainFetch({ ids }, this.projectRoot);
23990
+ return this.wrapEngineResult(result, "query", "memory", operation, startTime);
23991
+ }
22616
23992
  default:
22617
23993
  return this.unsupported("query", "memory", operation, startTime);
22618
23994
  }
@@ -22705,6 +24081,25 @@ var MemoryHandler = class {
22705
24081
  );
22706
24082
  return this.wrapEngineResult(result, "mutate", "memory", operation, startTime);
22707
24083
  }
24084
+ // BRAIN retrieval mutate operations (T5131-T5135)
24085
+ case "brain.observe": {
24086
+ const text3 = params?.text;
24087
+ if (!text3) {
24088
+ return this.errorResponse("mutate", "memory", operation, "E_INVALID_INPUT", "text is required", startTime);
24089
+ }
24090
+ const result = await memoryBrainObserve(
24091
+ {
24092
+ text: text3,
24093
+ title: params?.title,
24094
+ type: params?.type,
24095
+ project: params?.project,
24096
+ sourceSessionId: params?.sourceSessionId,
24097
+ sourceType: params?.sourceType
24098
+ },
24099
+ this.projectRoot
24100
+ );
24101
+ return this.wrapEngineResult(result, "mutate", "memory", operation, startTime);
24102
+ }
22708
24103
  default:
22709
24104
  return this.unsupported("mutate", "memory", operation, startTime);
22710
24105
  }
@@ -22717,8 +24112,8 @@ var MemoryHandler = class {
22717
24112
  // -----------------------------------------------------------------------
22718
24113
  getSupportedOperations() {
22719
24114
  return {
22720
- query: ["show", "list", "find", "pending", "stats", "manifest.read", "contradictions", "superseded", "pattern.search", "pattern.stats", "learning.search", "learning.stats"],
22721
- mutate: ["inject", "link", "manifest.append", "manifest.archive", "pattern.store", "learning.store"]
24115
+ query: ["show", "list", "find", "pending", "stats", "manifest.read", "contradictions", "superseded", "pattern.search", "pattern.stats", "learning.search", "learning.stats", "brain.search", "brain.timeline", "brain.fetch"],
24116
+ mutate: ["inject", "link", "manifest.append", "manifest.archive", "pattern.store", "learning.store", "brain.observe"]
22722
24117
  };
22723
24118
  }
22724
24119
  // -----------------------------------------------------------------------
@@ -23519,7 +24914,7 @@ import { execFileSync as execFileSync6 } from "node:child_process";
23519
24914
  // src/core/issue/template-parser.ts
23520
24915
  init_paths();
23521
24916
  import { existsSync as existsSync48, readFileSync as readFileSync35, readdirSync as readdirSync17, writeFileSync as writeFileSync11 } from "node:fs";
23522
- import { join as join49, basename as basename8 } from "node:path";
24917
+ import { join as join50, basename as basename8 } from "node:path";
23523
24918
  var TEMPLATE_DIR = ".github/ISSUE_TEMPLATE";
23524
24919
  var CACHE_FILE = "issue-templates.json";
23525
24920
  var SUBCOMMAND_MAP = {
@@ -23594,12 +24989,12 @@ function parseTemplateFile2(filePath) {
23594
24989
  }
23595
24990
  function parseIssueTemplates2(projectDir) {
23596
24991
  const dir = projectDir ?? getProjectRoot();
23597
- const templateDir = join49(dir, TEMPLATE_DIR);
24992
+ const templateDir = join50(dir, TEMPLATE_DIR);
23598
24993
  if (!existsSync48(templateDir)) return [];
23599
24994
  const templates = [];
23600
24995
  for (const file of readdirSync17(templateDir)) {
23601
24996
  if (!file.endsWith(".yml") && !file.endsWith(".yaml")) continue;
23602
- const template = parseTemplateFile2(join49(templateDir, file));
24997
+ const template = parseTemplateFile2(join50(templateDir, file));
23603
24998
  if (template) templates.push(template);
23604
24999
  }
23605
25000
  return templates;
@@ -23608,7 +25003,7 @@ function getTemplateConfig(cwd) {
23608
25003
  const projectDir = cwd ?? getProjectRoot();
23609
25004
  const liveTemplates = parseIssueTemplates2(projectDir);
23610
25005
  if (liveTemplates.length > 0) return liveTemplates;
23611
- const cachePath = join49(getCleoDir(cwd), CACHE_FILE);
25006
+ const cachePath = join50(getCleoDir(cwd), CACHE_FILE);
23612
25007
  if (existsSync48(cachePath)) {
23613
25008
  try {
23614
25009
  const cached = JSON.parse(readFileSync35(cachePath, "utf-8"));
@@ -24418,7 +25813,7 @@ init_logger();
24418
25813
  // src/core/sharing/index.ts
24419
25814
  import { readFile as readFile10, writeFile as writeFile6 } from "node:fs/promises";
24420
25815
  import { existsSync as existsSync49, readdirSync as readdirSync18, statSync as statSync9 } from "node:fs";
24421
- import { join as join50, relative as relative3 } from "node:path";
25816
+ import { join as join51, relative as relative3 } from "node:path";
24422
25817
  init_paths();
24423
25818
  var GITIGNORE_START = "# CLEO:SHARING:START - Auto-managed by cleo sharing sync";
24424
25819
  var GITIGNORE_END = "# CLEO:SHARING:END";
@@ -24446,7 +25841,7 @@ function collectCleoFiles(cleoDir) {
24446
25841
  const entries = readdirSync18(dir);
24447
25842
  for (const entry of entries) {
24448
25843
  if (entry === ".git") continue;
24449
- const fullPath = join50(dir, entry);
25844
+ const fullPath = join51(dir, entry);
24450
25845
  const relPath = relative3(cleoDir, fullPath);
24451
25846
  try {
24452
25847
  const stat2 = statSync9(fullPath);
@@ -24506,7 +25901,7 @@ function generateGitignoreEntries(sharing) {
24506
25901
  async function syncGitignore(cwd) {
24507
25902
  const config = await loadConfig2(cwd);
24508
25903
  const projectRoot = getProjectRoot(cwd);
24509
- const gitignorePath = join50(projectRoot, ".gitignore");
25904
+ const gitignorePath = join51(projectRoot, ".gitignore");
24510
25905
  const entries = generateGitignoreEntries(config.sharing);
24511
25906
  const managedSection = [
24512
25907
  "",
@@ -24539,10 +25934,10 @@ async function syncGitignore(cwd) {
24539
25934
  // src/core/snapshot/index.ts
24540
25935
  init_data_accessor();
24541
25936
  init_paths();
24542
- import { createHash as createHash6 } from "node:crypto";
25937
+ import { createHash as createHash7 } from "node:crypto";
24543
25938
  import { readFile as readFile11, writeFile as writeFile7, mkdir as mkdir10 } from "node:fs/promises";
24544
25939
  import { existsSync as existsSync50 } from "node:fs";
24545
- import { join as join51, dirname as dirname13 } from "node:path";
25940
+ import { join as join52, dirname as dirname14 } from "node:path";
24546
25941
  var SNAPSHOT_FORMAT_VERSION = "1.0.0";
24547
25942
  function toSnapshotTask(task) {
24548
25943
  return {
@@ -24563,7 +25958,7 @@ function toSnapshotTask(task) {
24563
25958
  };
24564
25959
  }
24565
25960
  function computeChecksum2(tasks2) {
24566
- const hash = createHash6("sha256");
25961
+ const hash = createHash7("sha256");
24567
25962
  hash.update(JSON.stringify(tasks2));
24568
25963
  return hash.digest("hex").slice(0, 16);
24569
25964
  }
@@ -24595,7 +25990,7 @@ async function exportSnapshot(cwd) {
24595
25990
  };
24596
25991
  }
24597
25992
  async function writeSnapshot(snapshot, outputPath) {
24598
- const dir = dirname13(outputPath);
25993
+ const dir = dirname14(outputPath);
24599
25994
  if (!existsSync50(dir)) {
24600
25995
  await mkdir10(dir, { recursive: true });
24601
25996
  }
@@ -24612,7 +26007,7 @@ async function readSnapshot(inputPath) {
24612
26007
  function getDefaultSnapshotPath(cwd) {
24613
26008
  const cleoDir = getCleoDirAbsolute(cwd);
24614
26009
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
24615
- return join51(cleoDir, "snapshots", `snapshot-${timestamp}.json`);
26010
+ return join52(cleoDir, "snapshots", `snapshot-${timestamp}.json`);
24616
26011
  }
24617
26012
  async function importSnapshot(snapshot, cwd) {
24618
26013
  const accessor = await getAccessor(cwd);