refactor(prompt): drop unreachable role-block defensive branches; keep marker grammar
This commit is contained in:
parent
20ff891962
commit
f490e07509
2 changed files with 17 additions and 67 deletions
|
|
@ -350,14 +350,14 @@ socket at `/run/hive/` once at startup:
|
|||
favour of this direct injection).
|
||||
Passed via `--system-prompt-file`.
|
||||
|
||||
**Marker grammar.** `<!-- role:X -->` opens a block; matching
|
||||
`<!-- /role:X -->` closes it. The renderer always uses role `agent`.
|
||||
Blocks with other role tags are elided. Nesting is NOT supported —
|
||||
a stray opener overrides until its closing tag (or end of file). A
|
||||
mismatched closer is elided from the output but does NOT pop the
|
||||
active role. Whitespace inside markers is tolerated
|
||||
(`<!--role:foo-->` parses the same as `<!-- role:foo -->`).
|
||||
Content outside any marker is always included.
|
||||
**Marker grammar.** `<!-- role:X -->` opens a block; any
|
||||
`<!-- /role:X -->` closes the current block. The renderer always uses
|
||||
role `agent`, so blocks with other role tags are elided. Nesting is NOT
|
||||
supported — a stray opener with no closer runs until end of file.
|
||||
Whitespace inside markers is tolerated (`<!--role:foo-->` parses the
|
||||
same as `<!-- role:foo -->`). Content outside any marker is always
|
||||
included. Today's `system.md` carries no markers (single agent role) —
|
||||
the grammar stays wired for a future manager / multi-role prompt.
|
||||
|
||||
**`hive_identity` / `swarm_identity` shape.** Each carries a
|
||||
leading space + backticked name (` on hive \`pr1ma\``,
|
||||
|
|
|
|||
|
|
@ -55,14 +55,12 @@ pub fn render(
|
|||
}
|
||||
}
|
||||
|
||||
/// Walk `template` line-by-line. Inside a `<!-- role:X -->` block,
|
||||
/// suppress all lines unless `X == target`. Marker lines themselves are
|
||||
/// always elided from the output. Unbalanced openers (no matching
|
||||
/// closer) hold the suppression state until end-of-file. A mismatched
|
||||
/// closer (`<!-- /role:manager -->` inside a `role:agent` block) is
|
||||
/// elided from the output but does NOT reset the active role — keeps
|
||||
/// the suppression conservative so a typo can't dump wrong-flavor
|
||||
/// content.
|
||||
/// Walk `template` line-by-line, stripping `<!-- role:X -->` /
|
||||
/// `<!-- /role:X -->` marker lines and suppressing the lines inside a block
|
||||
/// unless `X == target`. A close marker ends the current block. Production
|
||||
/// `system.md` carries no markers today (single agent role — see the module
|
||||
/// doc), so this is effectively a passthrough; the marker grammar stays wired
|
||||
/// for a future manager / multi-role prompt.
|
||||
fn filter_role_blocks(template: &str, target: &str) -> String {
|
||||
let mut out = String::with_capacity(template.len());
|
||||
// None = outside any block; Some(role) = inside role-tagged block.
|
||||
|
|
@ -73,19 +71,11 @@ fn filter_role_blocks(template: &str, target: &str) -> String {
|
|||
active_role = Some(role);
|
||||
continue;
|
||||
}
|
||||
if let Some(close_role) = parse_close_marker(trimmed) {
|
||||
if active_role == Some(close_role) {
|
||||
active_role = None;
|
||||
}
|
||||
// Mismatched close: elide the marker line but keep the
|
||||
// active role intact so wrong-flavor content stays gated.
|
||||
if parse_close_marker(trimmed).is_some() {
|
||||
active_role = None;
|
||||
continue;
|
||||
}
|
||||
let include = match active_role {
|
||||
None => true,
|
||||
Some(role) => role == target,
|
||||
};
|
||||
if include {
|
||||
if active_role.is_none_or(|role| role == target) {
|
||||
out.push_str(line);
|
||||
out.push('\n');
|
||||
}
|
||||
|
|
@ -245,46 +235,6 @@ shared closer
|
|||
assert_eq!(parse_close_marker("just text"), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mismatched_close_keeps_active_role() {
|
||||
// `<!-- role:agent -->` block with a stray `<!-- /role:manager -->`
|
||||
// closer inside: the manager-tagged close must NOT pop the agent
|
||||
// gate, else manager-target output would leak the agent block's
|
||||
// text (or vice-versa). Stray marker line itself is still elided.
|
||||
let template = "shared\n\
|
||||
<!-- role:agent -->\n\
|
||||
agent line 1\n\
|
||||
<!-- /role:manager -->\n\
|
||||
agent line 2\n\
|
||||
<!-- /role:agent -->\n\
|
||||
shared end\n";
|
||||
let manager = filter_role_blocks(template, "manager");
|
||||
// Both agent lines stay gated out for the manager target; the
|
||||
// stray close didn't accidentally pop the role. Stray marker
|
||||
// itself elided from the output.
|
||||
assert!(!manager.contains("agent line 1"));
|
||||
assert!(!manager.contains("agent line 2"));
|
||||
assert!(!manager.contains("<!--"));
|
||||
assert!(manager.contains("shared"));
|
||||
assert!(manager.contains("shared end"));
|
||||
// Agent target still sees both lines (matched closer pops at the end).
|
||||
let agent = filter_role_blocks(template, "agent");
|
||||
assert!(agent.contains("agent line 1"));
|
||||
assert!(agent.contains("agent line 2"));
|
||||
assert!(agent.contains("shared end"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unbalanced_opener_suppresses_until_eof() {
|
||||
// Stray opener with no closer — content stays suppressed for
|
||||
// the wrong-role target right through to end-of-file. Real-
|
||||
// file safety net: a typo in a closer doesn't accidentally
|
||||
// dump wrong-flavor content into the active prompt.
|
||||
let template = "shared\n<!-- role:manager -->\nm-only\nstill m-only\n";
|
||||
let agent = filter_role_blocks(template, "agent");
|
||||
assert_eq!(agent, "shared\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn render_substitutes_label_and_pronouns() {
|
||||
// Real template's first agent line — keeps the renderer
|
||||
|
|
|
|||
Loading…
Reference in a new issue