@bunshin-cc/bunshin 0.6.4 → 0.6.5

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 (2) hide show
  1. package/dist/bin.js +61 -3
  2. package/package.json +1 -1
package/dist/bin.js CHANGED
@@ -1749,7 +1749,7 @@ function servable(sections, reader) {
1749
1749
  return [...out.values()];
1750
1750
  }
1751
1751
  function recallable(sections, reader) {
1752
- return servable(sections, reader).filter((s) => s.delivery !== "always" && s.delivery !== "stop");
1752
+ return servable(sections, reader).filter((s) => s.delivery !== "always" && s.delivery !== "stop" && s.delivery !== "reflect");
1753
1753
  }
1754
1754
  function passagesOfSection(s) {
1755
1755
  const hit = passageCache.get(s);
@@ -1965,6 +1965,50 @@ var init_engine = __esm({
1965
1965
  }
1966
1966
  });
1967
1967
 
1968
+ // ../core/src/v2/guidelines.ts
1969
+ function reflectionGuidelines(sections, reader, opts = {}) {
1970
+ const pool = reader ? servable(sections, reader) : sections;
1971
+ return pool.filter((s) => s.delivery === "reflect" && s.status === "active").filter((s) => !opts.layer || s.layer === "org" || opts.layer === s.layer || opts.layer.startsWith(`${s.layer}/`)).sort((a, b) => generality(a.layer) - generality(b.layer) || a.id.localeCompare(b.id)).map((s) => ({ id: s.id, title: s.title, layer: s.layer, body: s.body }));
1972
+ }
1973
+ function guidelineRules(body) {
1974
+ const at = body.search(/^## /m);
1975
+ const rules = (at < 0 ? body : body.slice(at)).replace(/^## Rules[^\n]*\n/m, "").trim();
1976
+ return rules;
1977
+ }
1978
+ function guidelinesSection(gs, opts = {}) {
1979
+ const list2 = gs ?? [];
1980
+ const withRules = list2.map((g) => ({ g, rules: guidelineRules(g.body) })).filter((x) => x.rules);
1981
+ const rules = withRules.length ? `These rules come from reviewers' feedback on earlier lessons. Follow them; where they conflict
1982
+ with the defaults below, they win.
1983
+
1984
+ ${withRules.map(({ g, rules: rules2 }) => `### ${g.title}${list2.length > 1 ? ` (${g.layer})` : ""}
1985
+
1986
+ ${rules2}`).join("\n\n")}
1987
+ ` : "";
1988
+ const target = list2[0];
1989
+ const route = opts.forReflection && target ? `${rules ? "\n" : ""}When the person in this session gives feedback about lessons themselves (how they should be
1990
+ captured or written, what to leave out: for example "/learn do not write ticket-specific details"),
1991
+ that is a rule for these guidelines, not for a task document: op "append" to ${target.id},
1992
+ anchor "${GUIDELINES_ANCHOR}", one general rule in the imperative, with the reason.
1993
+ ` : "";
1994
+ if (!rules && !route) return "";
1995
+ return `
1996
+ ## How this company wants lessons written (reflection guidelines)
1997
+
1998
+ ${rules}${route}`;
1999
+ }
2000
+ var GUIDELINES_ANCHOR, generality;
2001
+ var init_guidelines = __esm({
2002
+ "../core/src/v2/guidelines.ts"() {
2003
+ "use strict";
2004
+ init_types();
2005
+ init_layers();
2006
+ init_engine();
2007
+ GUIDELINES_ANCHOR = "rules";
2008
+ generality = (l) => ({ org: 0, dept: 1, fleet: 1, team: 2, arm: 3, mount: 3, robot: 4, user: 4 })[layerKind(l)] ?? 5;
2009
+ }
2010
+ });
2011
+
1968
2012
  // ../core/src/redact.ts
1969
2013
  function secretWord(w) {
1970
2014
  if (/tokeniz/.test(w)) return false;
@@ -2569,7 +2613,7 @@ ${input.digestNote ? `${input.digestNote}
2569
2613
  ${input.focus ? `## What to capture
2570
2614
 
2571
2615
  ${input.focus}
2572
- ` : ""}
2616
+ ` : ""}${guidelinesSection(input.guidelines, { forReflection: true })}
2573
2617
  ## When something is worth capturing
2574
2618
 
2575
2619
  Capture only what would change how a future agent acts, and is recorded nowhere durable:
@@ -2586,6 +2630,16 @@ Capture only what would change how a future agent acts, and is recorded nowhere
2586
2630
  Label each suggestion with its "signal": a \u2192 "steering", b \u2192 "environment", c \u2192 "knowledge",
2587
2631
  d \u2192 "capability", e \u2192 "approach".
2588
2632
 
2633
+ ## How to write it
2634
+
2635
+ A lesson is read by agents on other tasks, months from now. Write the rule, not the story:
2636
+ - Say when it applies, what to do, and why, so it holds beyond this session.
2637
+ - Leave out what only this session had: dates, how many tickets or items there were, ticket ids,
2638
+ the particular cases it happened on, who asked. Name a specific repo, service, file, command or
2639
+ spec only when the lesson is about that thing. One short generic example is fine when it makes
2640
+ the rule clearer.
2641
+ - The date and source are added automatically; never write them yourself.
2642
+
2589
2643
  ## Where it goes
2590
2644
 
2591
2645
  Every entry is a whole document (a skill, a spec, a policy). Prefer editing an existing document
@@ -2772,6 +2826,7 @@ var REFLECT_MARKER, ENVIRONMENT_RECHECK_DAYS, SIGNAL_WORDS, REFLECT_SCHEMA, KIND
2772
2826
  var init_reflect = __esm({
2773
2827
  "../core/src/v2/reflect.ts"() {
2774
2828
  "use strict";
2829
+ init_guidelines();
2775
2830
  init_redact();
2776
2831
  init_types();
2777
2832
  REFLECT_MARKER = "BUNSHIN:reflect";
@@ -2866,6 +2921,7 @@ var init_reconcile = __esm({
2866
2921
  var init_merge = __esm({
2867
2922
  "../core/src/v2/merge.ts"() {
2868
2923
  "use strict";
2924
+ init_guidelines();
2869
2925
  init_text();
2870
2926
  init_reconcile();
2871
2927
  init_markdown();
@@ -2918,6 +2974,7 @@ var init_v2 = __esm({
2918
2974
  init_release();
2919
2975
  init_research();
2920
2976
  init_profile();
2977
+ init_guidelines();
2921
2978
  }
2922
2979
  });
2923
2980
 
@@ -5814,7 +5871,8 @@ async function runReflectionV2(store, opts) {
5814
5871
  const from = reflectCursor(session, turns);
5815
5872
  const lessons = [.../* @__PURE__ */ new Set([...prior.map(lessonLine), ...session.serverLessons ?? []])].slice(0, 40);
5816
5873
  const earlier = from > 0 || lessons.length ? { ...from > 0 && facts ? { from: anchorAt(facts, from) } : {}, lessons } : void 0;
5817
- const promptBase = { contextKind: view.ctx.kind, layers: view.layers, index, captured, ...opts.focus ? { focus: opts.focus } : {}, ...earlier ? { earlier } : {}, ...profile ? { profileId: profile.id } : {} };
5874
+ const guidelines = reflectionGuidelines(view.sections, view.reader);
5875
+ const promptBase = { contextKind: view.ctx.kind, layers: view.layers, index, captured, guidelines, ...opts.focus ? { focus: opts.focus } : {}, ...earlier ? { earlier } : {}, ...profile ? { profileId: profile.id } : {} };
5818
5876
  let raw = null;
5819
5877
  if (harness === "claude-code") {
5820
5878
  const fork = await runClaudeFork(opts.sessionId, buildReflectPrompt(promptBase), { cwd: session.cwd, model: config.model });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bunshin-cc/bunshin",
3
- "version": "0.6.4",
3
+ "version": "0.6.5",
4
4
  "description": "Shared memory for company AI agents. Connect Codex, Claude Code, or Pi to Bunshin.",
5
5
  "type": "module",
6
6
  "bin": {