@ouro.bot/cli 0.0.1-alpha.0 → 0.1.0-alpha.2

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 (119) hide show
  1. package/AdoptionSpecialist.ouro/agent.json +20 -0
  2. package/AdoptionSpecialist.ouro/psyche/SOUL.md +22 -0
  3. package/AdoptionSpecialist.ouro/psyche/identities/basilisk.md +31 -0
  4. package/AdoptionSpecialist.ouro/psyche/identities/jafar.md +31 -0
  5. package/AdoptionSpecialist.ouro/psyche/identities/jormungandr.md +31 -0
  6. package/AdoptionSpecialist.ouro/psyche/identities/kaa.md +31 -0
  7. package/AdoptionSpecialist.ouro/psyche/identities/medusa.md +31 -0
  8. package/AdoptionSpecialist.ouro/psyche/identities/monty.md +31 -0
  9. package/AdoptionSpecialist.ouro/psyche/identities/nagini.md +31 -0
  10. package/AdoptionSpecialist.ouro/psyche/identities/ouroboros.md +31 -0
  11. package/AdoptionSpecialist.ouro/psyche/identities/python.md +31 -0
  12. package/AdoptionSpecialist.ouro/psyche/identities/quetzalcoatl.md +31 -0
  13. package/AdoptionSpecialist.ouro/psyche/identities/sir-hiss.md +31 -0
  14. package/AdoptionSpecialist.ouro/psyche/identities/the-serpent.md +31 -0
  15. package/AdoptionSpecialist.ouro/psyche/identities/the-snake.md +31 -0
  16. package/README.md +224 -6
  17. package/dist/heart/agent-entry.js +17 -0
  18. package/dist/heart/api-error.js +34 -0
  19. package/dist/heart/config.js +296 -0
  20. package/dist/heart/core.js +515 -0
  21. package/dist/heart/daemon/daemon-cli.js +675 -0
  22. package/dist/heart/daemon/daemon-entry.js +74 -0
  23. package/dist/heart/daemon/daemon.js +313 -0
  24. package/dist/heart/daemon/hatch-flow.js +285 -0
  25. package/dist/heart/daemon/hatch-specialist.js +107 -0
  26. package/dist/heart/daemon/health-monitor.js +79 -0
  27. package/dist/heart/daemon/log-tailer.js +146 -0
  28. package/dist/heart/daemon/message-router.js +98 -0
  29. package/dist/heart/daemon/os-cron.js +260 -0
  30. package/dist/heart/daemon/ouro-bot-entry.js +23 -0
  31. package/dist/heart/daemon/ouro-bot-wrapper.js +90 -0
  32. package/dist/heart/daemon/ouro-entry.js +23 -0
  33. package/dist/heart/daemon/ouro-uti.js +212 -0
  34. package/dist/heart/daemon/process-manager.js +237 -0
  35. package/dist/heart/daemon/runtime-logging.js +98 -0
  36. package/dist/heart/daemon/subagent-installer.js +125 -0
  37. package/dist/heart/daemon/task-scheduler.js +240 -0
  38. package/dist/heart/harness.js +26 -0
  39. package/dist/heart/identity.js +281 -0
  40. package/dist/heart/kicks.js +144 -0
  41. package/dist/heart/primitives.js +4 -0
  42. package/dist/heart/providers/anthropic.js +329 -0
  43. package/dist/heart/providers/azure.js +66 -0
  44. package/dist/heart/providers/minimax.js +53 -0
  45. package/dist/heart/providers/openai-codex.js +162 -0
  46. package/dist/heart/streaming.js +412 -0
  47. package/dist/heart/turn-coordinator.js +62 -0
  48. package/dist/inner-worker-entry.js +4 -0
  49. package/dist/mind/associative-recall.js +197 -0
  50. package/dist/mind/bundle-manifest.js +118 -0
  51. package/dist/mind/context.js +302 -0
  52. package/dist/mind/first-impressions.js +43 -0
  53. package/dist/mind/format.js +56 -0
  54. package/dist/mind/friends/channel.js +41 -0
  55. package/dist/mind/friends/resolver.js +84 -0
  56. package/dist/mind/friends/store-file.js +171 -0
  57. package/dist/mind/friends/store.js +4 -0
  58. package/dist/mind/friends/tokens.js +26 -0
  59. package/dist/mind/friends/types.js +21 -0
  60. package/dist/mind/memory.js +388 -0
  61. package/dist/mind/pending.js +93 -0
  62. package/dist/mind/phrases.js +43 -0
  63. package/dist/mind/prompt-refresh.js +20 -0
  64. package/dist/mind/prompt.js +352 -0
  65. package/dist/mind/token-estimate.js +119 -0
  66. package/dist/nerves/cli-logging.js +31 -0
  67. package/dist/nerves/coverage/audit-rules.js +81 -0
  68. package/dist/nerves/coverage/audit.js +200 -0
  69. package/dist/nerves/coverage/cli-main.js +5 -0
  70. package/dist/nerves/coverage/cli.js +51 -0
  71. package/dist/nerves/coverage/contract.js +23 -0
  72. package/dist/nerves/coverage/file-completeness.js +56 -0
  73. package/dist/nerves/coverage/run-artifacts.js +77 -0
  74. package/dist/nerves/coverage/source-scanner.js +34 -0
  75. package/dist/nerves/index.js +152 -0
  76. package/dist/nerves/runtime.js +38 -0
  77. package/dist/repertoire/ado-client.js +211 -0
  78. package/dist/repertoire/ado-context.js +73 -0
  79. package/dist/repertoire/ado-semantic.js +841 -0
  80. package/dist/repertoire/ado-templates.js +146 -0
  81. package/dist/repertoire/coding/index.js +36 -0
  82. package/dist/repertoire/coding/manager.js +489 -0
  83. package/dist/repertoire/coding/monitor.js +60 -0
  84. package/dist/repertoire/coding/reporter.js +45 -0
  85. package/dist/repertoire/coding/spawner.js +102 -0
  86. package/dist/repertoire/coding/tools.js +167 -0
  87. package/dist/repertoire/coding/types.js +2 -0
  88. package/dist/repertoire/data/ado-endpoints.json +122 -0
  89. package/dist/repertoire/data/graph-endpoints.json +212 -0
  90. package/dist/repertoire/github-client.js +64 -0
  91. package/dist/repertoire/graph-client.js +118 -0
  92. package/dist/repertoire/skills.js +156 -0
  93. package/dist/repertoire/tasks/board.js +122 -0
  94. package/dist/repertoire/tasks/index.js +210 -0
  95. package/dist/repertoire/tasks/lifecycle.js +80 -0
  96. package/dist/repertoire/tasks/middleware.js +65 -0
  97. package/dist/repertoire/tasks/parser.js +173 -0
  98. package/dist/repertoire/tasks/scanner.js +132 -0
  99. package/dist/repertoire/tasks/transitions.js +145 -0
  100. package/dist/repertoire/tasks/types.js +2 -0
  101. package/dist/repertoire/tools-base.js +714 -0
  102. package/dist/repertoire/tools-github.js +53 -0
  103. package/dist/repertoire/tools-teams.js +308 -0
  104. package/dist/repertoire/tools.js +199 -0
  105. package/dist/senses/cli-entry.js +15 -0
  106. package/dist/senses/cli.js +604 -0
  107. package/dist/senses/commands.js +98 -0
  108. package/dist/senses/inner-dialog-worker.js +61 -0
  109. package/dist/senses/inner-dialog.js +231 -0
  110. package/dist/senses/session-lock.js +119 -0
  111. package/dist/senses/teams-entry.js +15 -0
  112. package/dist/senses/teams.js +696 -0
  113. package/dist/senses/trust-gate.js +150 -0
  114. package/package.json +34 -11
  115. package/subagents/README.md +73 -0
  116. package/subagents/work-doer.md +233 -0
  117. package/subagents/work-merger.md +624 -0
  118. package/subagents/work-planner.md +373 -0
  119. package/bin/ouro.js +0 -6
@@ -0,0 +1,210 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.getTaskModule = getTaskModule;
37
+ exports.resetTaskModule = resetTaskModule;
38
+ const fs = __importStar(require("fs"));
39
+ const path = __importStar(require("path"));
40
+ const runtime_1 = require("../../nerves/runtime");
41
+ const board_1 = require("./board");
42
+ const lifecycle_1 = require("./lifecycle");
43
+ const parser_1 = require("./parser");
44
+ const scanner_1 = require("./scanner");
45
+ const middleware_1 = require("./middleware");
46
+ const transitions_1 = require("./transitions");
47
+ function formatDate(now = new Date()) {
48
+ return now.toISOString().slice(0, 10);
49
+ }
50
+ function formatStemTimestamp(now = new Date()) {
51
+ const year = now.getFullYear();
52
+ const month = String(now.getMonth() + 1).padStart(2, "0");
53
+ const day = String(now.getDate()).padStart(2, "0");
54
+ const hours = String(now.getHours()).padStart(2, "0");
55
+ const minutes = String(now.getMinutes()).padStart(2, "0");
56
+ return `${year}-${month}-${day}-${hours}${minutes}`;
57
+ }
58
+ function slugify(input) {
59
+ return input
60
+ .toLowerCase()
61
+ .replace(/[^a-z0-9]+/g, "-")
62
+ .replace(/^-+/, "")
63
+ .replace(/-+$/, "")
64
+ .slice(0, 64);
65
+ }
66
+ function findTask(index, nameOrStem) {
67
+ return (index.tasks.find((task) => task.stem === nameOrStem || task.name === nameOrStem) ??
68
+ index.tasks.find((task) => task.stem.endsWith(nameOrStem)) ??
69
+ null);
70
+ }
71
+ function removeRuntimeFrontmatter(frontmatter) {
72
+ const { _isCanonicalFilename, ...clean } = frontmatter;
73
+ return clean;
74
+ }
75
+ class FileTaskModule {
76
+ scan() {
77
+ return (0, scanner_1.scanTasks)((0, scanner_1.getTaskRoot)());
78
+ }
79
+ getBoard() {
80
+ return (0, board_1.buildTaskBoard)(this.scan());
81
+ }
82
+ getTask(name) {
83
+ return findTask(this.scan(), name);
84
+ }
85
+ createTask(input) {
86
+ (0, runtime_1.emitNervesEvent)({
87
+ event: "mind.step_start",
88
+ component: "mind",
89
+ message: "creating task file",
90
+ meta: { type: input.type },
91
+ });
92
+ const type = (0, transitions_1.normalizeTaskType)(input.type);
93
+ if (!type) {
94
+ throw new Error(`invalid task type: ${input.type}`);
95
+ }
96
+ const status = (0, transitions_1.normalizeTaskStatus)(input.status ?? "drafting");
97
+ if (!status) {
98
+ throw new Error(`invalid task status: ${String(input.status)}`);
99
+ }
100
+ const collection = (0, transitions_1.canonicalCollectionForTaskType)(type);
101
+ const stem = `${formatStemTimestamp()}-${slugify(input.title) || "task"}`;
102
+ const filename = `${stem}.md`;
103
+ const root = (0, scanner_1.getTaskRoot)();
104
+ const filePath = path.join(root, collection, filename);
105
+ const today = formatDate();
106
+ const frontmatter = {
107
+ type,
108
+ category: input.category || "infrastructure",
109
+ title: input.title,
110
+ status,
111
+ validator: input.validator ?? null,
112
+ requester: input.requester ?? "agent",
113
+ cadence: input.cadence ?? null,
114
+ scheduledAt: input.scheduledAt ?? null,
115
+ lastRun: input.lastRun ?? null,
116
+ created: today,
117
+ updated: today,
118
+ child_tasks: [],
119
+ artifacts: [],
120
+ };
121
+ if (type === "one-shot") {
122
+ frontmatter.parent_task = null;
123
+ frontmatter.depends_on = [];
124
+ }
125
+ const content = (0, parser_1.renderTaskFile)(frontmatter, input.body);
126
+ const validation = (0, middleware_1.validateWrite)(filePath, content);
127
+ if (!validation.ok) {
128
+ throw new Error(validation.reason ?? "task write validation failed");
129
+ }
130
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
131
+ fs.writeFileSync(filePath, content, "utf-8");
132
+ (0, scanner_1.clearTaskScanCache)();
133
+ return filePath;
134
+ }
135
+ updateStatus(name, toStatus) {
136
+ const normalized = (0, transitions_1.normalizeTaskStatus)(toStatus);
137
+ if (!normalized) {
138
+ return { ok: false, from: "drafting", to: "drafting", reason: `invalid target status: ${toStatus}` };
139
+ }
140
+ const index = this.scan();
141
+ const task = findTask(index, name);
142
+ if (!task) {
143
+ return { ok: false, from: "drafting", to: normalized, reason: `task not found: ${name}` };
144
+ }
145
+ const gate = (0, middleware_1.validateStatusTransition)(task, normalized);
146
+ if (!gate.ok) {
147
+ return { ok: false, from: task.status, to: normalized, reason: gate.reason };
148
+ }
149
+ const content = fs.readFileSync(task.path, "utf-8");
150
+ const parsed = (0, parser_1.parseTaskFile)(content, task.path);
151
+ const frontmatter = removeRuntimeFrontmatter(parsed.frontmatter);
152
+ frontmatter.status = normalized;
153
+ frontmatter.updated = formatDate();
154
+ fs.writeFileSync(task.path, (0, parser_1.renderTaskFile)(frontmatter, parsed.body), "utf-8");
155
+ (0, scanner_1.clearTaskScanCache)();
156
+ const transition = { ok: true, from: task.status, to: normalized };
157
+ const afterIndex = this.scan();
158
+ const archive = (0, lifecycle_1.archiveCompletedTasks)(afterIndex);
159
+ if (archive.archived.length > 0 || archive.failures.length > 0) {
160
+ (0, scanner_1.clearTaskScanCache)();
161
+ }
162
+ return {
163
+ ...transition,
164
+ path: task.path,
165
+ archived: archive.archived,
166
+ };
167
+ }
168
+ validateWrite(filePath, content) {
169
+ return (0, middleware_1.validateWrite)(filePath, content);
170
+ }
171
+ validateTransition(from, to) {
172
+ return (0, transitions_1.validateTransition)(from, to);
173
+ }
174
+ validateSpawn(taskName, spawnType) {
175
+ const task = this.getTask(taskName);
176
+ if (!task) {
177
+ return { ok: false, reason: `task not found: ${taskName}` };
178
+ }
179
+ return (0, middleware_1.validateSpawn)(task, spawnType);
180
+ }
181
+ detectStale(thresholdDays) {
182
+ return (0, lifecycle_1.detectStaleTasks)(this.scan(), thresholdDays);
183
+ }
184
+ boardStatus(status) {
185
+ const normalized = (0, transitions_1.normalizeTaskStatus)(status);
186
+ if (!normalized)
187
+ return [];
188
+ return (0, board_1.boardStatus)(this.getBoard(), normalized);
189
+ }
190
+ boardAction() {
191
+ return (0, board_1.boardAction)(this.getBoard());
192
+ }
193
+ boardDeps() {
194
+ return (0, board_1.boardDeps)(this.getBoard());
195
+ }
196
+ boardSessions() {
197
+ return (0, board_1.boardSessions)(this.getBoard());
198
+ }
199
+ }
200
+ let taskModule = null;
201
+ function getTaskModule() {
202
+ if (!taskModule) {
203
+ taskModule = new FileTaskModule();
204
+ }
205
+ return taskModule;
206
+ }
207
+ function resetTaskModule() {
208
+ taskModule = null;
209
+ (0, scanner_1.clearTaskScanCache)();
210
+ }
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.archiveCompletedTasks = archiveCompletedTasks;
37
+ exports.detectStaleTasks = detectStaleTasks;
38
+ const fs = __importStar(require("fs"));
39
+ const path = __importStar(require("path"));
40
+ const runtime_1 = require("../../nerves/runtime");
41
+ function archiveCompletedTasks(index) {
42
+ (0, runtime_1.emitNervesEvent)({
43
+ event: "mind.step_start",
44
+ component: "mind",
45
+ message: "archiving completed tasks",
46
+ meta: { root: index.root },
47
+ });
48
+ const archived = [];
49
+ const failures = [];
50
+ for (const task of index.tasks) {
51
+ if (task.status !== "done")
52
+ continue;
53
+ const archiveDir = path.join(index.root, "archive", task.collection);
54
+ const archiveFile = path.join(archiveDir, task.name);
55
+ try {
56
+ fs.mkdirSync(archiveDir, { recursive: true });
57
+ fs.renameSync(task.path, archiveFile);
58
+ const taskArtifactDir = task.path.replace(/\.md$/i, "");
59
+ if (fs.existsSync(taskArtifactDir)) {
60
+ fs.renameSync(taskArtifactDir, path.join(archiveDir, path.basename(taskArtifactDir)));
61
+ }
62
+ archived.push(archiveFile);
63
+ }
64
+ catch (error) {
65
+ failures.push(`${task.path}: ${error instanceof Error ? error.message : String(error)}`);
66
+ }
67
+ }
68
+ return { archived, failures };
69
+ }
70
+ function detectStaleTasks(index, thresholdDays, now = new Date()) {
71
+ const staleCutoffMs = now.getTime() - thresholdDays * 24 * 60 * 60 * 1000;
72
+ return index.tasks.filter((task) => {
73
+ const updated = Date.parse(task.updated);
74
+ if (Number.isNaN(updated))
75
+ return false;
76
+ if (task.status === "done")
77
+ return false;
78
+ return updated < staleCutoffMs;
79
+ });
80
+ }
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateTemplate = validateTemplate;
4
+ exports.validateWrite = validateWrite;
5
+ exports.validateSpawn = validateSpawn;
6
+ exports.validateStatusTransition = validateStatusTransition;
7
+ const runtime_1 = require("../../nerves/runtime");
8
+ const parser_1 = require("./parser");
9
+ const transitions_1 = require("./transitions");
10
+ function validateTemplate(task) {
11
+ const required = transitions_1.TASK_REQUIRED_TEMPLATE_FIELDS[task.type];
12
+ const missing = required.filter((field) => !(field in task.frontmatter));
13
+ if (missing.length > 0) {
14
+ return { ok: false, reason: "missing required fields", missingFields: missing };
15
+ }
16
+ return { ok: true };
17
+ }
18
+ function validateWrite(filePath, content) {
19
+ (0, runtime_1.emitNervesEvent)({
20
+ event: "mind.step_start",
21
+ component: "mind",
22
+ message: "validating task write",
23
+ meta: { filePath },
24
+ });
25
+ const base = filePath.split(/[/\\]/).pop() ?? "";
26
+ if (!(0, transitions_1.isCanonicalTaskFilename)(base)) {
27
+ return { ok: false, reason: "non-canonical filename" };
28
+ }
29
+ try {
30
+ const parsed = (0, parser_1.parseTaskFile)(content, filePath);
31
+ return validateTemplate(parsed);
32
+ }
33
+ catch (error) {
34
+ return {
35
+ ok: false,
36
+ reason: error instanceof Error ? error.message : String(error),
37
+ };
38
+ }
39
+ }
40
+ function validateSpawn(task, spawnType) {
41
+ if (task.status === "done") {
42
+ return { ok: false, reason: "spawn-completed-path" };
43
+ }
44
+ const pipelineStage = String(task.frontmatter.pipeline_stage ?? "");
45
+ if (task.status === "drafting" && pipelineStage && pipelineStage !== "quality-gates") {
46
+ return { ok: false, reason: "spawn-coding-pipeline-stage" };
47
+ }
48
+ if (spawnType === "coding") {
49
+ if (task.status !== "processing" && task.status !== "collaborating") {
50
+ return { ok: false, reason: "spawn-coding-task-status" };
51
+ }
52
+ const hasScope = /(^|\n)##\s*scope\b/i.test(task.body);
53
+ if (!hasScope) {
54
+ return { ok: false, reason: "spawn-coding-scope-missing" };
55
+ }
56
+ }
57
+ return { ok: true };
58
+ }
59
+ function validateStatusTransition(from, toStatus) {
60
+ const transition = (0, transitions_1.validateTransition)(from.status, toStatus);
61
+ if (!transition.ok) {
62
+ return { ok: false, reason: transition.reason };
63
+ }
64
+ return { ok: true };
65
+ }
@@ -0,0 +1,173 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.parseFrontmatter = parseFrontmatter;
37
+ exports.parseTaskFile = parseTaskFile;
38
+ exports.renderTaskFile = renderTaskFile;
39
+ const path = __importStar(require("path"));
40
+ const runtime_1 = require("../../nerves/runtime");
41
+ const transitions_1 = require("./transitions");
42
+ function parseScalar(raw) {
43
+ const value = raw.trim();
44
+ if (value === "null")
45
+ return null;
46
+ if (value === "[]")
47
+ return [];
48
+ if ((value.startsWith("\"") && value.endsWith("\"")) || (value.startsWith("'") && value.endsWith("'"))) {
49
+ return value.slice(1, -1);
50
+ }
51
+ return value;
52
+ }
53
+ function parseFrontmatter(raw) {
54
+ const frontmatter = {};
55
+ const lines = raw.split(/\r?\n/);
56
+ for (let idx = 0; idx < lines.length; idx += 1) {
57
+ const line = lines[idx];
58
+ if (!line.trim())
59
+ continue;
60
+ const match = /^([A-Za-z0-9_:-]+):\s*(.*)$/.exec(line);
61
+ if (!match)
62
+ continue;
63
+ const key = match[1];
64
+ const inline = match[2];
65
+ if (inline.length > 0) {
66
+ frontmatter[key] = parseScalar(inline);
67
+ continue;
68
+ }
69
+ const items = [];
70
+ let cursor = idx + 1;
71
+ while (cursor < lines.length && /^\s*-\s+/.test(lines[cursor])) {
72
+ items.push(parseScalar(lines[cursor].replace(/^\s*-\s+/, "")));
73
+ cursor += 1;
74
+ }
75
+ frontmatter[key] = items;
76
+ idx = cursor - 1;
77
+ }
78
+ return frontmatter;
79
+ }
80
+ function parseTaskBody(content) {
81
+ const lines = content.split(/\r?\n/);
82
+ if (lines[0]?.trim() !== "---") {
83
+ throw new Error("task file missing frontmatter");
84
+ }
85
+ const closing = lines.findIndex((line, index) => index > 0 && line.trim() === "---");
86
+ if (closing === -1) {
87
+ throw new Error("task file has unterminated frontmatter");
88
+ }
89
+ const rawFrontmatter = lines.slice(1, closing).join("\n");
90
+ const body = lines.slice(closing + 1).join("\n").trim();
91
+ return { frontmatter: parseFrontmatter(rawFrontmatter), body };
92
+ }
93
+ function collectionFromPath(taskPath, type) {
94
+ const parts = taskPath.split(path.sep);
95
+ if (parts.includes("one-shots"))
96
+ return "one-shots";
97
+ if (parts.includes("ongoing"))
98
+ return "ongoing";
99
+ if (parts.includes("habits"))
100
+ return "habits";
101
+ return (0, transitions_1.canonicalCollectionForTaskType)(type);
102
+ }
103
+ function parseTaskFile(content, filePath) {
104
+ (0, runtime_1.emitNervesEvent)({
105
+ event: "mind.step_start",
106
+ component: "mind",
107
+ message: "parsing task file",
108
+ meta: { filePath },
109
+ });
110
+ const parsed = parseTaskBody(content);
111
+ const name = path.basename(filePath);
112
+ const stem = name.replace(/\.md$/i, "");
113
+ const type = (0, transitions_1.normalizeTaskType)(parsed.frontmatter.type);
114
+ const status = (0, transitions_1.normalizeTaskStatus)(parsed.frontmatter.status);
115
+ if (!type) {
116
+ throw new Error(`task file has invalid type: ${filePath}`);
117
+ }
118
+ if (!status) {
119
+ throw new Error(`task file has invalid status: ${filePath}`);
120
+ }
121
+ const title = String(parsed.frontmatter.title ?? stem);
122
+ const category = String(parsed.frontmatter.category ?? "infrastructure");
123
+ const created = String(parsed.frontmatter.created ?? "");
124
+ const updated = String(parsed.frontmatter.updated ?? created);
125
+ return {
126
+ path: filePath,
127
+ name,
128
+ stem,
129
+ type,
130
+ collection: collectionFromPath(filePath, type),
131
+ category,
132
+ title,
133
+ status,
134
+ created,
135
+ updated,
136
+ frontmatter: {
137
+ ...parsed.frontmatter,
138
+ _isCanonicalFilename: (0, transitions_1.isCanonicalTaskFilename)(name),
139
+ },
140
+ body: parsed.body,
141
+ };
142
+ }
143
+ function formatFrontmatterValue(value) {
144
+ if (Array.isArray(value)) {
145
+ if (value.length === 0)
146
+ return ["[]"];
147
+ return ["", ...value.map((entry) => `- ${String(entry)}`)];
148
+ }
149
+ if (value === null)
150
+ return ["null"];
151
+ return [String(value)];
152
+ }
153
+ function renderTaskFile(frontmatter, body) {
154
+ const keys = Object.keys(frontmatter);
155
+ const lines = ["---"];
156
+ for (const key of keys) {
157
+ const rendered = formatFrontmatterValue(frontmatter[key]);
158
+ if (rendered.length === 1) {
159
+ lines.push(`${key}: ${rendered[0]}`);
160
+ }
161
+ else {
162
+ lines.push(`${key}:`);
163
+ for (const entry of rendered.slice(1)) {
164
+ lines.push(entry);
165
+ }
166
+ }
167
+ }
168
+ lines.push("---");
169
+ lines.push("");
170
+ lines.push(body.trim());
171
+ lines.push("");
172
+ return lines.join("\n");
173
+ }
@@ -0,0 +1,132 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.getTaskRoot = getTaskRoot;
37
+ exports.ensureTaskLayout = ensureTaskLayout;
38
+ exports.clearTaskScanCache = clearTaskScanCache;
39
+ exports.scanTasks = scanTasks;
40
+ const fs = __importStar(require("fs"));
41
+ const path = __importStar(require("path"));
42
+ const identity_1 = require("../../heart/identity");
43
+ const runtime_1 = require("../../nerves/runtime");
44
+ const transitions_1 = require("./transitions");
45
+ const parser_1 = require("./parser");
46
+ let scanCache = null;
47
+ function getTaskRoot() {
48
+ return path.join((0, identity_1.getAgentRoot)(), "tasks");
49
+ }
50
+ function ensureTaskLayout(root = getTaskRoot()) {
51
+ const dirs = [
52
+ root,
53
+ ...transitions_1.TASK_CANONICAL_COLLECTIONS.map((collection) => path.join(root, collection)),
54
+ path.join(root, "templates"),
55
+ path.join(root, ".trash"),
56
+ path.join(root, "archive"),
57
+ ];
58
+ for (const dir of dirs) {
59
+ fs.mkdirSync(dir, { recursive: true });
60
+ }
61
+ }
62
+ function walkMarkdownFiles(dir, acc) {
63
+ if (!fs.existsSync(dir))
64
+ return;
65
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
66
+ for (const entry of entries) {
67
+ if (entry.isDirectory()) {
68
+ if (transitions_1.TASK_RESERVED_DIRECTORIES.includes(entry.name)) {
69
+ continue;
70
+ }
71
+ walkMarkdownFiles(path.join(dir, entry.name), acc);
72
+ continue;
73
+ }
74
+ if (entry.name.endsWith(".md")) {
75
+ acc.push(path.join(dir, entry.name));
76
+ }
77
+ }
78
+ }
79
+ function buildFingerprint(paths) {
80
+ const segments = paths
81
+ .map((filePath) => {
82
+ const stat = fs.statSync(filePath);
83
+ return `${filePath}:${stat.mtimeMs}:${stat.size}`;
84
+ })
85
+ .sort();
86
+ return segments.join("|");
87
+ }
88
+ function clearTaskScanCache() {
89
+ scanCache = null;
90
+ }
91
+ function scanTasks(root = getTaskRoot()) {
92
+ (0, runtime_1.emitNervesEvent)({
93
+ event: "mind.step_start",
94
+ component: "mind",
95
+ message: "scanning task files",
96
+ meta: { root },
97
+ });
98
+ ensureTaskLayout(root);
99
+ const files = [];
100
+ for (const collection of transitions_1.TASK_CANONICAL_COLLECTIONS) {
101
+ walkMarkdownFiles(path.join(root, collection), files);
102
+ }
103
+ const fingerprint = buildFingerprint(files);
104
+ if (scanCache && scanCache.fingerprint === fingerprint) {
105
+ return scanCache.index;
106
+ }
107
+ const tasks = [];
108
+ const parseErrors = [];
109
+ const invalidFilenames = [];
110
+ for (const filePath of files) {
111
+ const base = path.basename(filePath);
112
+ if (!(0, transitions_1.isCanonicalTaskFilename)(base)) {
113
+ invalidFilenames.push(filePath);
114
+ }
115
+ try {
116
+ const content = fs.readFileSync(filePath, "utf-8");
117
+ tasks.push((0, parser_1.parseTaskFile)(content, filePath));
118
+ }
119
+ catch (error) {
120
+ parseErrors.push(`${filePath}: ${error instanceof Error ? error.message : String(error)}`);
121
+ }
122
+ }
123
+ const index = {
124
+ root,
125
+ tasks,
126
+ invalidFilenames,
127
+ parseErrors,
128
+ fingerprint,
129
+ };
130
+ scanCache = { fingerprint, index };
131
+ return index;
132
+ }