openvibers/openvibe.codes Commits
Describe Codes prompt layers (#360)
Changes
@@@ -146,6 +146,8 @@ async function runAttempt(opts = {}) {sessionId: state.sessionId,model: st.model || opts.model || null,summary: ((st.events || []).find((e) => e.t === 'final') || {}).text || '',++ // Preserve the exact, inspectable prompt composition with the run result for later review.++ promptLayers: prompt.parts,usage: state.usage,cost: state.cost,steps: state.steps,@@@ -63,12 +63,14 @@ function assemble({ brief, dir, env = process.env, know } = {}) {const houseRules = fragment('house-rules.md');const repo = repomap(dir);const learned = lessons({ file: know, repo: repo.repo, brief, env });++ // Every prompt section is inspectable as a versioned layer. Stable layers stay first;++ // the request is always last so changing the task leaves the cached prefix byte-identical.const parts = [-- { name: 'git-rule', text: gitRule },-- { name: 'house-rules', text: houseRules },-- { name: 'lessons', text: learned },-- { name: 'repo-digest', text: repo.text },-- { name: 'brief', text: String(brief || '') },++ { name: 'git-rule', layer: 'platform', source: 'engine/fragments/git-rule.md', version: 1, text: gitRule },++ { name: 'house-rules', layer: 'product', source: 'engine/fragments/house-rules.md', version: 1, text: houseRules },++ { name: 'lessons', layer: 'role', source: 'Know recall', version: 1, text: learned },++ { name: 'repo-digest', layer: 'role', source: 'engine/repomap.js', version: 1, text: repo.text },++ { name: 'brief', layer: 'task', source: 'launch request', version: 1, text: String(brief || '') },].filter((p) => p.text && p.text.trim());return { text: parts.map((p) => p.text).join('\n\n'), parts };}@@@ -38,6 +38,9 @@ function fake(dir, name, lines) {assert.equal(res.sessionId, 's-1');assert.equal(res.summary, 'landed');assert.equal(res.ok, true);++ assert.equal(res.promptLayers.at(-1).layer, 'task');++ assert.equal(res.promptLayers.at(-1).text, 'do it');++ assert.ok(res.promptLayers.slice(0, -1).every((part) => part.source && part.version === 1));assert.ok(fs.existsSync(res.log), 'the feed is kept');fs.rmSync(dir, { recursive: true, force: true });});@@@ -56,6 +56,10 @@ const { assemble, lessons, fragment } = require('../engine/prompt');fs.writeFileSync(path.join(dir, 'README.md'), '# Demo\n\nA demo repository.\n');const built = assemble({ brief: 'the brief', dir });assert.deepStrictEqual(built.parts.map((p) => p.name), ['git-rule', 'house-rules', 'repo-digest', 'brief']);++ assert.deepStrictEqual(built.parts.map((p) => p.layer), ['platform', 'product', 'role', 'task']);++ assert.ok(built.parts.every((p) => p.source && p.version === 1));++ const changed = assemble({ brief: 'different task', dir });++ assert.deepStrictEqual(changed.parts.slice(0, -1), built.parts.slice(0, -1), 'changing task preserves the stable prompt prefix');assert.ok(built.text.trimEnd().endsWith('the brief'), 'the brief is last');fs.rmSync(dir, { recursive: true, force: true });});
@@ -146,6 +146,8 @@ async function runAttempt(opts = {}) {
@@ -146,6 +146,8 @@ async function runAttempt(opts = {}) {
sessionId: state.sessionId,
sessionId: state.sessionId,
model: st.model || opts.model || null,
model: st.model || opts.model || null,
summary: ((st.events || []).find((e) => e.t === 'final') || {}).text || '',
summary: ((st.events || []).find((e) => e.t === 'final') || {}).text || '',
+ // Preserve the exact, inspectable prompt composition with the run result for later review.
+ promptLayers: prompt.parts,
usage: state.usage,
usage: state.usage,
cost: state.cost,
cost: state.cost,
steps: state.steps,
steps: state.steps,
@@ -63,12 +63,14 @@ function assemble({ brief, dir, env = process.env, know } = {}) {
@@ -63,12 +63,14 @@ function assemble({ brief, dir, env = process.env, know } = {}) {
const houseRules = fragment('house-rules.md');
const houseRules = fragment('house-rules.md');
const repo = repomap(dir);
const repo = repomap(dir);
const learned = lessons({ file: know, repo: repo.repo, brief, env });
const learned = lessons({ file: know, repo: repo.repo, brief, env });
+ // Every prompt section is inspectable as a versioned layer. Stable layers stay first;
+ // the request is always last so changing the task leaves the cached prefix byte-identical.
const parts = [
const parts = [
- { name: 'git-rule', text: gitRule },
- { name: 'house-rules', text: houseRules },
- { name: 'lessons', text: learned },
- { name: 'repo-digest', text: repo.text },
- { name: 'brief', text: String(brief || '') },
+ { name: 'git-rule', layer: 'platform', source: 'engine/fragments/git-rule.md', version: 1, text: gitRule },
+ { name: 'house-rules', layer: 'product', source: 'engine/fragments/house-rules.md', version: 1, text: houseRules },
+ { name: 'lessons', layer: 'role', source: 'Know recall', version: 1, text: learned },
+ { name: 'repo-digest', layer: 'role', source: 'engine/repomap.js', version: 1, text: repo.text },
+ { name: 'brief', layer: 'task', source: 'launch request', version: 1, text: String(brief || '') },
].filter((p) => p.text && p.text.trim());
].filter((p) => p.text && p.text.trim());
return { text: parts.map((p) => p.text).join('\n\n'), parts };
return { text: parts.map((p) => p.text).join('\n\n'), parts };
}
}
@@ -38,6 +38,9 @@ function fake(dir, name, lines) {
@@ -38,6 +38,9 @@ function fake(dir, name, lines) {
assert.equal(res.sessionId, 's-1');
assert.equal(res.sessionId, 's-1');
assert.equal(res.summary, 'landed');
assert.equal(res.summary, 'landed');
assert.equal(res.ok, true);
assert.equal(res.ok, true);
+ assert.equal(res.promptLayers.at(-1).layer, 'task');
+ assert.equal(res.promptLayers.at(-1).text, 'do it');
+ assert.ok(res.promptLayers.slice(0, -1).every((part) => part.source && part.version === 1));
assert.ok(fs.existsSync(res.log), 'the feed is kept');
assert.ok(fs.existsSync(res.log), 'the feed is kept');
fs.rmSync(dir, { recursive: true, force: true });
fs.rmSync(dir, { recursive: true, force: true });
});
});
@@ -56,6 +56,10 @@ const { assemble, lessons, fragment } = require('../engine/prompt');
@@ -56,6 +56,10 @@ const { assemble, lessons, fragment } = require('../engine/prompt');
fs.writeFileSync(path.join(dir, 'README.md'), '# Demo\n\nA demo repository.\n');
fs.writeFileSync(path.join(dir, 'README.md'), '# Demo\n\nA demo repository.\n');
const built = assemble({ brief: 'the brief', dir });
const built = assemble({ brief: 'the brief', dir });
assert.deepStrictEqual(built.parts.map((p) => p.name), ['git-rule', 'house-rules', 'repo-digest', 'brief']);
assert.deepStrictEqual(built.parts.map((p) => p.name), ['git-rule', 'house-rules', 'repo-digest', 'brief']);
+ assert.deepStrictEqual(built.parts.map((p) => p.layer), ['platform', 'product', 'role', 'task']);
+ assert.ok(built.parts.every((p) => p.source && p.version === 1));
+ const changed = assemble({ brief: 'different task', dir });
+ assert.deepStrictEqual(changed.parts.slice(0, -1), built.parts.slice(0, -1), 'changing task preserves the stable prompt prefix');
assert.ok(built.text.trimEnd().endsWith('the brief'), 'the brief is last');
assert.ok(built.text.trimEnd().endsWith('the brief'), 'the brief is last');
fs.rmSync(dir, { recursive: true, force: true });
fs.rmSync(dir, { recursive: true, force: true });
});
});