@ouro.bot/cli 0.1.0-alpha.184 → 0.1.0-alpha.186
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/changelog.json +19 -2
- package/dist/heart/active-work.js +19 -10
- package/dist/heart/agent-relationships.js +161 -0
- package/dist/heart/cares.js +174 -0
- package/dist/heart/daemon/daemon-cli.js +48 -16
- package/dist/heart/daemon/hatch-flow.js +1 -1
- package/dist/heart/daemon/hatch-specialist.js +3 -3
- package/dist/heart/daemon/outlook-read.js +40 -0
- package/dist/heart/daemon/specialist-prompt.js +2 -2
- package/dist/heart/intentions.js +168 -0
- package/dist/heart/obligations.js +23 -0
- package/dist/heart/presence.js +185 -0
- package/dist/heart/tempo.js +93 -0
- package/dist/heart/temporal-view.js +41 -0
- package/dist/heart/wake-packet.js +226 -0
- package/dist/mind/episodes.js +116 -0
- package/dist/mind/prompt.js +10 -1
- package/dist/repertoire/coding/context-pack.js +25 -2
- package/dist/repertoire/tools-base.js +240 -0
- package/dist/senses/cli.js +3 -1
- package/dist/senses/pipeline.js +88 -0
- package/package.json +2 -2
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/agent.json +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/SOUL.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildWakePacket = buildWakePacket;
|
|
4
|
+
exports.renderWakePacket = renderWakePacket;
|
|
5
|
+
exports.renderCompactWakePacket = renderCompactWakePacket;
|
|
6
|
+
const runtime_1 = require("../nerves/runtime");
|
|
7
|
+
const tempo_1 = require("./tempo");
|
|
8
|
+
function estimateTokens(text) {
|
|
9
|
+
return Math.ceil(text.length / 4);
|
|
10
|
+
}
|
|
11
|
+
// --- Section builders (pure derivation from authored data, no embellishment) ---
|
|
12
|
+
function buildPlotLine(episodes, tempo) {
|
|
13
|
+
if (episodes.length === 0)
|
|
14
|
+
return "";
|
|
15
|
+
const limit = tempo === "crisis" ? 3 : tempo === "brief" ? 2 : 5;
|
|
16
|
+
const selected = episodes.slice(0, limit);
|
|
17
|
+
const lines = selected.map((ep) => {
|
|
18
|
+
const parts = [`- ${ep.summary}`];
|
|
19
|
+
if (ep.whyItMattered && tempo !== "brief") {
|
|
20
|
+
parts[0] += ` (${ep.whyItMattered})`;
|
|
21
|
+
}
|
|
22
|
+
return parts[0];
|
|
23
|
+
});
|
|
24
|
+
return lines.join("\n");
|
|
25
|
+
}
|
|
26
|
+
function buildObligationsSection(obligations) {
|
|
27
|
+
if (obligations.length === 0)
|
|
28
|
+
return "";
|
|
29
|
+
return obligations
|
|
30
|
+
.map((ob) => {
|
|
31
|
+
const parts = [`- ${ob.content}`];
|
|
32
|
+
if (ob.meaning?.resumeHint) {
|
|
33
|
+
parts.push(` [hint: ${ob.meaning.resumeHint}]`);
|
|
34
|
+
}
|
|
35
|
+
if (ob.meaning?.stalenessClass && ob.meaning.stalenessClass !== "fresh") {
|
|
36
|
+
parts.push(` (${ob.meaning.stalenessClass})`);
|
|
37
|
+
}
|
|
38
|
+
if (ob.meaning?.waitingOn) {
|
|
39
|
+
parts.push(` waiting on ${ob.meaning.waitingOn.kind}: ${ob.meaning.waitingOn.target}`);
|
|
40
|
+
}
|
|
41
|
+
return parts.join("");
|
|
42
|
+
})
|
|
43
|
+
.join("\n");
|
|
44
|
+
}
|
|
45
|
+
function buildCaresSection(cares) {
|
|
46
|
+
if (cares.length === 0)
|
|
47
|
+
return "";
|
|
48
|
+
return cares
|
|
49
|
+
.map((c) => {
|
|
50
|
+
const parts = [`- ${c.label}`];
|
|
51
|
+
if (c.salience !== "low") {
|
|
52
|
+
parts.push(` [${c.salience}]`);
|
|
53
|
+
}
|
|
54
|
+
if (c.currentRisk) {
|
|
55
|
+
parts.push(` risk: ${c.currentRisk}`);
|
|
56
|
+
}
|
|
57
|
+
return parts.join("");
|
|
58
|
+
})
|
|
59
|
+
.join("\n");
|
|
60
|
+
}
|
|
61
|
+
function buildPresenceSection(peers) {
|
|
62
|
+
if (peers.length === 0)
|
|
63
|
+
return "";
|
|
64
|
+
return peers
|
|
65
|
+
.map((p) => `- ${p.agentName}: ${p.availability}/${p.lane}`)
|
|
66
|
+
.join("\n");
|
|
67
|
+
}
|
|
68
|
+
function buildResumeHint(view) {
|
|
69
|
+
// Compose from authored obligation resumeHints and top intentions
|
|
70
|
+
const hints = [];
|
|
71
|
+
for (const ob of view.activeObligations) {
|
|
72
|
+
if (ob.meaning?.resumeHint) {
|
|
73
|
+
hints.push(ob.meaning.resumeHint);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
for (const intent of view.openIntentions.slice(0, 3)) {
|
|
77
|
+
hints.push(intent.content);
|
|
78
|
+
}
|
|
79
|
+
if (hints.length === 0) {
|
|
80
|
+
// Fall back to top obligation content
|
|
81
|
+
if (view.activeObligations.length > 0) {
|
|
82
|
+
hints.push(view.activeObligations[0].content);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
if (hints.length === 0)
|
|
86
|
+
return "";
|
|
87
|
+
return hints.join("; ");
|
|
88
|
+
}
|
|
89
|
+
function buildWakePacket(view) {
|
|
90
|
+
const tempo = view.tempo;
|
|
91
|
+
const tokenBudget = tempo_1.TEMPO_BUDGETS[tempo];
|
|
92
|
+
const packet = {
|
|
93
|
+
plotLine: buildPlotLine(view.recentEpisodes, tempo),
|
|
94
|
+
obligations: buildObligationsSection(view.activeObligations),
|
|
95
|
+
cares: buildCaresSection(view.activeCares),
|
|
96
|
+
presence: buildPresenceSection(view.peerPresence),
|
|
97
|
+
resumeHint: buildResumeHint(view),
|
|
98
|
+
tempo,
|
|
99
|
+
tokenBudget,
|
|
100
|
+
assembledAt: new Date().toISOString(),
|
|
101
|
+
};
|
|
102
|
+
(0, runtime_1.emitNervesEvent)({
|
|
103
|
+
component: "heart",
|
|
104
|
+
event: "heart.wake_packet_built",
|
|
105
|
+
message: `wake packet built: tempo=${tempo}`,
|
|
106
|
+
meta: {
|
|
107
|
+
tempo,
|
|
108
|
+
plotLineTokens: estimateTokens(packet.plotLine),
|
|
109
|
+
obligationsTokens: estimateTokens(packet.obligations),
|
|
110
|
+
caresTokens: estimateTokens(packet.cares),
|
|
111
|
+
presenceTokens: estimateTokens(packet.presence),
|
|
112
|
+
resumeHintTokens: estimateTokens(packet.resumeHint),
|
|
113
|
+
},
|
|
114
|
+
});
|
|
115
|
+
return packet;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Renders a wake packet to prompt text, respecting token budget.
|
|
119
|
+
* Truncation priority (last truncated first):
|
|
120
|
+
* resumeHint (PROTECTED) > obligations > cares > plotLine > presence
|
|
121
|
+
* So presence is truncated first, then plotLine, then cares, then obligations.
|
|
122
|
+
* resumeHint is never truncated.
|
|
123
|
+
*/
|
|
124
|
+
function renderWakePacket(packet) {
|
|
125
|
+
const budget = packet.tokenBudget;
|
|
126
|
+
// Assemble sections in priority order (highest priority first for budget allocation)
|
|
127
|
+
// Each section is { label, content, priority } where lower priority number = truncated first
|
|
128
|
+
const sections = [
|
|
129
|
+
{ label: "resume", content: packet.resumeHint, priority: 5 },
|
|
130
|
+
{ label: "obligations", content: packet.obligations, priority: 4 },
|
|
131
|
+
{ label: "cares", content: packet.cares, priority: 3 },
|
|
132
|
+
{ label: "plot", content: packet.plotLine, priority: 2 },
|
|
133
|
+
{ label: "presence", content: packet.presence, priority: 1 },
|
|
134
|
+
].filter((s) => s.content.length > 0);
|
|
135
|
+
if (sections.length === 0) {
|
|
136
|
+
(0, runtime_1.emitNervesEvent)({
|
|
137
|
+
component: "heart",
|
|
138
|
+
event: "heart.wake_packet_rendered",
|
|
139
|
+
message: "wake packet rendered: empty",
|
|
140
|
+
meta: { tokens: 0, tempo: packet.tempo },
|
|
141
|
+
});
|
|
142
|
+
return "";
|
|
143
|
+
}
|
|
144
|
+
// Build the rendered output, truncating lower-priority sections first
|
|
145
|
+
let rendered = formatSections(sections);
|
|
146
|
+
let tokens = estimateTokens(rendered);
|
|
147
|
+
// Truncate sections from lowest priority until we fit budget
|
|
148
|
+
const sortedByPriority = [...sections].sort((a, b) => a.priority - b.priority);
|
|
149
|
+
for (const section of sortedByPriority) {
|
|
150
|
+
if (tokens <= budget.max)
|
|
151
|
+
break;
|
|
152
|
+
// Skip resumeHint — it's PROTECTED
|
|
153
|
+
if (section.label === "resume")
|
|
154
|
+
continue;
|
|
155
|
+
// Remove this section entirely
|
|
156
|
+
const idx = sections.findIndex((s) => s.label === section.label);
|
|
157
|
+
sections.splice(idx, 1);
|
|
158
|
+
rendered = formatSections(sections);
|
|
159
|
+
tokens = estimateTokens(rendered);
|
|
160
|
+
}
|
|
161
|
+
// If still over budget after removing all non-protected sections, trim what's left
|
|
162
|
+
if (tokens > budget.max) {
|
|
163
|
+
const maxChars = budget.max * 4;
|
|
164
|
+
rendered = rendered.slice(0, maxChars);
|
|
165
|
+
}
|
|
166
|
+
(0, runtime_1.emitNervesEvent)({
|
|
167
|
+
component: "heart",
|
|
168
|
+
event: "heart.wake_packet_rendered",
|
|
169
|
+
message: `wake packet rendered: ${tokens} tokens`,
|
|
170
|
+
meta: { tokens, tempo: packet.tempo, sectionCount: sections.length },
|
|
171
|
+
});
|
|
172
|
+
return rendered;
|
|
173
|
+
}
|
|
174
|
+
function formatSections(sections) {
|
|
175
|
+
const parts = [];
|
|
176
|
+
for (const section of sections) {
|
|
177
|
+
switch (section.label) {
|
|
178
|
+
case "resume":
|
|
179
|
+
parts.push(`**Next:** ${section.content}`);
|
|
180
|
+
break;
|
|
181
|
+
case "obligations":
|
|
182
|
+
parts.push(`**Owed:**\n${section.content}`);
|
|
183
|
+
break;
|
|
184
|
+
case "cares":
|
|
185
|
+
parts.push(`**Cares:**\n${section.content}`);
|
|
186
|
+
break;
|
|
187
|
+
case "plot":
|
|
188
|
+
parts.push(`**Recent:**\n${section.content}`);
|
|
189
|
+
break;
|
|
190
|
+
case "presence":
|
|
191
|
+
parts.push(`**Peers:**\n${section.content}`);
|
|
192
|
+
break;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return parts.join("\n\n");
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Ultra-compact version for coding context (max 200 tokens).
|
|
199
|
+
* Just resumeHint + top obligation + top care, single-line bullets.
|
|
200
|
+
*/
|
|
201
|
+
function renderCompactWakePacket(packet) {
|
|
202
|
+
const parts = [];
|
|
203
|
+
if (packet.resumeHint) {
|
|
204
|
+
parts.push(`next: ${packet.resumeHint}`);
|
|
205
|
+
}
|
|
206
|
+
if (packet.obligations) {
|
|
207
|
+
// Just first line of obligations
|
|
208
|
+
const firstOb = packet.obligations.split("\n")[0];
|
|
209
|
+
parts.push(`owed: ${firstOb.replace(/^- /, "")}`);
|
|
210
|
+
}
|
|
211
|
+
if (packet.cares) {
|
|
212
|
+
const firstCare = packet.cares.split("\n")[0];
|
|
213
|
+
parts.push(`care: ${firstCare.replace(/^- /, "")}`);
|
|
214
|
+
}
|
|
215
|
+
const compact = parts.join(" | ");
|
|
216
|
+
// Hard cap at 200 tokens (800 chars)
|
|
217
|
+
const maxChars = 200 * 4;
|
|
218
|
+
const result = compact.length > maxChars ? compact.slice(0, maxChars) : compact;
|
|
219
|
+
(0, runtime_1.emitNervesEvent)({
|
|
220
|
+
component: "heart",
|
|
221
|
+
event: "heart.wake_packet_compact_rendered",
|
|
222
|
+
message: `compact wake packet: ${estimateTokens(result)} tokens`,
|
|
223
|
+
meta: { tokens: estimateTokens(result) },
|
|
224
|
+
});
|
|
225
|
+
return result;
|
|
226
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
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.emitEpisode = emitEpisode;
|
|
37
|
+
exports.readRecentEpisodes = readRecentEpisodes;
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
const runtime_1 = require("../nerves/runtime");
|
|
41
|
+
function episodesDir(agentRoot) {
|
|
42
|
+
return path.join(agentRoot, "state", "episodes");
|
|
43
|
+
}
|
|
44
|
+
function generateId() {
|
|
45
|
+
const timestamp = Date.now();
|
|
46
|
+
const random = Math.random().toString(36).slice(2, 10);
|
|
47
|
+
return `ep-${timestamp}-${random}`;
|
|
48
|
+
}
|
|
49
|
+
function emitEpisode(agentRoot, input) {
|
|
50
|
+
const now = new Date().toISOString();
|
|
51
|
+
const id = generateId();
|
|
52
|
+
const episode = {
|
|
53
|
+
id,
|
|
54
|
+
timestamp: now,
|
|
55
|
+
kind: input.kind,
|
|
56
|
+
summary: input.summary,
|
|
57
|
+
whyItMattered: input.whyItMattered,
|
|
58
|
+
relatedEntities: input.relatedEntities,
|
|
59
|
+
salience: input.salience,
|
|
60
|
+
...(input.meta ? { meta: input.meta } : {}),
|
|
61
|
+
};
|
|
62
|
+
const dir = episodesDir(agentRoot);
|
|
63
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
64
|
+
fs.writeFileSync(path.join(dir, `${id}.json`), JSON.stringify(episode, null, 2), "utf-8");
|
|
65
|
+
(0, runtime_1.emitNervesEvent)({
|
|
66
|
+
component: "mind",
|
|
67
|
+
event: "mind.episode_emitted",
|
|
68
|
+
message: `episode emitted: ${input.kind}`,
|
|
69
|
+
meta: {
|
|
70
|
+
episodeId: id,
|
|
71
|
+
kind: input.kind,
|
|
72
|
+
salience: input.salience,
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
return episode;
|
|
76
|
+
}
|
|
77
|
+
function readRecentEpisodes(agentRoot, options) {
|
|
78
|
+
const dir = episodesDir(agentRoot);
|
|
79
|
+
if (!fs.existsSync(dir)) {
|
|
80
|
+
(0, runtime_1.emitNervesEvent)({
|
|
81
|
+
component: "mind",
|
|
82
|
+
event: "mind.episodes_read",
|
|
83
|
+
message: "read episodes: directory missing, returning empty",
|
|
84
|
+
meta: { count: 0 },
|
|
85
|
+
});
|
|
86
|
+
return [];
|
|
87
|
+
}
|
|
88
|
+
const limit = options?.limit ?? 50;
|
|
89
|
+
const since = options?.since;
|
|
90
|
+
const kinds = options?.kinds;
|
|
91
|
+
const files = fs.readdirSync(dir).filter((f) => f.endsWith(".json"));
|
|
92
|
+
const episodes = [];
|
|
93
|
+
for (const file of files) {
|
|
94
|
+
try {
|
|
95
|
+
const content = fs.readFileSync(path.join(dir, file), "utf-8");
|
|
96
|
+
const episode = JSON.parse(content);
|
|
97
|
+
if (since && episode.timestamp < since)
|
|
98
|
+
continue;
|
|
99
|
+
if (kinds && !kinds.includes(episode.kind))
|
|
100
|
+
continue;
|
|
101
|
+
episodes.push(episode);
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
// Skip malformed JSON files gracefully
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
episodes.sort((a, b) => b.timestamp.localeCompare(a.timestamp));
|
|
108
|
+
const result = episodes.slice(0, limit);
|
|
109
|
+
(0, runtime_1.emitNervesEvent)({
|
|
110
|
+
component: "mind",
|
|
111
|
+
event: "mind.episodes_read",
|
|
112
|
+
message: `read ${result.length} recent episodes`,
|
|
113
|
+
meta: { count: result.length, total: episodes.length, limit },
|
|
114
|
+
});
|
|
115
|
+
return result;
|
|
116
|
+
}
|
package/dist/mind/prompt.js
CHANGED
|
@@ -39,6 +39,7 @@ exports.bodyMapSection = bodyMapSection;
|
|
|
39
39
|
exports.mcpToolsSection = mcpToolsSection;
|
|
40
40
|
exports.runtimeInfoSection = runtimeInfoSection;
|
|
41
41
|
exports.toolRestrictionSection = toolRestrictionSection;
|
|
42
|
+
exports.wakePacketSection = wakePacketSection;
|
|
42
43
|
exports.centerOfGravitySteeringSection = centerOfGravitySteeringSection;
|
|
43
44
|
exports.commitmentsSection = commitmentsSection;
|
|
44
45
|
exports.delegationHintSection = delegationHintSection;
|
|
@@ -481,10 +482,13 @@ function bridgeContextSection(options) {
|
|
|
481
482
|
return "";
|
|
482
483
|
return bridgeContext.startsWith("## ") ? bridgeContext : `## active bridge work\n${bridgeContext}`;
|
|
483
484
|
}
|
|
485
|
+
function wakePacketSection(options) {
|
|
486
|
+
return options?.wakePacket ?? "";
|
|
487
|
+
}
|
|
484
488
|
function activeWorkSection(options) {
|
|
485
489
|
if (!options?.activeWorkFrame)
|
|
486
490
|
return "";
|
|
487
|
-
return (0, active_work_1.formatActiveWorkFrame)(options.activeWorkFrame);
|
|
491
|
+
return (0, active_work_1.formatActiveWorkFrame)(options.activeWorkFrame, { hasWakePacket: !!options?.wakePacket });
|
|
488
492
|
}
|
|
489
493
|
function liveWorldStateSection(options) {
|
|
490
494
|
if (!options?.activeWorkFrame)
|
|
@@ -506,6 +510,10 @@ function familyCrossSessionTruthSection(context, options) {
|
|
|
506
510
|
return "";
|
|
507
511
|
if (context?.friend?.trustLevel !== "family")
|
|
508
512
|
return "";
|
|
513
|
+
// When wake packet is present, compress to one line
|
|
514
|
+
if (options?.wakePacket) {
|
|
515
|
+
return "When family asks whole-self status, answer from the cross-session picture above.";
|
|
516
|
+
}
|
|
509
517
|
return `## cross-session truth
|
|
510
518
|
When family asks what I'm up to or how things are going, I answer from the live world-state across visible sessions and lanes, not just the current thread.
|
|
511
519
|
When live state conflicts with older transcript history, live state wins.
|
|
@@ -1010,6 +1018,7 @@ async function buildSystem(channel = "cli", options, context) {
|
|
|
1010
1018
|
] : []),
|
|
1011
1019
|
// Group 7: dynamic state for this turn
|
|
1012
1020
|
"# dynamic state for this turn",
|
|
1021
|
+
wakePacketSection(options),
|
|
1013
1022
|
liveWorldStateSection(options),
|
|
1014
1023
|
pendingMessagesSection(options),
|
|
1015
1024
|
activeWorkSection(options),
|
|
@@ -34,6 +34,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.prepareCodingContextPack = prepareCodingContextPack;
|
|
37
|
+
exports.emitCodingEpisode = emitCodingEpisode;
|
|
37
38
|
const crypto = __importStar(require("crypto"));
|
|
38
39
|
const fs = __importStar(require("fs"));
|
|
39
40
|
const path = __importStar(require("path"));
|
|
@@ -41,6 +42,7 @@ const child_process_1 = require("child_process");
|
|
|
41
42
|
const active_work_1 = require("../../heart/active-work");
|
|
42
43
|
const identity_1 = require("../../heart/identity");
|
|
43
44
|
const runtime_1 = require("../../nerves/runtime");
|
|
45
|
+
const episodes_1 = require("../../mind/episodes");
|
|
44
46
|
const skills_1 = require("../skills");
|
|
45
47
|
const CONTEXT_FILENAMES = ["AGENTS.md", "CLAUDE.md"];
|
|
46
48
|
function defaultRunCommand(command, args, cwd) {
|
|
@@ -173,7 +175,7 @@ function buildScopeContent(request, contextFiles, skills, agentName) {
|
|
|
173
175
|
formatSkills(skills),
|
|
174
176
|
].join("\n");
|
|
175
177
|
}
|
|
176
|
-
function buildStateContent(request, contextKey, generatedAt, snapshot, existingSessions, agentName, activeWorkFrame) {
|
|
178
|
+
function buildStateContent(request, contextKey, generatedAt, snapshot, existingSessions, agentName, activeWorkFrame, wakePacket) {
|
|
177
179
|
const gitSection = snapshot.available
|
|
178
180
|
? [
|
|
179
181
|
`repoRoot: ${snapshot.repoRoot ?? "unknown"}`,
|
|
@@ -190,6 +192,7 @@ function buildStateContent(request, contextKey, generatedAt, snapshot, existingS
|
|
|
190
192
|
`agent: ${request.parentAgent ?? agentName}`,
|
|
191
193
|
formatOrigin(request),
|
|
192
194
|
`obligationId: ${request.obligationId ?? "none"}`,
|
|
195
|
+
...(wakePacket ? ["", "## Continuity", wakePacket] : []),
|
|
193
196
|
"",
|
|
194
197
|
"## Workspace Snapshot",
|
|
195
198
|
gitSection,
|
|
@@ -226,7 +229,7 @@ function prepareCodingContextPack(input, deps = {}) {
|
|
|
226
229
|
const snapshot = captureRepoSnapshot(input.request.workdir, runCommand);
|
|
227
230
|
const generatedAt = nowIso();
|
|
228
231
|
const scopeContent = buildScopeContent(input.request, contextFiles, skills, agentName);
|
|
229
|
-
const stateContent = buildStateContent(input.request, contextKey, generatedAt, snapshot, existingSessions, agentName, input.activeWorkFrame);
|
|
232
|
+
const stateContent = buildStateContent(input.request, contextKey, generatedAt, snapshot, existingSessions, agentName, input.activeWorkFrame, input.wakePacket || undefined);
|
|
230
233
|
mkdirSync(contextDir, { recursive: true });
|
|
231
234
|
writeFileSync(scopeFile, `${scopeContent}\n`, "utf-8");
|
|
232
235
|
writeFileSync(stateFile, `${stateContent}\n`, "utf-8");
|
|
@@ -252,3 +255,23 @@ function prepareCodingContextPack(input, deps = {}) {
|
|
|
252
255
|
stateContent,
|
|
253
256
|
};
|
|
254
257
|
}
|
|
258
|
+
/**
|
|
259
|
+
* Emit a coding milestone episode when a session completes or blocks.
|
|
260
|
+
* This is the outbound leg of the coding round-trip: compact wake packet goes IN,
|
|
261
|
+
* episodes come BACK OUT.
|
|
262
|
+
*/
|
|
263
|
+
function emitCodingEpisode(agentRoot, session, outcome) {
|
|
264
|
+
(0, episodes_1.emitEpisode)(agentRoot, {
|
|
265
|
+
kind: "coding_milestone",
|
|
266
|
+
summary: `coding session ${session.id} (${session.runner}): ${outcome}`,
|
|
267
|
+
whyItMattered: `coding lane ${session.status}`,
|
|
268
|
+
relatedEntities: [`coding:${session.id}`],
|
|
269
|
+
salience: session.status === "failed" ? "high" : "medium",
|
|
270
|
+
});
|
|
271
|
+
(0, runtime_1.emitNervesEvent)({
|
|
272
|
+
component: "repertoire",
|
|
273
|
+
event: "repertoire.coding_episode_emitted",
|
|
274
|
+
message: `coding episode emitted for ${session.id}`,
|
|
275
|
+
meta: { sessionId: session.id, outcome, status: session.status },
|
|
276
|
+
});
|
|
277
|
+
}
|