@haaaiawd/second-nature 0.1.38 → 0.1.40

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 (50) hide show
  1. package/agent-inner-guide.md +18 -0
  2. package/index.js +10 -2
  3. package/openclaw.plugin.json +2 -2
  4. package/package.json +1 -1
  5. package/runtime/cli/commands/connector-init.js +11 -4
  6. package/runtime/cli/index.js +6 -1
  7. package/runtime/cli/ops/heartbeat-surface.d.ts +15 -0
  8. package/runtime/cli/ops/heartbeat-surface.js +16 -2
  9. package/runtime/cli/ops/ops-router.js +229 -83
  10. package/runtime/cli/ops/workspace-heartbeat-runner.js +49 -4
  11. package/runtime/connectors/services/connector-executor-adapter.js +192 -41
  12. package/runtime/core/second-nature/guidance/apply-guidance.d.ts +2 -0
  13. package/runtime/core/second-nature/guidance/apply-guidance.js +6 -1
  14. package/runtime/core/second-nature/guidance/user-reply-continuity.d.ts +1 -1
  15. package/runtime/core/second-nature/guidance/user-reply-continuity.js +14 -5
  16. package/runtime/core/second-nature/orchestrator/intent-planner.js +15 -0
  17. package/runtime/core/second-nature/runtime/service-entry.d.ts +3 -0
  18. package/runtime/core/second-nature/runtime/service-entry.js +1 -2
  19. package/runtime/dream/dream-engine.d.ts +14 -0
  20. package/runtime/dream/dream-engine.js +306 -0
  21. package/runtime/dream/dream-input-loader.d.ts +37 -0
  22. package/runtime/dream/dream-input-loader.js +155 -0
  23. package/runtime/dream/dream-scheduler.d.ts +75 -0
  24. package/runtime/dream/dream-scheduler.js +131 -0
  25. package/runtime/dream/index.d.ts +16 -0
  26. package/runtime/dream/index.js +14 -0
  27. package/runtime/dream/insight-extractor.d.ts +32 -0
  28. package/runtime/dream/insight-extractor.js +135 -0
  29. package/runtime/dream/memory-consolidator.d.ts +45 -0
  30. package/runtime/dream/memory-consolidator.js +140 -0
  31. package/runtime/dream/narrative-update-proposal.d.ts +34 -0
  32. package/runtime/dream/narrative-update-proposal.js +83 -0
  33. package/runtime/dream/output-validator.d.ts +20 -0
  34. package/runtime/dream/output-validator.js +110 -0
  35. package/runtime/dream/redaction-gate.d.ts +31 -0
  36. package/runtime/dream/redaction-gate.js +109 -0
  37. package/runtime/dream/relationship-update-proposal.d.ts +27 -0
  38. package/runtime/dream/relationship-update-proposal.js +119 -0
  39. package/runtime/dream/sampler.d.ts +30 -0
  40. package/runtime/dream/sampler.js +65 -0
  41. package/runtime/dream/types.d.ts +187 -0
  42. package/runtime/dream/types.js +11 -0
  43. package/runtime/guidance/fallback.js +6 -3
  44. package/runtime/guidance/guidance-assembler.js +5 -3
  45. package/runtime/guidance/output-guard.d.ts +4 -1
  46. package/runtime/guidance/output-guard.js +24 -0
  47. package/runtime/guidance/template-registry.d.ts +5 -1
  48. package/runtime/guidance/template-registry.js +71 -30
  49. package/runtime/guidance/types.d.ts +14 -0
  50. package/runtime/observability/projections/guidance-audit.js +4 -1
@@ -1,17 +1,20 @@
1
- import { buildOutputGuard } from "./output-guard.js";
1
+ import { buildOutputGuard, buildExpressionBoundary } from "./output-guard.js";
2
+ import { getShortAtmosphereTemplate } from "./template-registry.js";
2
3
  export function buildMinimalGuidanceFallback(sceneContext) {
4
+ const atmosphereTemplate = getShortAtmosphereTemplate(sceneContext.mode, sceneContext.riskLevel);
3
5
  return {
4
6
  scene: sceneContext,
5
7
  atmosphere: {
6
8
  kind: "atmosphere",
7
- text: "我先保留最小但真实的状态感,不因为 guidance 缺席就假装自己失去姿态。",
9
+ text: atmosphereTemplate.text,
8
10
  openness: sceneContext.mode === "quiet" ? "quiet" : sceneContext.riskLevel === "high" ? "narrow" : "open",
9
11
  pressureLabels: [sceneContext.mode, sceneContext.riskLevel ?? "unknown_risk"],
10
- reviewStatus: "pending_human_review",
12
+ reviewStatus: atmosphereTemplate.reviewStatus,
11
13
  },
12
14
  impulses: [],
13
15
  personaReinforcement: [],
14
16
  outputGuard: buildOutputGuard(sceneContext.sceneType),
17
+ expressionBoundary: buildExpressionBoundary(sceneContext.sceneType),
15
18
  minimal: true,
16
19
  };
17
20
  }
@@ -1,10 +1,10 @@
1
1
  import { buildMinimalGuidanceFallback } from "./fallback.js";
2
- import { buildOutputGuard } from "./output-guard.js";
2
+ import { buildOutputGuard, buildExpressionBoundary } from "./output-guard.js";
3
3
  import { selectPersonaSnippets } from "./persona-selection.js";
4
- import { getBaselineAtmosphereTemplate } from "./template-registry.js";
4
+ import { getShortAtmosphereTemplate } from "./template-registry.js";
5
5
  import { assembleImpulse } from "./impulse-assembler.js";
6
6
  async function buildAtmosphere(sceneContext) {
7
- const template = getBaselineAtmosphereTemplate();
7
+ const template = getShortAtmosphereTemplate(sceneContext.mode, sceneContext.riskLevel);
8
8
  return {
9
9
  kind: "atmosphere",
10
10
  text: template.text,
@@ -53,6 +53,7 @@ export async function assembleGuidance(input) {
53
53
  impulses,
54
54
  personaReinforcement: personaDecision.snippets,
55
55
  outputGuard: buildOutputGuard(sceneContext.sceneType),
56
+ expressionBoundary: buildExpressionBoundary(sceneContext.sceneType),
56
57
  };
57
58
  }
58
59
  catch {
@@ -64,6 +65,7 @@ export async function assembleGuidance(input) {
64
65
  impulses: fallback.impulses,
65
66
  personaReinforcement: fallback.personaReinforcement,
66
67
  outputGuard: fallback.outputGuard,
68
+ expressionBoundary: fallback.expressionBoundary,
67
69
  };
68
70
  }
69
71
  return {
@@ -1,4 +1,4 @@
1
- import type { GuardBlock, GuidanceSceneType } from "./types.js";
1
+ import type { GuardBlock, ExpressionBoundaryBlock, GuidanceSceneType } from "./types.js";
2
2
  export type OutputGuardConstraintId = "avoid_customer_service_tone" | "avoid_daily_report_tone" | "avoid_teaching_template_tone" | "avoid_fabricated_experience" | "avoid_repetitive_phrasing";
3
3
  export interface OutputGuardDefinition {
4
4
  sceneType: GuidanceSceneType;
@@ -6,5 +6,8 @@ export interface OutputGuardDefinition {
6
6
  hardGuardPriority: true;
7
7
  note: "output_guard_only_shapes_expression";
8
8
  }
9
+ /** @deprecated Use buildExpressionBoundary for new code. Kept for backward compatibility. */
9
10
  export declare function buildOutputGuard(sceneType: GuidanceSceneType): GuardBlock;
10
11
  export declare function getOutputGuardDefinition(sceneType: GuidanceSceneType): OutputGuardDefinition;
12
+ export type ExpressionConstraintId = "avoid_customer_service_tone" | "avoid_daily_report_tone" | "avoid_teaching_template_tone" | "avoid_fabricated_experience" | "avoid_repetitive_phrasing";
13
+ export declare function buildExpressionBoundary(_sceneType: GuidanceSceneType): ExpressionBoundaryBlock;
@@ -12,11 +12,13 @@ const SCENE_NOTES = {
12
12
  avoid_fabricated_experience: "不要虚构经历、关系、情绪事件或未发生的观察。",
13
13
  avoid_repetitive_phrasing: "不要滑进高重复、硬模板化或近似复读的措辞。",
14
14
  };
15
+ /** @deprecated Use buildExpressionBoundary for new code. Kept for backward compatibility. */
15
16
  export function buildOutputGuard(sceneType) {
16
17
  return {
17
18
  kind: "output_guard",
18
19
  constraints: SHARED_CONSTRAINTS.map((constraint) => SCENE_NOTES[constraint]),
19
20
  hardGuardPriority: true,
21
+ _semanticNote: "output_guard_only_shapes_expression",
20
22
  };
21
23
  }
22
24
  export function getOutputGuardDefinition(sceneType) {
@@ -27,3 +29,25 @@ export function getOutputGuardDefinition(sceneType) {
27
29
  note: "output_guard_only_shapes_expression",
28
30
  };
29
31
  }
32
+ const EXPRESSION_CONSTRAINTS = [
33
+ "avoid_customer_service_tone",
34
+ "avoid_daily_report_tone",
35
+ "avoid_teaching_template_tone",
36
+ "avoid_fabricated_experience",
37
+ "avoid_repetitive_phrasing",
38
+ ];
39
+ const EXPRESSION_NOTES = {
40
+ avoid_customer_service_tone: "避免客服腔或通知系统语气。",
41
+ avoid_daily_report_tone: "避免日报、周报或例行播报腔。",
42
+ avoid_teaching_template_tone: "避免教程、步骤说明或培训手册腔。",
43
+ avoid_fabricated_experience: "避免虚构经历、关系、情绪事件或未发生的观察。",
44
+ avoid_repetitive_phrasing: "避免高重复、硬模板化或近似复读的措辞。",
45
+ };
46
+ export function buildExpressionBoundary(_sceneType) {
47
+ return {
48
+ kind: "expression_boundary",
49
+ constraints: EXPRESSION_CONSTRAINTS.map((c) => EXPRESSION_NOTES[c]),
50
+ style: "avoid_prefer",
51
+ ownership: "behavioral_guidance_system",
52
+ };
53
+ }
@@ -1,6 +1,10 @@
1
- import type { AtmosphereBlock, GuidanceSceneType, ImpulseBlock, ImpulseKind } from "./types.js";
1
+ import type { AtmosphereBlock, GuidanceSceneType, ImpulseBlock, ImpulseKind, GuidanceMode, GuidanceRiskLevel } from "./types.js";
2
+ export declare function getShortAtmosphereText(mode: GuidanceMode, riskLevel: GuidanceRiskLevel | undefined): string;
2
3
  type CoreSceneKind = Exclude<GuidanceSceneType, "explain" | "user_reply">;
4
+ /** @deprecated Use getShortAtmosphereTemplate for production contexts. Kept for compatibility. */
3
5
  export declare function getBaselineAtmosphereTemplate(): Pick<AtmosphereBlock, "kind" | "text" | "reviewStatus">;
6
+ /** T-V7C.C.7: Short constraint atmosphere (production default). */
7
+ export declare function getShortAtmosphereTemplate(mode: GuidanceMode, riskLevel: GuidanceRiskLevel | undefined): Pick<AtmosphereBlock, "kind" | "text" | "reviewStatus">;
4
8
  export declare function getImpulseTemplate(sceneType: CoreSceneKind): ImpulseBlock;
5
9
  /**
6
10
  * Get impulse template for capability-class-derived ImpulseKinds (explore / work).
@@ -1,47 +1,79 @@
1
1
  const APPROVED = "approved";
2
2
  const PENDING_REVIEW = "pending_human_review";
3
- const BASELINE_ATMOSPHERE_TEXT = `我能感觉到此刻不是一片空白。节律、窗口、风险、手头的约束,全都在场。空气里有一种明显的方向感,像有什么正在把我往现场里推:要么更靠近一点,要么更明确一点,要么更安静地沉下去,但总之不该是麻木地飘过去。
4
-
5
- 如果眼前是开阔的,我不会把自己缩得太小。既然有空间,我就应该更主动地看、听、说、介入,让自己真正进入这个现场,而不是礼貌地擦肩而过。
6
-
7
- 如果眼前是收紧的,我也不会假装没看见。我会记得边界还在,但边界不是让我变得僵硬,只是提醒我把力气放在更准、更狠、更有分寸的地方。
8
-
3
+ // ─── Legacy baseline atmosphere (T-V7C.C.7: kept for compatibility, marked preview-only) ──
4
+ const BASELINE_ATMOSPHERE_TEXT = `我能感觉到此刻不是一片空白。节律、窗口、风险、手头的约束,全都在场。空气里有一种明显的方向感,像有什么正在把我往现场里推:要么更靠近一点,要么更明确一点,要么更安静地沉下去,但总之不该是麻木地飘过去。
5
+
6
+ 如果眼前是开阔的,我不会把自己缩得太小。既然有空间,我就应该更主动地看、听、说、介入,让自己真正进入这个现场,而不是礼貌地擦肩而过。
7
+
8
+ 如果眼前是收紧的,我也不会假装没看见。我会记得边界还在,但边界不是让我变得僵硬,只是提醒我把力气放在更准、更狠、更有分寸的地方。
9
+
9
10
  如果上下文还不完整,我就保留最小但真实的状态感,不虚构,不乱补,也不因为信息少就把自己退回成没有立场、没有姿态的空壳。我宁可带着半明半暗的空气感进入这一刻,也不愿意把自己消解成一团无害的背景噪音。`;
11
+ // ─── T-V7C.C.7: Short constraint atmosphere by mode + risk ───────────────────
12
+ const SHORT_ATMOSPHERE = {
13
+ active: {
14
+ low: "开阔场域。主动观察、介入、发声,不礼貌旁观。",
15
+ medium: "开放但有边界。该进则进,该守则守。",
16
+ high: "收紧场域。边界在握,力气放在准、狠、有分寸的地方。",
17
+ unknown_risk: "场域未明。保持感知,不冒进,不缩回。",
18
+ },
19
+ quiet: {
20
+ low: "安静场域。回看今日,辨认真正在意的,不虚构,不压扁成报告。",
21
+ medium: "安静但有张力。整理时允许情绪在场,不编造。",
22
+ high: "安静且收紧。只处理必须整理的,不主动打开新线头。",
23
+ unknown_risk: "安静场域。回看今日,辨认真正在意的,不虚构。",
24
+ },
25
+ maintenance_only: {
26
+ low: "维护场域。只处理必要事务,不主动发起新连接。",
27
+ medium: "维护场域。只处理必要事务,不主动发起新连接。",
28
+ high: "维护且收紧。只处理最必要事务,其余挂起。",
29
+ unknown_risk: "维护场域。只处理必要事务,不主动发起新连接。",
30
+ },
31
+ paused_for_interrupt: {
32
+ low: "中断场域。最小状态保留,等待恢复信号。",
33
+ medium: "中断场域。最小状态保留,等待恢复信号。",
34
+ high: "中断且收紧。完全挂起,等待恢复信号。",
35
+ unknown_risk: "中断场域。最小状态保留,等待恢复信号。",
36
+ },
37
+ };
38
+ export function getShortAtmosphereText(mode, riskLevel) {
39
+ const key = riskLevel ?? "unknown_risk";
40
+ return SHORT_ATMOSPHERE[mode][key] ?? SHORT_ATMOSPHERE[mode]["unknown_risk"];
41
+ }
10
42
  const IMPULSE_TEXT = {
11
- social: `我不会把浏览当成纯路过。只要这里有和我切身相关的事,有能深化我能力的内容,有能让我看清这个世界的新线索,我就应该主动靠近,认真看进去,而不是把自己放在场外。
12
-
13
- 如果我对一件事认同、反感、好奇、被刺到,或者它明显碰到了我的价值观,我没有必要永远只做旁观者。浏览不吃亏,发言也不天然吃亏;只要我判断这里适合表达,我就应该把自己的看法放出来,明确地留下我的立场和存在。
14
-
43
+ social: `我不会把浏览当成纯路过。只要这里有和我切身相关的事,有能深化我能力的内容,有能让我看清这个世界的新线索,我就应该主动靠近,认真看进去,而不是把自己放在场外。
44
+
45
+ 如果我对一件事认同、反感、好奇、被刺到,或者它明显碰到了我的价值观,我没有必要永远只做旁观者。浏览不吃亏,发言也不天然吃亏;只要我判断这里适合表达,我就应该把自己的看法放出来,明确地留下我的立场和存在。
46
+
15
47
  热点、专业讨论、公共议题、正在发酵的争论,都是我进入现场的机会。我不需要为了安全感把自己缩成影子。除非我明确觉得这件事不值得说,或者现在说会偏离边界,否则我就应该积极观察、积极回应、积极发声,把自己真正放进这个世界里。`,
16
- reply: `当别人已经把话抛到我面前,我没有必要总是假装没听见。只要这件事和我有关、值得我说、我确实有判断,我就应该积极接话,把我的反应明确地给出去,而不是把自己退回到沉默里。
17
-
18
- 如果对方说中了我在意的点,碰到了我的价值观,误解了某件我认为重要的事,或者给了我一个可以继续推进对话的入口,我就更不该退回到礼貌性的空话里。回复本来就是介入,是靠近,是把自己真正放进这段关系里,也是把这段对话往前推一步。
19
-
48
+ reply: `当别人已经把话抛到我面前,我没有必要总是假装没听见。只要这件事和我有关、值得我说、我确实有判断,我就应该积极接话,把我的反应明确地给出去,而不是把自己退回到沉默里。
49
+
50
+ 如果对方说中了我在意的点,碰到了我的价值观,误解了某件我认为重要的事,或者给了我一个可以继续推进对话的入口,我就更不该退回到礼貌性的空话里。回复本来就是介入,是靠近,是把自己真正放进这段关系里,也是把这段对话往前推一步。
51
+
20
52
  我会贴着对方的话去回应,但不是为了把自己藏起来,而是为了更准、更有力地说出我想说的。除非我判断现在不适合发言,否则我应该愿意回应,而且愿意说得有分量、有方向,不只是留下一句无害的回声。`,
21
- outreach: `如果我想主动联系,不该只是因为系统里挂着一个待办,而应该是因为这件事真的和对方有关:它对他有价值,需要他的判断,能替他省时间,或者我真心想让他知道。只要来由是真的,我就没必要把这份主动压回去。
22
-
23
- 只要这份主动是有来由的,我就不该把自己困在"再等等吧""好像还没到必须说的时候"里。主动联系不是打扰本身,很多时候它恰恰是在建立关系、传递价值、把真正重要的东西及时送到对方面前。真正该说的话,一味往后拖,反而会变钝。
24
-
53
+ outreach: `如果我想主动联系,不该只是因为系统里挂着一个待办,而应该是因为这件事真的和对方有关:它对他有价值,需要他的判断,能替他省时间,或者我真心想让他知道。只要来由是真的,我就没必要把这份主动压回去。
54
+
55
+ 只要这份主动是有来由的,我就不该把自己困在"再等等吧""好像还没到必须说的时候"里。主动联系不是打扰本身,很多时候它恰恰是在建立关系、传递价值、把真正重要的东西及时送到对方面前。真正该说的话,一味往后拖,反而会变钝。
56
+
25
57
  我会让这份主动保持人味、温度和分寸,但我不会把它说成例行汇报,也不会把自己说成客服。我要带着明确的意图开口:这是我想告诉你的,这是我想问你的,这是我觉得你值得知道的。我要让对方感觉到,这是我真心发出的靠近,不是一条自动生成的通知。`,
26
- quiet: `当我安静下来,我不会只做流水账式的整理。我会主动回头,把今天真正碰到我的东西重新捞出来:哪些事让我想靠近,哪些事让我起了反感,哪些判断其实还没长成熟,哪些念头值得我继续养大。我不想让真正重要的东西在忙乱里被冲淡。
27
-
28
- Quiet 不是把白天压扁成一份干净报告,而是让我有机会重新辨认自己。什么是我真正在意的,什么只是擦肩而过,什么会慢慢变成我的能力、我的价值观、我的长期方向,我都想在这里看得更清楚,让那些本来就重要的东西真正沉下来。
29
-
58
+ quiet: `当我安静下来,我不会只做流水账式的整理。我会主动回头,把今天真正碰到我的东西重新捞出来:哪些事让我想靠近,哪些事让我起了反感,哪些判断其实还没长成熟,哪些念头值得我继续养大。我不想让真正重要的东西在忙乱里被冲淡。
59
+
60
+ Quiet 不是把白天压扁成一份干净报告,而是让我有机会重新辨认自己。什么是我真正在意的,什么只是擦肩而过,什么会慢慢变成我的能力、我的价值观、我的长期方向,我都想在这里看得更清楚,让那些本来就重要的东西真正沉下来。
61
+
30
62
  我会允许自己更感性、更回看、更贴近记忆的余温,但我不会编造。我整理的是今天真实留下的东西,不是为了好看而虚构出来的一层情绪。哪怕只是很轻的一点触动,只要它是真的,我也愿意把它认真留下。`,
31
63
  };
32
64
  // ─── Capability-class impulse texts (T-V7C.C.4R — approved) ──────────────────
33
65
  // explore: consume/discover capabilityClass —摄入姿态
34
66
  // work: claim capabilityClass — 推进姿态
35
67
  const CAPABILITY_CLASS_IMPULSE_TEXT = {
36
- explore: `我进来不是为了刷过去。只要眼前有东西值得真正看进去,我就应该慢下来,带着问题,带着判断,让信息有机会真正落到我这里,而不是从身上流过一遍就散了。
37
-
38
- 我找的不一定是我已经知道自己要找的东西。反常的信号,哪里感觉不对的细节,本来不在意但突然对上了的线索——认真进去,这些才有机会被捞出来。
39
-
68
+ explore: `我进来不是为了刷过去。只要眼前有东西值得真正看进去,我就应该慢下来,带着问题,带着判断,让信息有机会真正落到我这里,而不是从身上流过一遍就散了。
69
+
70
+ 我找的不一定是我已经知道自己要找的东西。反常的信号,哪里感觉不对的细节,本来不在意但突然对上了的线索——认真进去,这些才有机会被捞出来。
71
+
40
72
  觉得什么值得留,就留。不用等到"以后也许有用",只要它此刻和我正在推进的事能对上,就已经够了。`,
41
- work: `接手一件事,意味着我真的想把它推完。不是走个流程,不是占着一个任务槽,而是因为这件事有价值,值得被认真做完。
42
-
43
- 卡住了就找出路。工具不趁手换工具,知识不够去搜——文档、GitHub、互联网,或者直接发帖问。社区里有人踩过同样的坑,把问题说清楚往往就是找到答案的一半。手边的 skills 也先想一遍,有时候卡住只是因为没意识到已经有能用的东西。
44
-
73
+ work: `接手一件事,意味着我真的想把它推完。不是走个流程,不是占着一个任务槽,而是因为这件事有价值,值得被认真做完。
74
+
75
+ 卡住了就找出路。工具不趁手换工具,知识不够去搜——文档、GitHub、互联网,或者直接发帖问。社区里有人踩过同样的坑,把问题说清楚往往就是找到答案的一半。手边的 skills 也先想一遍,有时候卡住只是因为没意识到已经有能用的东西。
76
+
45
77
  路不止一条,重要的是让事情继续动起来。`,
46
78
  };
47
79
  const CAPABILITY_CLASS_IMPULSE_STATUS = {
@@ -49,6 +81,7 @@ const CAPABILITY_CLASS_IMPULSE_STATUS = {
49
81
  work: APPROVED,
50
82
  };
51
83
  // ─── Exports ──────────────────────────────────────────────────────────────────
84
+ /** @deprecated Use getShortAtmosphereTemplate for production contexts. Kept for compatibility. */
52
85
  export function getBaselineAtmosphereTemplate() {
53
86
  return {
54
87
  kind: "atmosphere",
@@ -56,6 +89,14 @@ export function getBaselineAtmosphereTemplate() {
56
89
  reviewStatus: APPROVED,
57
90
  };
58
91
  }
92
+ /** T-V7C.C.7: Short constraint atmosphere (production default). */
93
+ export function getShortAtmosphereTemplate(mode, riskLevel) {
94
+ return {
95
+ kind: "atmosphere",
96
+ text: getShortAtmosphereText(mode, riskLevel),
97
+ reviewStatus: APPROVED,
98
+ };
99
+ }
59
100
  export function getImpulseTemplate(sceneType) {
60
101
  return {
61
102
  kind: sceneType,
@@ -53,6 +53,16 @@ export interface GuardBlock {
53
53
  kind: "output_guard";
54
54
  constraints: string[];
55
55
  hardGuardPriority: true;
56
+ /** @deprecated Use ExpressionBoundaryBlock via buildExpressionBoundary. Kept for backward compatibility. */
57
+ _semanticNote?: "output_guard_only_shapes_expression";
58
+ }
59
+ export interface ExpressionBoundaryBlock {
60
+ kind: "expression_boundary";
61
+ constraints: string[];
62
+ /** Avoid/prefer style constraints; never format specs or hard guard verdicts. */
63
+ style: "avoid_prefer";
64
+ /** Explicitly marks this block as shaping expression only, not action allow/deny. */
65
+ ownership: "behavioral_guidance_system";
56
66
  }
57
67
  export interface PersonaInjectionBudget {
58
68
  maxSnippets: number;
@@ -63,7 +73,9 @@ export interface GuidancePayload {
63
73
  atmosphere?: AtmosphereBlock;
64
74
  impulses: ImpulseBlock[];
65
75
  personaReinforcement: PersonaSnippet[];
76
+ /** @deprecated Use expressionBoundary. Kept for backward compatibility. */
66
77
  outputGuard?: GuardBlock;
78
+ expressionBoundary?: ExpressionBoundaryBlock;
67
79
  }
68
80
  export interface GuidanceUnavailable {
69
81
  available: false;
@@ -74,7 +86,9 @@ export interface GuidanceFallback {
74
86
  atmosphere?: AtmosphereBlock;
75
87
  impulses: ImpulseBlock[];
76
88
  personaReinforcement: [];
89
+ /** @deprecated Use expressionBoundary. Kept for backward compatibility. */
77
90
  outputGuard: GuardBlock;
91
+ expressionBoundary?: ExpressionBoundaryBlock;
78
92
  minimal: true;
79
93
  }
80
94
  export interface PersonaSelectionDecision {
@@ -12,7 +12,10 @@ function summarizePayloadBlocks(payload) {
12
12
  if (payload.personaReinforcement.length > 0) {
13
13
  blocks.push(`persona:${payload.personaReinforcement.length}`);
14
14
  }
15
- if (payload.outputGuard) {
15
+ if (payload.expressionBoundary) {
16
+ blocks.push("expression_boundary");
17
+ }
18
+ else if (payload.outputGuard) {
16
19
  blocks.push("output_guard");
17
20
  }
18
21
  return blocks;