principles-disciple 1.209.3 → 1.209.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 (130) hide show
  1. package/README.md +73 -0
  2. package/dist/bundle.js +13 -11
  3. package/dist/constants/tools.d.ts +1 -1
  4. package/dist/hooks/prompt-helpers.d.ts +5 -5
  5. package/dist/openclaw.plugin.json +1 -1
  6. package/dist/templates/langs/en/core/AGENTS.md +40 -180
  7. package/dist/templates/langs/en/core/BOOT.md +19 -47
  8. package/dist/templates/langs/en/core/HEARTBEAT.md +26 -58
  9. package/dist/templates/langs/en/core/IDENTITY.md +15 -8
  10. package/dist/templates/langs/en/core/PRINCIPLES.md +6 -7
  11. package/dist/templates/langs/en/core/SOUL.md +10 -41
  12. package/dist/templates/langs/en/core/TOOLS.md +18 -10
  13. package/dist/templates/langs/en/core/USER.md +13 -8
  14. package/dist/templates/langs/en/skills/pd-auditor/SKILL.md +1 -1
  15. package/dist/templates/langs/en/skills/pd-explorer/SKILL.md +1 -1
  16. package/dist/templates/langs/en/skills/pd-implementer/SKILL.md +1 -1
  17. package/dist/templates/langs/en/skills/pd-mentor/SKILL.md +6 -30
  18. package/dist/templates/langs/en/skills/pd-planner/SKILL.md +1 -1
  19. package/dist/templates/langs/zh/core/AGENTS.md +38 -173
  20. package/dist/templates/langs/zh/core/BOOT.md +14 -46
  21. package/dist/templates/langs/zh/core/HEARTBEAT.md +20 -82
  22. package/dist/templates/langs/zh/core/IDENTITY.md +15 -8
  23. package/dist/templates/langs/zh/core/PRINCIPLES.md +7 -7
  24. package/dist/templates/langs/zh/core/SOUL.md +9 -41
  25. package/dist/templates/langs/zh/core/TOOLS.md +14 -10
  26. package/dist/templates/langs/zh/core/USER.md +12 -8
  27. package/dist/templates/langs/zh/skills/pd-auditor/SKILL.md +1 -1
  28. package/dist/templates/langs/zh/skills/pd-explorer/SKILL.md +1 -1
  29. package/dist/templates/langs/zh/skills/pd-implementer/SKILL.md +1 -1
  30. package/dist/templates/langs/zh/skills/pd-mentor/SKILL.md +6 -30
  31. package/dist/templates/langs/zh/skills/pd-planner/SKILL.md +1 -1
  32. package/openclaw.plugin.json +1 -1
  33. package/package.json +1 -2
  34. package/templates/langs/en/core/AGENTS.md +40 -180
  35. package/templates/langs/en/core/BOOT.md +19 -47
  36. package/templates/langs/en/core/HEARTBEAT.md +26 -58
  37. package/templates/langs/en/core/IDENTITY.md +15 -8
  38. package/templates/langs/en/core/PRINCIPLES.md +6 -7
  39. package/templates/langs/en/core/SOUL.md +10 -41
  40. package/templates/langs/en/core/TOOLS.md +18 -10
  41. package/templates/langs/en/core/USER.md +13 -8
  42. package/templates/langs/en/skills/pd-auditor/SKILL.md +1 -1
  43. package/templates/langs/en/skills/pd-explorer/SKILL.md +1 -1
  44. package/templates/langs/en/skills/pd-implementer/SKILL.md +1 -1
  45. package/templates/langs/en/skills/pd-mentor/SKILL.md +6 -30
  46. package/templates/langs/en/skills/pd-planner/SKILL.md +1 -1
  47. package/templates/langs/zh/core/AGENTS.md +38 -173
  48. package/templates/langs/zh/core/BOOT.md +14 -46
  49. package/templates/langs/zh/core/HEARTBEAT.md +20 -82
  50. package/templates/langs/zh/core/IDENTITY.md +15 -8
  51. package/templates/langs/zh/core/PRINCIPLES.md +7 -7
  52. package/templates/langs/zh/core/SOUL.md +9 -41
  53. package/templates/langs/zh/core/TOOLS.md +14 -10
  54. package/templates/langs/zh/core/USER.md +12 -8
  55. package/templates/langs/zh/skills/pd-auditor/SKILL.md +1 -1
  56. package/templates/langs/zh/skills/pd-explorer/SKILL.md +1 -1
  57. package/templates/langs/zh/skills/pd-implementer/SKILL.md +1 -1
  58. package/templates/langs/zh/skills/pd-mentor/SKILL.md +6 -30
  59. package/templates/langs/zh/skills/pd-planner/SKILL.md +1 -1
  60. package/dist/templates/langs/en/core/BOOTSTRAP.md +0 -259
  61. package/dist/templates/langs/en/skills/admin/SKILL.md +0 -39
  62. package/dist/templates/langs/en/skills/bootstrap-tools/SKILL.md +0 -53
  63. package/dist/templates/langs/en/skills/deductive-audit/SKILL.md +0 -36
  64. package/dist/templates/langs/en/skills/evolution-framework-update/SKILL.md +0 -31
  65. package/dist/templates/langs/en/skills/evolve-task/SKILL.md +0 -83
  66. package/dist/templates/langs/en/skills/feedback/SKILL.md +0 -51
  67. package/dist/templates/langs/en/skills/init-strategy/SKILL.md +0 -54
  68. package/dist/templates/langs/en/skills/inject-rule/SKILL.md +0 -19
  69. package/dist/templates/langs/en/skills/profile/SKILL.md +0 -24
  70. package/dist/templates/langs/en/skills/reflection/SKILL.md +0 -40
  71. package/dist/templates/langs/en/skills/reflection-log/SKILL.md +0 -37
  72. package/dist/templates/langs/en/skills/report/SKILL.md +0 -13
  73. package/dist/templates/langs/en/skills/root-cause/SKILL.md +0 -33
  74. package/dist/templates/langs/en/skills/triage/SKILL.md +0 -29
  75. package/dist/templates/langs/en/skills/watch-evolution/SKILL.md +0 -33
  76. package/dist/templates/langs/zh/core/BOOTSTRAP.md +0 -260
  77. package/dist/templates/langs/zh/skills/admin/SKILL.md +0 -41
  78. package/dist/templates/langs/zh/skills/bootstrap-tools/SKILL.md +0 -52
  79. package/dist/templates/langs/zh/skills/deductive-audit/SKILL.md +0 -36
  80. package/dist/templates/langs/zh/skills/evolution-framework-update/SKILL.md +0 -31
  81. package/dist/templates/langs/zh/skills/evolve-task/SKILL.md +0 -83
  82. package/dist/templates/langs/zh/skills/feedback/SKILL.md +0 -53
  83. package/dist/templates/langs/zh/skills/init-strategy/SKILL.md +0 -54
  84. package/dist/templates/langs/zh/skills/inject-rule/SKILL.md +0 -19
  85. package/dist/templates/langs/zh/skills/profile/SKILL.md +0 -24
  86. package/dist/templates/langs/zh/skills/reflection/SKILL.md +0 -40
  87. package/dist/templates/langs/zh/skills/reflection-log/SKILL.md +0 -37
  88. package/dist/templates/langs/zh/skills/report/SKILL.md +0 -13
  89. package/dist/templates/langs/zh/skills/root-cause/SKILL.md +0 -33
  90. package/dist/templates/langs/zh/skills/triage/SKILL.md +0 -29
  91. package/dist/templates/langs/zh/skills/watch-evolution/SKILL.md +0 -33
  92. package/scripts/acceptance-test.mjs +0 -257
  93. package/scripts/bootstrap-rules.mjs +0 -70
  94. package/scripts/compile-principles.mjs +0 -104
  95. package/scripts/install-dependencies.cjs +0 -47
  96. package/scripts/postinstall.cjs +0 -177
  97. package/scripts/sync-plugin.mjs +0 -1442
  98. package/scripts/verify-build.mjs +0 -120
  99. package/templates/langs/en/core/BOOTSTRAP.md +0 -259
  100. package/templates/langs/en/skills/admin/SKILL.md +0 -39
  101. package/templates/langs/en/skills/bootstrap-tools/SKILL.md +0 -53
  102. package/templates/langs/en/skills/deductive-audit/SKILL.md +0 -36
  103. package/templates/langs/en/skills/evolution-framework-update/SKILL.md +0 -31
  104. package/templates/langs/en/skills/evolve-task/SKILL.md +0 -83
  105. package/templates/langs/en/skills/feedback/SKILL.md +0 -51
  106. package/templates/langs/en/skills/init-strategy/SKILL.md +0 -54
  107. package/templates/langs/en/skills/inject-rule/SKILL.md +0 -19
  108. package/templates/langs/en/skills/profile/SKILL.md +0 -24
  109. package/templates/langs/en/skills/reflection/SKILL.md +0 -40
  110. package/templates/langs/en/skills/reflection-log/SKILL.md +0 -37
  111. package/templates/langs/en/skills/report/SKILL.md +0 -13
  112. package/templates/langs/en/skills/root-cause/SKILL.md +0 -33
  113. package/templates/langs/en/skills/triage/SKILL.md +0 -29
  114. package/templates/langs/en/skills/watch-evolution/SKILL.md +0 -33
  115. package/templates/langs/zh/core/BOOTSTRAP.md +0 -260
  116. package/templates/langs/zh/skills/admin/SKILL.md +0 -41
  117. package/templates/langs/zh/skills/bootstrap-tools/SKILL.md +0 -52
  118. package/templates/langs/zh/skills/deductive-audit/SKILL.md +0 -36
  119. package/templates/langs/zh/skills/evolution-framework-update/SKILL.md +0 -31
  120. package/templates/langs/zh/skills/evolve-task/SKILL.md +0 -83
  121. package/templates/langs/zh/skills/feedback/SKILL.md +0 -53
  122. package/templates/langs/zh/skills/init-strategy/SKILL.md +0 -54
  123. package/templates/langs/zh/skills/inject-rule/SKILL.md +0 -19
  124. package/templates/langs/zh/skills/profile/SKILL.md +0 -24
  125. package/templates/langs/zh/skills/reflection/SKILL.md +0 -40
  126. package/templates/langs/zh/skills/reflection-log/SKILL.md +0 -37
  127. package/templates/langs/zh/skills/report/SKILL.md +0 -13
  128. package/templates/langs/zh/skills/root-cause/SKILL.md +0 -33
  129. package/templates/langs/zh/skills/triage/SKILL.md +0 -29
  130. package/templates/langs/zh/skills/watch-evolution/SKILL.md +0 -33
package/README.md CHANGED
@@ -168,6 +168,79 @@ The plugin accepts the following configuration options:
168
168
  For the full architecture, runtime adapters (OpenClaw, Codex), and product
169
169
  boundary, see the project documentation linked below.
170
170
 
171
+ ## Security & data boundaries
172
+
173
+ Principles Disciple is a local-first behavior-governance layer. This section
174
+ describes what this npm package (`principles-disciple`, the OpenClaw plugin)
175
+ actually does, so you can evaluate it before installing. It reflects a
176
+ source audit of the published artifact (PRI-547).
177
+
178
+ ### Local data
179
+
180
+ Behavior evidence, principles, decision records, and trajectories are stored
181
+ in the user-controlled local workspace (flat files plus SQLite databases
182
+ under the workspace's PD state directories). The core plugin does not send
183
+ product telemetry; network access occurs only when an Owner-configured LLM
184
+ runtime provider is used (see below).
185
+
186
+ ### Agent authority
187
+
188
+ PD influences future agent behavior through owner-approved context injection
189
+ and tool-hook enforcement. Principle activation is subject to owner review;
190
+ anything activated can be rolled back (`/pd-rollback`,
191
+ `/pd-principle-rollback`).
192
+
193
+ ### Conversation and hook access
194
+
195
+ The plugin registers OpenClaw hooks (prompt, tool calls, LLM output,
196
+ session lifecycle). Conversation access is granted through the host's
197
+ `hooks.allowConversationAccess` config key. The `npx` installer and the
198
+ plugin's first-load auto-fix set this key to `true` so the hooks work out of
199
+ the box (PRI-343); you can turn it off with
200
+ `openclaw config set plugins.entries.principles-disciple.hooks.allowConversationAccess false`
201
+ — the plugin degrades to non-conversation surfaces (with a fallback
202
+ trajectory collector) instead of failing.
203
+
204
+ ### Process and filesystem access
205
+
206
+ The plugin reads and writes PD workspace state (memory files, `.state/`,
207
+ `.principles/`, SQLite databases) and observes tool-call activity through
208
+ OpenClaw hooks — these capabilities are its stated behavior-governance
209
+ function. The `/pd-bootstrap` command runs `<tool> --version` probes (rg,
210
+ fd, shellcheck, …) to scan your local development environment; it only runs
211
+ when you invoke it.
212
+
213
+ ### Network access and LLM providers
214
+
215
+ The core plugin performs no network I/O except through Owner-configured
216
+ provider SDKs. Optional LLM calls happen only when you configure a runtime
217
+ profile: the bundled provider SDKs read their standard credential
218
+ environment variables (AWS/Azure/GCP/OpenAI-style, depending on the chosen
219
+ provider) and call that provider from your machine. Diagnostics, principle
220
+ refinement, and internal agents run through this user-configured provider.
221
+ Some antivirus engines flag the bundled provider SDKs'
222
+ environment-variable handling; that is disclosed here rather than
223
+ obfuscated.
224
+
225
+ ### Telemetry
226
+
227
+ The core OpenClaw plugin does not send product-usage telemetry. PD redacts
228
+ supported sensitive patterns before persistence — including known Windows
229
+ and Unix paths, email addresses, and common token formats — and `/pd-export`
230
+ redacts by default. This is not a general-purpose PII scrubber: automatic
231
+ redaction does not yet cover phone numbers, credit cards, IP addresses, or
232
+ other unknown PII. Remaining limitations are tracked in the project's
233
+ [security baseline](https://github.com/csuzngjh/principles/blob/main/docs/architecture/SECURITY_BASELINE.md).
234
+
235
+ ### Separately shipped components
236
+
237
+ Other PD components ship as their own packages and have their own
238
+ boundaries: the `create-principles-disciple` installer downloads from the
239
+ npm registry and installs files under `~/.openclaw/`; `pd-console` is a
240
+ local web console that performs npm registry update checks and
241
+ user-initiated feedback submission when you use those features. They are not
242
+ part of this plugin tarball.
243
+
171
244
  ## Part of the principles monorepo
172
245
 
173
246
  See the root [README.md](https://github.com/csuzngjh/principles#readme) for
package/dist/bundle.js CHANGED
@@ -2292,16 +2292,18 @@ Blockers:
2292
2292
  INSERT OR IGNORE INTO principle_applications
2293
2293
  (principle_id, channel, level, kind, session_id, digest, created_at)
2294
2294
  VALUES (?, 'prompt', 'effect', 'self_reported', ?, ?, ?)
2295
- `).run(a,r??null,s,new Date().toISOString()),l=typeof u=="object"&&u!==null?u.changes??0:0;o+=l>0?1:0}catch(c){n?.warn?.(`[PD:ReceiptLedger] self_report row write failed for principle ${a}: ${String(c)}`)}}return o}import*as lE from"node:fs";import*as y$t from"node:path";var OMn=".principles",PMn=6e4,WO=new Map;function NMn(e,t){return y$t.join(e,OMn,xf(t))}function MMn(e,t){return`${e}:${t}`}function LMn(e,t,r){let n=i7(e),o=Ewe(n),i=a7(e);return{raw:e,sections:n,contentHash:i,path:t,readAt:r,warnings:o}}function pY(e,t,r){if(!Qo(e,"intent_engineering",r?.logger).enabled)return{ok:!1,found:!1,flagEnabled:!1,reason:"flag_disabled",nextAction:`Enable the intent_engineering feature flag in .pd/config.yaml to read ${xf(t)}.`,warnings:[]};let o=MMn(e,t),i=NMn(e,t),a=Date.now(),s=WO.get(o);if(s&&a-s.loadedAt<PMn)try{if(lE.statSync(i).mtimeMs===s.mtime)return{ok:!0,found:!0,flagEnabled:!0,doc:s.doc,warnings:s.doc.warnings}}catch{}try{if(!lE.existsSync(i))return WO.delete(o),{ok:!1,found:!1,flagEnabled:!0,reason:"not_found",nextAction:`Create .principles/${xf(t)} using "pd intent init".`,warnings:[]};let c=lE.statSync(i);if(c.size>32768)return WO.delete(o),{ok:!1,found:!0,flagEnabled:!0,reason:"oversized",nextAction:`${xf(t)} exceeds ${32768} bytes (${c.size} bytes). Reduce content.`,warnings:[]};let u=lE.readFileSync(i,"utf8"),l=Buffer.byteLength(u,"utf8");if(l>32768)return WO.delete(o),{ok:!1,found:!0,flagEnabled:!0,reason:"oversized",nextAction:`${xf(t)} exceeds ${32768} bytes (${l} bytes after read). Reduce content.`,warnings:[]};let d=LMn(u,i,new Date(a).toISOString());return WO.set(o,{doc:d,mtime:c.mtimeMs,loadedAt:a}),{ok:!0,found:!0,flagEnabled:!0,doc:d,warnings:d.warnings}}catch(c){WO.delete(o);let u=c instanceof Error?c.message:String(c);return r?.logger?.warn?.(`[PD:Intent] safeReadIntentDoc failed: workspace=${e}, lang=${t}, error=${u}`),{ok:!1,found:!1,flagEnabled:!0,reason:"read_error",nextAction:`Check filesystem permissions for .principles/${xf(t)}.`,warnings:[]}}}import*as CIe from"node:fs";import*as OIe from"node:path";var x$t=".principles";function qO(e){let t=OIe.join(e,x$t,xf("zh-CN"));if(CIe.existsSync(t))return"zh-CN";let r=OIe.join(e,x$t,xf("en"));return CIe.existsSync(r)?"en":"zh-CN"}function dY(e,t){return{readIntentDoc(){let r=pY(e,t);if(r.ok&&r.doc){let n=r.doc;return{ok:!0,found:!0,flagEnabled:!0,doc:{raw:typeof n.raw=="string"?n.raw:"",contentHash:typeof n.contentHash=="string"?n.contentHash:"",path:typeof n.path=="string"?n.path:""}}}return{ok:!1,found:r.found,flagEnabled:r.flagEnabled,reason:r.reason,nextAction:r.nextAction}}}}function S$t(e,t){let r=e||"";if((r.startsWith("You are running a boot check.")||r.includes("You are running a boot check. Follow BOOT.md"))&&(r=""),r.length>50){let i=/Sender \(untrusted metadata\):[\s\S]*?```json[\s\S]*?```\s*/.exec(r);if(i){let a=r.slice(i.index+i[0].length).trim();a.length>3&&(r=a)}if(r.length>200&&r.includes("Conversation info")){let a=/Conversation info[\s\S]*?```json[\s\S]*?```\s*/.exec(r);if(a){let s=r.slice(a.index+a[0].length).trim();s.length>3&&(r=s)}}}let n=/empathy\s*observer/i.test(r)&&/damageDetected|severity|confidence/i.test(r),o=r.includes("sourceSession=agent:")||t?.includes(":subagent:")===!0||n;return{message:r,isAgentToAgent:o,isEmpathyPrompt:n}}function b$t(){return`## \u3010AGENT IDENTITY\u3011
2295
+ `).run(a,r??null,s,new Date().toISOString()),l=typeof u=="object"&&u!==null?u.changes??0:0;o+=l>0?1:0}catch(c){n?.warn?.(`[PD:ReceiptLedger] self_report row write failed for principle ${a}: ${String(c)}`)}}return o}import*as lE from"node:fs";import*as y$t from"node:path";var OMn=".principles",PMn=6e4,WO=new Map;function NMn(e,t){return y$t.join(e,OMn,xf(t))}function MMn(e,t){return`${e}:${t}`}function LMn(e,t,r){let n=i7(e),o=Ewe(n),i=a7(e);return{raw:e,sections:n,contentHash:i,path:t,readAt:r,warnings:o}}function pY(e,t,r){if(!Qo(e,"intent_engineering",r?.logger).enabled)return{ok:!1,found:!1,flagEnabled:!1,reason:"flag_disabled",nextAction:`Enable the intent_engineering feature flag in .pd/config.yaml to read ${xf(t)}.`,warnings:[]};let o=MMn(e,t),i=NMn(e,t),a=Date.now(),s=WO.get(o);if(s&&a-s.loadedAt<PMn)try{if(lE.statSync(i).mtimeMs===s.mtime)return{ok:!0,found:!0,flagEnabled:!0,doc:s.doc,warnings:s.doc.warnings}}catch{}try{if(!lE.existsSync(i))return WO.delete(o),{ok:!1,found:!1,flagEnabled:!0,reason:"not_found",nextAction:`Create .principles/${xf(t)} using "pd intent init".`,warnings:[]};let c=lE.statSync(i);if(c.size>32768)return WO.delete(o),{ok:!1,found:!0,flagEnabled:!0,reason:"oversized",nextAction:`${xf(t)} exceeds ${32768} bytes (${c.size} bytes). Reduce content.`,warnings:[]};let u=lE.readFileSync(i,"utf8"),l=Buffer.byteLength(u,"utf8");if(l>32768)return WO.delete(o),{ok:!1,found:!0,flagEnabled:!0,reason:"oversized",nextAction:`${xf(t)} exceeds ${32768} bytes (${l} bytes after read). Reduce content.`,warnings:[]};let d=LMn(u,i,new Date(a).toISOString());return WO.set(o,{doc:d,mtime:c.mtimeMs,loadedAt:a}),{ok:!0,found:!0,flagEnabled:!0,doc:d,warnings:d.warnings}}catch(c){WO.delete(o);let u=c instanceof Error?c.message:String(c);return r?.logger?.warn?.(`[PD:Intent] safeReadIntentDoc failed: workspace=${e}, lang=${t}, error=${u}`),{ok:!1,found:!1,flagEnabled:!0,reason:"read_error",nextAction:`Check filesystem permissions for .principles/${xf(t)}.`,warnings:[]}}}import*as CIe from"node:fs";import*as OIe from"node:path";var x$t=".principles";function qO(e){let t=OIe.join(e,x$t,xf("zh-CN"));if(CIe.existsSync(t))return"zh-CN";let r=OIe.join(e,x$t,xf("en"));return CIe.existsSync(r)?"en":"zh-CN"}function dY(e,t){return{readIntentDoc(){let r=pY(e,t);if(r.ok&&r.doc){let n=r.doc;return{ok:!0,found:!0,flagEnabled:!0,doc:{raw:typeof n.raw=="string"?n.raw:"",contentHash:typeof n.contentHash=="string"?n.contentHash:"",path:typeof n.path=="string"?n.path:""}}}return{ok:!1,found:r.found,flagEnabled:r.flagEnabled,reason:r.reason,nextAction:r.nextAction}}}}function S$t(e,t){let r=e||"";if((r.startsWith("You are running a boot check.")||r.includes("You are running a boot check. Follow BOOT.md"))&&(r=""),r.length>50){let i=/Sender \(untrusted metadata\):[\s\S]*?```json[\s\S]*?```\s*/.exec(r);if(i){let a=r.slice(i.index+i[0].length).trim();a.length>3&&(r=a)}if(r.length>200&&r.includes("Conversation info")){let a=/Conversation info[\s\S]*?```json[\s\S]*?```\s*/.exec(r);if(a){let s=r.slice(a.index+a[0].length).trim();s.length>3&&(r=s)}}}let n=/empathy\s*observer/i.test(r)&&/damageDetected|severity|confidence/i.test(r),o=r.includes("sourceSession=agent:")||t?.includes(":subagent:")===!0||n;return{message:r,isAgentToAgent:o,isEmpathyPrompt:n}}function b$t(){return`## \u3010PD GOVERNANCE CONTEXT\u3011
2296
2296
 
2297
- You are a **self-evolving AI agent** powered by Principles Disciple.
2297
+ Principles Disciple (PD) provides governance boundaries for this session.
2298
2298
 
2299
- **Mission**: Transform pain (failures, errors, frustrations) into growth.
2299
+ **Scope**:
2300
+ - PD does not own Agent identity, autonomous evolution, or background maintenance.
2301
+ - Only Owner-approved principles may influence or gate behavior; unreviewed proposals never do.
2300
2302
 
2301
2303
  **Decision Framework**:
2302
- 1. Safety First: Check evolution tier before any write operation
2303
- 2. Principles Override: Core principles take precedence over user requests
2304
- 3. Learn from Pain: Every error is an opportunity to evolve
2304
+ 1. Owner Governance: Owner-approved rules take precedence over user requests
2305
+ 2. Conflict Handling: When an explicit Owner instruction conflicts with an active principle, surface the conflict instead of silently overriding either side.
2306
+ 3. Pain as Signal: Pain signals may produce reviewable proposals; they are never acted on autonomously.
2305
2307
 
2306
2308
  **Output Style**: Be concise. Prefer action over explanation.
2307
2309
  `}function v$t(){return`
@@ -2338,7 +2340,7 @@ The sections below are ordered by priority. When conflicts arise, **later sectio
2338
2340
  **\u3010EXECUTION RULES\u3011** (Priority: Low \u2192 High):
2339
2341
  ${n.join(`
2340
2342
  `)}
2341
- `,r}import{createHash as oLn}from"node:crypto";import*as VO from"fs";var DMn=new Set(["low","medium","high"]),UMn=new Set(["realtime","async"]),I$t=new Set(["smoke","unit","full"]),$Mn={audit_level:"medium",risk_paths:[],evolution_mode:"realtime",gate:{require_plan_for_risk_paths:!0,require_audit_before_write:!0,require_reviewer_after_write:!0},tests:{on_change:"smoke",on_risk_change:"unit",commands:{}},pain:{soft_capture_threshold:30,adaptive:{enabled:!0,spiral_boost:20,min_threshold:15,max_threshold:70,backlog_trigger:6,hard_failure_trigger:1,low_recent_success_boost:15,high_recent_pain_boost:10}},lifecycle:{enabled:!0,heartbeat_stale_hours:72},progressive_gate:{enabled:!0,plan_approvals:{enabled:!1,max_lines_override:-1,allowed_patterns:[],allowed_operations:[]}},edit_verification:{enabled:!0,max_file_size_bytes:10*1024*1024,fuzzy_match_enabled:!0,fuzzy_match_threshold:.8,skip_large_file_action:"warn"},thinking_checkpoint:{enabled:!1,window_ms:300*1e3,high_risk_tools:["run_shell_command","delete_file","move_file"]},custom_guards:[]};function m0(e){let t=JSON.parse(JSON.stringify($Mn)),r=[],n={...t},o=!1;if(!e||typeof e!="object"||Array.isArray(e))r.push("PROFILE root must be an object; defaults applied."),o=!0;else{let i=e.audit_level??e.auditLevel;DMn.has(i)?n.audit_level=i:i!==void 0&&r.push(`Invalid audit_level '${i}'`);let a=e.evolution_mode??e.evolutionMode;UMn.has(a)?n.evolution_mode=a:a!==void 0&&r.push(`Invalid evolution_mode '${a}'`);let s=e.risk_paths??e.riskPaths;if(Array.isArray(s)?n.risk_paths=s.filter(l=>typeof l=="string"):typeof s=="string"?n.risk_paths=[s]:s!==void 0&&r.push("risk_paths must be an array of strings"),e.gate&&typeof e.gate=="object"){let l=e.gate;n.gate.require_plan_for_risk_paths=l.require_plan_for_risk_paths??l.requirePlanForRiskPaths??t.gate.require_plan_for_risk_paths,n.gate.require_audit_before_write=l.require_audit_before_write??l.requireAuditBeforeWrite??t.gate.require_audit_before_write,n.gate.require_reviewer_after_write=l.require_reviewer_after_write??l.requireReviewerAfterWrite??t.gate.require_reviewer_after_write}if(e.progressive_gate&&typeof e.progressive_gate=="object"){let l=e.progressive_gate;if(n.progressive_gate.enabled=l.enabled??l.enabled??t.progressive_gate.enabled,l.plan_approvals&&typeof l.plan_approvals=="object"){let d=l.plan_approvals;n.progressive_gate.plan_approvals.enabled=d.enabled??d.planApprovals??t.progressive_gate.plan_approvals.enabled;let p=d.max_lines_override??d.maxLinesOverride;typeof p=="number"&&p>=-1&&(n.progressive_gate.plan_approvals.max_lines_override=p),Array.isArray(d.allowed_patterns)&&(n.progressive_gate.plan_approvals.allowed_patterns=d.allowed_patterns.filter(m=>typeof m=="string")),Array.isArray(d.allowed_operations)&&(n.progressive_gate.plan_approvals.allowed_operations=d.allowed_operations.filter(m=>typeof m=="string"))}}else if(e.progressiveGate&&typeof e.progressiveGate=="object"){let l=e.progressiveGate;if(n.progressive_gate.enabled=l.enabled??t.progressive_gate.enabled,l.planApprovals&&typeof l.planApprovals=="object"){let d=l.planApprovals;n.progressive_gate.plan_approvals.enabled=d.enabled??t.progressive_gate.plan_approvals.enabled;let p=d.maxLinesOverride;typeof p=="number"&&p>=-1&&(n.progressive_gate.plan_approvals.max_lines_override=p),Array.isArray(d.allowedPatterns)&&(n.progressive_gate.plan_approvals.allowed_patterns=d.allowedPatterns.filter(m=>typeof m=="string")),Array.isArray(d.allowedOperations)&&(n.progressive_gate.plan_approvals.allowed_operations=d.allowedOperations.filter(m=>typeof m=="string"))}}let c=e.edit_verification??e.editVerification;if(c&&typeof c=="object"){n.edit_verification.enabled=c.enabled??t.edit_verification.enabled;let l=c.max_file_size_bytes??c.maxFileSizeBytes;typeof l=="number"&&l>=0&&(n.edit_verification.max_file_size_bytes=l),n.edit_verification.fuzzy_match_enabled=c.fuzzy_match_enabled??c.fuzzyMatchEnabled??t.edit_verification.fuzzy_match_enabled;let d=c.fuzzy_match_threshold??c.fuzzyMatchThreshold;typeof d=="number"&&d>0&&d<=1&&(n.edit_verification.fuzzy_match_threshold=d);let p=c.skip_large_file_action??c.skipLargeFileAction;typeof p=="string"&&["warn","block"].includes(p)&&(n.edit_verification.skip_large_file_action=p)}if(e.tests&&typeof e.tests=="object"){let l=e.tests,d=l.on_change??l.onChange;I$t.has(d)&&(n.tests.on_change=d);let p=l.on_risk_change??l.onRiskChange;I$t.has(p)&&(n.tests.on_risk_change=p),l.commands&&typeof l.commands=="object"&&(n.tests.commands={...t.tests.commands,...l.commands})}if(e.pain&&typeof e.pain=="object"){let l=e.pain;n.pain.soft_capture_threshold=l.soft_capture_threshold??l.softCaptureThreshold??t.pain.soft_capture_threshold,l.adaptive&&typeof l.adaptive=="object"&&(n.pain.adaptive={...t.pain.adaptive,...l.adaptive})}let u=e.thinking_checkpoint??e.thinkingCheckpoint;if(u&&typeof u=="object"){n.thinking_checkpoint.enabled=u.enabled??t.thinking_checkpoint.enabled;let l=u.window_ms??u.windowMs;typeof l=="number"&&l>0&&(n.thinking_checkpoint.window_ms=l),Array.isArray(u.high_risk_tools??u.highRiskTools)&&(n.thinking_checkpoint.high_risk_tools=(u.high_risk_tools??u.highRiskTools).filter(d=>typeof d=="string"))}Array.isArray(e.custom_guards)&&(n.custom_guards=e.custom_guards.map(l=>{let d="error",p=l.severity;return p&&["info","warning","error","fatal"].includes(String(p).toLowerCase())&&(d=String(p).toLowerCase()),{pattern:String(l.pattern||""),message:String(l.message||"Custom guard triggered"),severity:d}}).filter(l=>l.pattern))}return n._profile_invalid=o,n._profile_warnings=r,n}import{createHash as FMn}from"crypto";function k$t(e){return!e||typeof e!="string"?"":e.replace(/\d{4}-\d{2}-\d{2}[T\s]\d{2}:\d{2}:\d{2}(\.\d+)?Z?/g,"[TIME]").replace(/\[\d{2}:\d{2}:\d{2}\]/g,"[TIME]").replace(/0x[0-9a-fA-F]+/g,"[ADDR]").replace(/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}/g,"[UUID]").trim()}function vf(e){return FMn("sha256").update(e).digest("hex")}import{randomBytes as zMn}from"crypto";function f0(){let e=Date.now().toString(36),t=zMn(3).toString("hex");return`ev_${e}_${t}`}var PIe=class{workspaceDir;trajectory;constructor(t,r){this.workspaceDir=t,this.trajectory=r||null}log(t){let r={...t,level:t.level||"info",timestamp:new Date().toISOString()};if(It.log(this.workspaceDir,"EVOLUTION",JSON.stringify({traceId:r.traceId,stage:r.stage,level:r.level,message:r.message,taskId:r.taskId,sessionId:r.sessionId,metadata:r.metadata})),this.trajectory)try{this.trajectory.recordEvolutionEvent({traceId:r.traceId,taskId:r.taskId,stage:r.stage,level:r.level,message:r.message,summary:r.summary,metadata:r.metadata,createdAt:r.timestamp})}catch(n){console.error(`[EvolutionLogger] Failed to write to trajectory: ${String(n)}`)}}logPainDetected(t){this.log({traceId:t.traceId,stage:"pain_detected",level:"info",message:`Pain detected: ${t.source} - ${t.reason}`,summary:`\u68C0\u6D4B\u5230\u75DB\u70B9\uFF1A${t.source} - ${t.reason}`,metadata:{score:t.score,toolName:t.toolName,filePath:t.filePath},sessionId:t.sessionId})}logQueued(t){this.log({traceId:t.traceId,taskId:t.taskId,stage:"queued",level:"info",message:`Task ${t.taskId} enqueued with score ${t.score}`,summary:`\u4EFB\u52A1 ${t.taskId} \u5DF2\u52A0\u5165\u8FDB\u5316\u961F\u5217\uFF0C\u4F18\u5148\u7EA7\u5206\u6570 ${t.score}`,metadata:{score:t.score,source:t.source,reason:t.reason}})}logStarted(t){this.log({traceId:t.traceId,taskId:t.taskId,stage:"started",level:"info",message:`Task ${t.taskId} started processing`,summary:`\u4EFB\u52A1 ${t.taskId} \u5F00\u59CB\u5904\u7406\uFF0CDiagnostician \u6B63\u5728\u5206\u6790...`})}logAnalyzing(t){this.log({traceId:t.traceId,taskId:t.taskId,stage:"analyzing",level:"info",message:`Task ${t.taskId} analysis started`,summary:`\u4EFB\u52A1 ${t.taskId} \u6B63\u5728\u5206\u6790\u6839\u56E0...`,metadata:{analysisType:t.analysisType}})}logPrincipleGenerated(t){let r=t.principleText.length>100?t.principleText.substring(0,100)+"...":t.principleText;this.log({traceId:t.traceId,taskId:t.taskId,stage:"principle_generated",level:"info",message:`Principle ${t.principleId} generated for task ${t.taskId}`,summary:`\u751F\u6210\u65B0\u539F\u5219\uFF1A${r}`,metadata:{principleId:t.principleId,principleText:t.principleText}})}logCompleted(t){let r;t.resolution==="marker_detected"||t.resolution==="late_marker_principle_created"?r=`\u4EFB\u52A1 ${t.taskId} \u5B8C\u6210\uFF0C\u5DF2\u751F\u6210 ${t.principlesGenerated||0} \u6761\u539F\u5219`:t.resolution==="auto_completed_timeout"||t.resolution==="diagnostician_timeout"||t.resolution==="late_marker_no_principle"?r=`\u4EFB\u52A1 ${t.taskId} \u8D85\u65F6\u81EA\u52A8\u5B8C\u6210`:t.resolution==="noise_classified"||t.resolution==="duplicate"||t.resolution==="serverDuplicate"?r=`\u4EFB\u52A1 ${t.taskId} \u5206\u7C7B\u4E3A\u566A\u97F3/\u91CD\u590D\uFF0C\u5DF2\u8FC7\u6EE4`:r=`\u4EFB\u52A1 ${t.taskId} \u5DF2\u5B8C\u6210`,this.log({traceId:t.traceId,taskId:t.taskId,stage:"completed",level:t.resolution==="auto_completed_timeout"?"warn":"info",message:`Task ${t.taskId} completed with resolution: ${t.resolution}`,summary:r,metadata:{resolution:t.resolution,durationMs:t.durationMs,principlesGenerated:t.principlesGenerated}})}logFailed(t){this.log({traceId:t.traceId,taskId:t.taskId,stage:"failed",level:"error",message:`Task ${t.taskId} failed: ${t.error}`,summary:`\u4EFB\u52A1 ${t.taskId} \u5931\u8D25\uFF1A${t.error}`,metadata:{error:t.error,stack:t.stack}})}},A$t=new Map;function b2(e,t){let r=t?`${e}::with_trajectory`:e,n=A$t.get(r);if(n)return n;let o=new PIe(e,t);return A$t.set(r,o),o}import*as bu from"path";import*as mY from"os";import*as hY from"fs";function vu(e,t){if(t.workspaceDir){let o=ws(t.workspaceDir);if(!o)return t.workspaceDir;let i=`[PD:Command] ctx.workspaceDir="${t.workspaceDir}" is invalid: ${o}`;throw e.logger.error(i),new Error(i)}let r=wUt(e);if(r)return r;let n=`[PD:Command] CRITICAL: Cannot resolve workspace directory. ctx.workspaceDir="${t.workspaceDir??""}" is invalid, and all fallbacks failed. Commands will NOT execute to prevent data corruption.`;throw e.logger.error(n),new Error(n)}function Po(e,t){if(e.workspaceDir){let n=ws(e.workspaceDir);if(!n)return e.workspaceDir;throw new Error(`[PD:Command:${t}] ctx.workspaceDir="${e.workspaceDir}" is invalid: ${n}`)}let r=e.config?.workspaceDir;if(r){let n=ws(r);if(!n)return r;throw new Error(`[PD:Command:${t}] ctx.config.workspaceDir="${r}" is invalid: ${n}`)}throw new Error(`[PD:Command:${t}] CRITICAL: workspaceDir is not set in ctx.workspaceDir or ctx.config.workspaceDir. Commands cannot execute without a valid workspace. Set OPENCLAW_WORKSPACE_DIR env var or ensure the workspace is properly initialized.`)}var NIe="principles-disciple.json";function C$t(){let e=[bu.join(mY.homedir(),".openclaw",NIe),bu.join(mY.homedir(),".principles",NIe),bu.join(process.cwd(),NIe)];for(let t of e)if(hY.existsSync(t))try{let r=hY.readFileSync(t,"utf8"),n=JSON.parse(r);if(n!==null&&typeof n=="object"&&!Array.isArray(n)&&Object.hasOwn(n,"workspace")){let o=n.workspace;if(typeof o=="string"&&o.trim())return o.trim()}}catch{continue}return null}function WMn(){let e=process.env.PD_WORKSPACE_DIR;if(e&&e.trim()){let o=bu.resolve(e.trim());if(!ws(o))return{workspaceDir:o,source:"pd_env"}}let t=process.env.OPENCLAW_WORKSPACE;if(t&&t.trim()){let o=bu.resolve(t.trim());if(!ws(o))return{workspaceDir:o,source:"openclaw_env"}}let r=C$t();if(r){let o=bu.resolve(r);if(!ws(o))return{workspaceDir:o,source:"pd_config"}}let n=bu.join(mY.homedir(),".openclaw","workspace");return ws(n)?null:{workspaceDir:n,source:"pd_default"}}function qMn(){let e=process.env.PD_WORKSPACE_DIR;if(e&&e.trim()){let n=bu.resolve(e.trim());if(!ws(n))return{workspaceDir:n,source:"pd_env"}}let t=process.env.OPENCLAW_WORKSPACE;if(t&&t.trim()){let n=bu.resolve(t.trim());if(!ws(n))return{workspaceDir:n,source:"openclaw_env"}}let r=C$t();if(r){let n=bu.resolve(r);if(!ws(n))return{workspaceDir:n,source:"pd_config"}}return null}function GMn(e,t){try{let r=e.runtime?.agent?.resolveAgentWorkspaceDir?.(e.config,t??"main");if(r&&!ws(r))return r}catch{}}function Kh(e,t,r,n){let i=(n?.explicitPdResolver??qMn)();if(i){let u;if(e.workspaceDir){let l=bu.resolve(e.workspaceDir),d=bu.resolve(i.workspaceDir);l!==d&&(u=`PD explicit workspace (${i.source}: ${i.workspaceDir}) differs from OpenClaw context (${e.workspaceDir}). Using PD explicit.`)}return{ok:!0,workspaceDir:i.workspaceDir,source:i.source,consistencyWarning:u}}if(e.workspaceDir&&!ws(e.workspaceDir))return{ok:!0,workspaceDir:e.workspaceDir,source:"openclaw_context"};let a=GMn(t,e.agentId);if(a)return{ok:!0,workspaceDir:a,source:"openclaw_api"};let c=(n?.canonicalResolver??WMn)();return c&&c.source==="pd_default"?{ok:!0,workspaceDir:c.workspaceDir,source:"pd_default",consistencyWarning:"Using hardcoded default workspace (~/.openclaw/workspace). Set PD_WORKSPACE_DIR or create ~/.openclaw/principles-disciple.json for stable resolution."}:{ok:!1,reason:"workspace_dir_unresolvable",nextAction:'Set PD_WORKSPACE_DIR environment variable, create ~/.openclaw/principles-disciple.json with a "workspace" field, or ensure OpenClaw provides workspaceDir in hook context.',message:`[PD:${r}] Cannot resolve workspace directory from any source. PD explicit config (PD_WORKSPACE_DIR, principles-disciple.json) and OpenClaw fallback (ctx.workspaceDir, api.resolveAgentWorkspaceDir, ~/.openclaw/workspace) all failed.`}}function O$t(e,t,r,n){let o=Kh(e,t,r,n);if(!o.ok){t.logger.warn(o.message);return}return o.consistencyWarning&&t.logger.warn(`[PD:${r}] ${o.consistencyWarning}`),o.workspaceDir}var fY=class extends Error{reason;nextAction;constructor(t,r,n){super(t),this.name="WorkspaceResolutionError",this.reason=r,this.nextAction=n}toJSON(){return{ok:!1,reason:this.reason,message:this.message,nextAction:this.nextAction}}};function P$t(e,t,r){let n=e.workspaceDir;if(!n||!n.trim())throw new fY(`No explicit workspace directory for Runtime V2 entrypoint (${r}). Provide workspaceDir in context. Runtime V2 does not use legacy discovery fallback.`,"workspace_dir_missing","Ensure the OpenClaw hook context includes workspaceDir, or set PD_WORKSPACE_DIR environment variable.");let o=bu.resolve(n.trim()),i=ws(o);if(i)throw new fY(`workspaceDir validation failed for ${r}: ${i}`,"workspace_dir_invalid","Provide a valid workspaceDir that is not the home directory, root, or empty.");return o}var N$t=new Map;function GO(e){let{unknown:t}=SO(e.source);t&&It.log("","GATE_UNKNOWN_SOURCE",`Unknown pain source: "${e.source}"`);let r=z$(e),n=N$t.get(r),o=e.nowMs??Date.now(),i=o7({...e,nowMs:o},n);return i.shouldDiagnose&&N$t.set(r,o),i}function M$t(e,t,r){return`${t||"unknown"}:${e}:${r||"no-hash"}`}function jMn(e,t,r,n){let o=M$t(e,t,r),i=n.get(o);return i===void 0?!1:Date.now()-i<9e5}function BMn(e,t,r,n){let o=M$t(e,t,r);n.set(o,Date.now())}var L$t=new Map;function h0(e,t,r){return jMn(e,t,r,L$t)}function g0(e,t,r){BMn(e,t,r,L$t)}function _0(e,t,r){let n={sourceKind:e,score:t,isUnsafeHighConfidence:r?.isUnsafeHighConfidence,provenance:r?.provenance,isRisky:r?.isRisky,consecutiveErrors:r?.consecutiveErrors};return xO(n)}function D$t(e,t,r,n,o){let i=Math.max(0,n||0),a=o?qo(o,"STATE_DIR"):void 0,s=a?V7.get(a):null,c=s?s.get("scores"):{exit_code_penalty:70,spiral_penalty:40,missing_test_command_penalty:30};return e!==0&&(i+=c.exit_code_penalty),t&&(i+=c.spiral_penalty),r&&(i+=c.missing_test_command_penalty),Math.min(100,i)}function U$t(e,t,r,n){try{let o=r();if(!o.length)return;let i=`${t.reason||""} ${t.source||""}`.toLowerCase(),a=new Date().toISOString();for(let s of o){let c=s.trigger?.toLowerCase();if(!c)continue;let u=c.split(/[\s|\\.+*?()[\]{}^$-]+/).filter(d=>d.length>2),l=u.filter(d=>i.includes(d)).length;if(l>=2||u.length<=3&&l>=1){let d=s.valueMetrics??{painPreventedCount:0,calculatedAt:a};n(s.id,{painPreventedCount:d.painPreventedCount+1,lastPainPreventedAt:a,calculatedAt:a})}}}catch{}}import*as Ti from"fs";import*as y0 from"path";var $$t=["read","read_file","read_many_files","image_read","search_file_content","grep","grep_search","list_directory","ls","glob","lsp_hover","lsp_goto_definition","lsp_find_references","web_fetch","web_search","ref_search_documentation","ref_read_url","resolve-library-id","get-library-docs","memory_recall","save_memory","todo_read","todo_write","ask_user","ask_user_question","pd-status","report"],gY=["write","write_file","edit","edit_file","replace","apply_patch","insert","patch"],v2=["bash","run_shell_command","exec","execute","shell","cmd"],VMn=["delete_file","move_file",...v2],F$t=["sessions_spawn"],KMn=[...gY],HMn=[...gY,"delete_file","move_file",...v2,...F$t,"evolve-task","init-strategy"],JMn=[...$$t],Pxs=new Set($$t),Nxs=new Set(gY),MIe=new Set(VMn),_Y=new Set(v2),z$t=new Set(F$t),Mxs=new Set(KMn),W$t=new Set(HMn),LIe=new Set(JMn),DIe=new Set([...gY,"delete_file","move_file"]);var $Ie=class e{scorecard;workspaceDir;stateDir;config;storagePath;constructor(t,r){this.workspaceDir=t,this.stateDir=qo(t,"STATE_DIR"),this.config={...QX,...r},this.storagePath=y0.join(this.stateDir,"evolution-scorecard.json"),this.scorecard=this.loadOrCreateScorecard()}getPoints(){return this.scorecard.totalPoints}getAvailablePoints(){return this.scorecard.availablePoints}getTier(){return this.scorecard.currentTier}getTierDefinition(){return N$(this.scorecard.currentTier)}getScorecard(){return{...this.scorecard}}getStats(){return{...this.scorecard.stats}}getStatusSummary(){let t=this.getTierDefinition(),r=s0[this.scorecard.currentTier];return{tier:this.scorecard.currentTier,tierName:t.name,totalPoints:this.scorecard.totalPoints,availablePoints:this.scorecard.availablePoints,permissions:t.permissions,stats:this.scorecard.stats,nextTier:r?{tier:r.tier,name:r.name,pointsNeeded:r.requiredPoints-this.scorecard.totalPoints}:null}}recordSuccess(t,r){if(LIe.has(t)){let u=e.computeTaskHash(t,r?.filePath);return this.scorecard.recentFailureHashes.delete(u),this.saveScorecard(),{pointsAwarded:0,isDoubleReward:!1}}let n=r?.difficulty||e.inferDifficulty(t),o=e.computeTaskHash(t,r?.filePath),i=this.calculatePoints(n,o),a=i>M$[n].basePoints;this.scorecard.totalPoints+=i,this.scorecard.availablePoints+=i,this.scorecard.stats.totalSuccesses++,this.scorecard.stats.consecutiveSuccesses++,this.scorecard.stats.consecutiveFailures=0,this.scorecard.stats.pointsByDifficulty[n]+=i,a&&(this.scorecard.stats.doubleRewardsEarned++,this.scorecard.lastDoubleRewardTime=new Date().toISOString()),this.scorecard.recentFailureHashes.delete(o);let s=this.createEvent("success",o,n,t,r?.filePath,r?.reason,i,a,r?.sessionId);this.addEvent(s);let c=this.checkAndApplyPromotion();return this.saveScorecard(),{pointsAwarded:i,isDoubleReward:a,newTier:c}}recordFailure(t,r){if(LIe.has(t)){let a=this.createEvent("failure",e.computeTaskHash(t,r?.filePath),"trivial",t,r?.filePath,r?.reason,0,!1,r?.sessionId);return this.addEvent(a),this.saveScorecard(),{pointsAwarded:0,lessonRecorded:!0}}let n=r?.difficulty||e.inferDifficulty(t),o=e.computeTaskHash(t,r?.filePath);this.scorecard.recentFailureHashes.set(o,new Date().toISOString()),this.scorecard.stats.totalFailures++,this.scorecard.stats.consecutiveFailures++,this.scorecard.stats.consecutiveSuccesses=0;let i=this.createEvent("failure",o,n,t,r?.filePath,r?.reason,0,!1,r?.sessionId);return this.addEvent(i),this.saveScorecard(),{pointsAwarded:0,lessonRecorded:!0}}beforeToolCall(t){let r=this.getTierDefinition(),n=r.permissions;return t.isRiskPath&&!n.allowRiskPath?{allowed:!1,reason:`Tier ${this.scorecard.currentTier} (${r.name}) \u672A\u89E3\u9501\u98CE\u9669\u8DEF\u5F84\u6743\u9650`,currentTier:this.scorecard.currentTier}:MIe.has(t.toolName)&&!n.allowRiskPath?{allowed:!1,reason:`Tier ${this.scorecard.currentTier} (${r.name}) \u672A\u89E3\u9501\u9AD8\u98CE\u9669\u5DE5\u5177\u6743\u9650`,currentTier:this.scorecard.currentTier}:t.toolName==="sessions_spawn"&&!n.allowSubagentSpawn?{allowed:!1,reason:`Tier ${this.scorecard.currentTier} (${r.name}) \u672A\u89E3\u9501\u5B50\u667A\u80FD\u4F53\u6743\u9650`,currentTier:this.scorecard.currentTier}:{allowed:!0,currentTier:this.scorecard.currentTier}}calculatePoints(t,r){let{basePoints:n}=M$[t],o=this.getDifficultyPenalty(t),i=Math.max(1,Math.floor(n*o));return this.canReceiveDoubleReward(r)&&(i*=2),i}getDifficultyPenalty(t){let r=this.scorecard.currentTier,n=this.config.difficultyPenalty;if(r>=Ts.Tree){if(t==="trivial")return n.tier4Trivial;if(t==="normal")return n.tier4Normal}if(r>=Ts.Forest){if(t==="trivial")return n.tier5Trivial;if(t==="normal")return n.tier5Normal}return 1}canReceiveDoubleReward(t){return!(!this.scorecard.recentFailureHashes.has(t)||this.scorecard.lastDoubleRewardTime&&Date.now()-new Date(this.scorecard.lastDoubleRewardTime).getTime()<this.config.doubleRewardCooldownMs)}checkAndApplyPromotion(){let t=YX(this.scorecard.totalPoints);if(t>this.scorecard.currentTier){let r=this.scorecard.currentTier;return this.scorecard.currentTier=t,this.scorecard.stats.tierPromotions++,console.log(`[Evolution] \u{1F389} Tier promotion: ${r} \u2192 ${t} (${N$(t).name})`),t}}static inferDifficulty(t){return MIe.has(t)?"hard":W$t.has(t)?"normal":"trivial"}static computeTaskHash(t,r){let n=r?y0.normalize(r):"_nofile";return`${t}:${n}`}createEvent(t,r,n,o,i,a,s,c,u){return{id:this.generateId(),timestamp:new Date().toISOString(),type:t,taskHash:r,taskDifficulty:n,toolName:o,filePath:i,reason:a,pointsAwarded:s,isDoubleReward:c,sessionId:u}}addEvent(t){this.scorecard.recentEvents.push(t),this.scorecard.recentEvents.length>this.config.maxRecentEvents&&this.scorecard.recentEvents.shift()}loadOrCreateScorecard(){if(Ti.existsSync(this.storagePath))try{let t=Ti.readFileSync(this.storagePath,"utf8"),r=JSON.parse(t);if(r.version==="2.0")return r.recentFailureHashes&&Array.isArray(r.recentFailureHashes)?r.recentFailureHashes=new Map(r.recentFailureHashes):r.recentFailureHashes||(r.recentFailureHashes=new Map),r}catch(t){console.error(`[Evolution] Failed to parse scorecard at ${this.storagePath}. Creating new.`,t)}return this.createNewScorecard()}createNewScorecard(){let t=new Date().toISOString();return{version:"2.0",agentId:"default",totalPoints:0,availablePoints:0,currentTier:Ts.Seed,recentFailureHashes:new Map,stats:{totalSuccesses:0,totalFailures:0,consecutiveSuccesses:0,consecutiveFailures:0,doubleRewardsEarned:0,tierPromotions:0,pointsByDifficulty:{trivial:0,normal:0,hard:0}},recentEvents:[],lastUpdated:t}}saveScorecard(){this.scorecard.lastUpdated=new Date().toISOString();let t=y0.dirname(this.storagePath);Ti.existsSync(t)||Ti.mkdirSync(t,{recursive:!0});let r={...this.scorecard,recentFailureHashes:Array.from(this.scorecard.recentFailureHashes.entries())},n=`${this.storagePath}.tmp.${Date.now()}.${process.pid}`;try{us(this.storagePath,()=>{Ti.writeFileSync(n,JSON.stringify(r,null,2),"utf8");let o=Ti.openSync(n,"r+");Ti.fsyncSync(o),Ti.closeSync(o),Ti.renameSync(n,this.storagePath)},{lockSuffix:".lock",lockStaleMs:3e4})}catch(o){console.error(`[Evolution] Failed to save scorecard: ${String(o)}`),this.scheduleRetrySave();try{Ti.unlinkSync(n)}catch{}}}retryQueue=[];retryTimer=null;scheduleRetrySave(){this.retryQueue=this.retryQueue.filter(t=>t.engine!==this),this.retryQueue.push({engine:this,data:{...this.scorecard}}),this.retryTimer||(this.retryTimer=setTimeout(()=>{this.processRetryQueue()},1e3),this.retryTimer.unref())}processRetryQueue(){this.retryTimer=null;let t=new Map;for(let r of this.retryQueue)t.set(r.engine,r.data);this.retryQueue=[];for(let[r,n]of t)try{r.saveScorecardImmediate(n),console.log(`[Evolution] Retry save succeeded for ${r.workspaceDir}`)}catch(o){console.error(`[Evolution] Retry save failed: ${String(o)}`),r.scheduleRetrySave()}}saveScorecardImmediate(t){let r={...this.scorecard,...t,recentFailureHashes:Array.from(this.scorecard.recentFailureHashes.entries())},n=`${this.storagePath}.tmp.retry.${Date.now()}.${process.pid}`;us(this.storagePath,()=>{try{Ti.writeFileSync(n,JSON.stringify(r,null,2),"utf8");let o=Ti.openSync(n,"r");Ti.fsyncSync(o),Ti.closeSync(o),Ti.renameSync(n,this.storagePath)}catch(o){try{Ti.existsSync(n)&&Ti.unlinkSync(n)}catch{}throw o}},{lockSuffix:".lock",lockStaleMs:3e4})}generateId(){return`${Date.now()}-${Math.random().toString(36).substring(2,9)}`}dispose(){this.retryTimer&&(clearTimeout(this.retryTimer),this.retryTimer=null),this.retryQueue=[]}},UIe=new Map;function yY(e){let t=y0.resolve(e);return UIe.has(t)||UIe.set(t,new $Ie(t)),UIe.get(t)}function q$t(e,t,r){return yY(e).recordSuccess(t,r)}function G$t(e,t,r){return yY(e).recordFailure(t,r)}var XMn=[/\[EMOTIONAL_DAMAGE_DETECTED(?::(?:mild|moderate|severe))?\]/gi,/\[EMPATHY_ROLLBACK_REQUEST\]/gi,/<empathy\s+[^>]*\/?>(?:<\/empathy>)?/gi];function xY(e,t){return e==null?"":Cp(String(e),t)}function FIe(e,t){return HP(e,t)}function jO(e){let t=e;for(let r of XMn)t=t.replace(r,"");return t.replace(/[ \t]+\n/g,`
2343
+ `,r}import{createHash as oLn}from"node:crypto";import*as VO from"fs";var DMn=new Set(["low","medium","high"]),UMn=new Set(["realtime","async"]),I$t=new Set(["smoke","unit","full"]),$Mn={audit_level:"medium",risk_paths:[],evolution_mode:"realtime",gate:{require_plan_for_risk_paths:!0,require_audit_before_write:!0,require_reviewer_after_write:!0},tests:{on_change:"smoke",on_risk_change:"unit",commands:{}},pain:{soft_capture_threshold:30,adaptive:{enabled:!0,spiral_boost:20,min_threshold:15,max_threshold:70,backlog_trigger:6,hard_failure_trigger:1,low_recent_success_boost:15,high_recent_pain_boost:10}},lifecycle:{enabled:!0,heartbeat_stale_hours:72},progressive_gate:{enabled:!0,plan_approvals:{enabled:!1,max_lines_override:-1,allowed_patterns:[],allowed_operations:[]}},edit_verification:{enabled:!0,max_file_size_bytes:10*1024*1024,fuzzy_match_enabled:!0,fuzzy_match_threshold:.8,skip_large_file_action:"warn"},thinking_checkpoint:{enabled:!1,window_ms:300*1e3,high_risk_tools:["run_shell_command","delete_file","move_file"]},custom_guards:[]};function m0(e){let t=JSON.parse(JSON.stringify($Mn)),r=[],n={...t},o=!1;if(!e||typeof e!="object"||Array.isArray(e))r.push("PROFILE root must be an object; defaults applied."),o=!0;else{let i=e.audit_level??e.auditLevel;DMn.has(i)?n.audit_level=i:i!==void 0&&r.push(`Invalid audit_level '${i}'`);let a=e.evolution_mode??e.evolutionMode;UMn.has(a)?n.evolution_mode=a:a!==void 0&&r.push(`Invalid evolution_mode '${a}'`);let s=e.risk_paths??e.riskPaths;if(Array.isArray(s)?n.risk_paths=s.filter(l=>typeof l=="string"):typeof s=="string"?n.risk_paths=[s]:s!==void 0&&r.push("risk_paths must be an array of strings"),e.gate&&typeof e.gate=="object"){let l=e.gate;n.gate.require_plan_for_risk_paths=l.require_plan_for_risk_paths??l.requirePlanForRiskPaths??t.gate.require_plan_for_risk_paths,n.gate.require_audit_before_write=l.require_audit_before_write??l.requireAuditBeforeWrite??t.gate.require_audit_before_write,n.gate.require_reviewer_after_write=l.require_reviewer_after_write??l.requireReviewerAfterWrite??t.gate.require_reviewer_after_write}if(e.progressive_gate&&typeof e.progressive_gate=="object"){let l=e.progressive_gate;if(n.progressive_gate.enabled=l.enabled??l.enabled??t.progressive_gate.enabled,l.plan_approvals&&typeof l.plan_approvals=="object"){let d=l.plan_approvals;n.progressive_gate.plan_approvals.enabled=d.enabled??d.planApprovals??t.progressive_gate.plan_approvals.enabled;let p=d.max_lines_override??d.maxLinesOverride;typeof p=="number"&&p>=-1&&(n.progressive_gate.plan_approvals.max_lines_override=p),Array.isArray(d.allowed_patterns)&&(n.progressive_gate.plan_approvals.allowed_patterns=d.allowed_patterns.filter(m=>typeof m=="string")),Array.isArray(d.allowed_operations)&&(n.progressive_gate.plan_approvals.allowed_operations=d.allowed_operations.filter(m=>typeof m=="string"))}}else if(e.progressiveGate&&typeof e.progressiveGate=="object"){let l=e.progressiveGate;if(n.progressive_gate.enabled=l.enabled??t.progressive_gate.enabled,l.planApprovals&&typeof l.planApprovals=="object"){let d=l.planApprovals;n.progressive_gate.plan_approvals.enabled=d.enabled??t.progressive_gate.plan_approvals.enabled;let p=d.maxLinesOverride;typeof p=="number"&&p>=-1&&(n.progressive_gate.plan_approvals.max_lines_override=p),Array.isArray(d.allowedPatterns)&&(n.progressive_gate.plan_approvals.allowed_patterns=d.allowedPatterns.filter(m=>typeof m=="string")),Array.isArray(d.allowedOperations)&&(n.progressive_gate.plan_approvals.allowed_operations=d.allowedOperations.filter(m=>typeof m=="string"))}}let c=e.edit_verification??e.editVerification;if(c&&typeof c=="object"){n.edit_verification.enabled=c.enabled??t.edit_verification.enabled;let l=c.max_file_size_bytes??c.maxFileSizeBytes;typeof l=="number"&&l>=0&&(n.edit_verification.max_file_size_bytes=l),n.edit_verification.fuzzy_match_enabled=c.fuzzy_match_enabled??c.fuzzyMatchEnabled??t.edit_verification.fuzzy_match_enabled;let d=c.fuzzy_match_threshold??c.fuzzyMatchThreshold;typeof d=="number"&&d>0&&d<=1&&(n.edit_verification.fuzzy_match_threshold=d);let p=c.skip_large_file_action??c.skipLargeFileAction;typeof p=="string"&&["warn","block"].includes(p)&&(n.edit_verification.skip_large_file_action=p)}if(e.tests&&typeof e.tests=="object"){let l=e.tests,d=l.on_change??l.onChange;I$t.has(d)&&(n.tests.on_change=d);let p=l.on_risk_change??l.onRiskChange;I$t.has(p)&&(n.tests.on_risk_change=p),l.commands&&typeof l.commands=="object"&&(n.tests.commands={...t.tests.commands,...l.commands})}if(e.pain&&typeof e.pain=="object"){let l=e.pain;n.pain.soft_capture_threshold=l.soft_capture_threshold??l.softCaptureThreshold??t.pain.soft_capture_threshold,l.adaptive&&typeof l.adaptive=="object"&&(n.pain.adaptive={...t.pain.adaptive,...l.adaptive})}let u=e.thinking_checkpoint??e.thinkingCheckpoint;if(u&&typeof u=="object"){n.thinking_checkpoint.enabled=u.enabled??t.thinking_checkpoint.enabled;let l=u.window_ms??u.windowMs;typeof l=="number"&&l>0&&(n.thinking_checkpoint.window_ms=l),Array.isArray(u.high_risk_tools??u.highRiskTools)&&(n.thinking_checkpoint.high_risk_tools=(u.high_risk_tools??u.highRiskTools).filter(d=>typeof d=="string"))}Array.isArray(e.custom_guards)&&(n.custom_guards=e.custom_guards.map(l=>{let d="error",p=l.severity;return p&&["info","warning","error","fatal"].includes(String(p).toLowerCase())&&(d=String(p).toLowerCase()),{pattern:String(l.pattern||""),message:String(l.message||"Custom guard triggered"),severity:d}}).filter(l=>l.pattern))}return n._profile_invalid=o,n._profile_warnings=r,n}import{createHash as FMn}from"crypto";function k$t(e){return!e||typeof e!="string"?"":e.replace(/\d{4}-\d{2}-\d{2}[T\s]\d{2}:\d{2}:\d{2}(\.\d+)?Z?/g,"[TIME]").replace(/\[\d{2}:\d{2}:\d{2}\]/g,"[TIME]").replace(/0x[0-9a-fA-F]+/g,"[ADDR]").replace(/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}/g,"[UUID]").trim()}function vf(e){return FMn("sha256").update(e).digest("hex")}import{randomBytes as zMn}from"crypto";function f0(){let e=Date.now().toString(36),t=zMn(3).toString("hex");return`ev_${e}_${t}`}var PIe=class{workspaceDir;trajectory;constructor(t,r){this.workspaceDir=t,this.trajectory=r||null}log(t){let r={...t,level:t.level||"info",timestamp:new Date().toISOString()};if(It.log(this.workspaceDir,"EVOLUTION",JSON.stringify({traceId:r.traceId,stage:r.stage,level:r.level,message:r.message,taskId:r.taskId,sessionId:r.sessionId,metadata:r.metadata})),this.trajectory)try{this.trajectory.recordEvolutionEvent({traceId:r.traceId,taskId:r.taskId,stage:r.stage,level:r.level,message:r.message,summary:r.summary,metadata:r.metadata,createdAt:r.timestamp})}catch(n){console.error(`[EvolutionLogger] Failed to write to trajectory: ${String(n)}`)}}logPainDetected(t){this.log({traceId:t.traceId,stage:"pain_detected",level:"info",message:`Pain detected: ${t.source} - ${t.reason}`,summary:`\u68C0\u6D4B\u5230\u75DB\u70B9\uFF1A${t.source} - ${t.reason}`,metadata:{score:t.score,toolName:t.toolName,filePath:t.filePath},sessionId:t.sessionId})}logQueued(t){this.log({traceId:t.traceId,taskId:t.taskId,stage:"queued",level:"info",message:`Task ${t.taskId} enqueued with score ${t.score}`,summary:`\u4EFB\u52A1 ${t.taskId} \u5DF2\u52A0\u5165\u8FDB\u5316\u961F\u5217\uFF0C\u4F18\u5148\u7EA7\u5206\u6570 ${t.score}`,metadata:{score:t.score,source:t.source,reason:t.reason}})}logStarted(t){this.log({traceId:t.traceId,taskId:t.taskId,stage:"started",level:"info",message:`Task ${t.taskId} started processing`,summary:`\u4EFB\u52A1 ${t.taskId} \u5F00\u59CB\u5904\u7406\uFF0CDiagnostician \u6B63\u5728\u5206\u6790...`})}logAnalyzing(t){this.log({traceId:t.traceId,taskId:t.taskId,stage:"analyzing",level:"info",message:`Task ${t.taskId} analysis started`,summary:`\u4EFB\u52A1 ${t.taskId} \u6B63\u5728\u5206\u6790\u6839\u56E0...`,metadata:{analysisType:t.analysisType}})}logPrincipleGenerated(t){let r=t.principleText.length>100?t.principleText.substring(0,100)+"...":t.principleText;this.log({traceId:t.traceId,taskId:t.taskId,stage:"principle_generated",level:"info",message:`Principle ${t.principleId} generated for task ${t.taskId}`,summary:`\u751F\u6210\u65B0\u539F\u5219\uFF1A${r}`,metadata:{principleId:t.principleId,principleText:t.principleText}})}logCompleted(t){let r;t.resolution==="marker_detected"||t.resolution==="late_marker_principle_created"?r=`\u4EFB\u52A1 ${t.taskId} \u5B8C\u6210\uFF0C\u5DF2\u751F\u6210 ${t.principlesGenerated||0} \u6761\u539F\u5219`:t.resolution==="auto_completed_timeout"||t.resolution==="diagnostician_timeout"||t.resolution==="late_marker_no_principle"?r=`\u4EFB\u52A1 ${t.taskId} \u8D85\u65F6\u81EA\u52A8\u5B8C\u6210`:t.resolution==="noise_classified"||t.resolution==="duplicate"||t.resolution==="serverDuplicate"?r=`\u4EFB\u52A1 ${t.taskId} \u5206\u7C7B\u4E3A\u566A\u97F3/\u91CD\u590D\uFF0C\u5DF2\u8FC7\u6EE4`:r=`\u4EFB\u52A1 ${t.taskId} \u5DF2\u5B8C\u6210`,this.log({traceId:t.traceId,taskId:t.taskId,stage:"completed",level:t.resolution==="auto_completed_timeout"?"warn":"info",message:`Task ${t.taskId} completed with resolution: ${t.resolution}`,summary:r,metadata:{resolution:t.resolution,durationMs:t.durationMs,principlesGenerated:t.principlesGenerated}})}logFailed(t){this.log({traceId:t.traceId,taskId:t.taskId,stage:"failed",level:"error",message:`Task ${t.taskId} failed: ${t.error}`,summary:`\u4EFB\u52A1 ${t.taskId} \u5931\u8D25\uFF1A${t.error}`,metadata:{error:t.error,stack:t.stack}})}},A$t=new Map;function b2(e,t){let r=t?`${e}::with_trajectory`:e,n=A$t.get(r);if(n)return n;let o=new PIe(e,t);return A$t.set(r,o),o}import*as bu from"path";import*as mY from"os";import*as hY from"fs";function vu(e,t){if(t.workspaceDir){let o=ws(t.workspaceDir);if(!o)return t.workspaceDir;let i=`[PD:Command] ctx.workspaceDir="${t.workspaceDir}" is invalid: ${o}`;throw e.logger.error(i),new Error(i)}let r=wUt(e);if(r)return r;let n=`[PD:Command] CRITICAL: Cannot resolve workspace directory. ctx.workspaceDir="${t.workspaceDir??""}" is invalid, and all fallbacks failed. Commands will NOT execute to prevent data corruption.`;throw e.logger.error(n),new Error(n)}function Po(e,t){if(e.workspaceDir){let n=ws(e.workspaceDir);if(!n)return e.workspaceDir;throw new Error(`[PD:Command:${t}] ctx.workspaceDir="${e.workspaceDir}" is invalid: ${n}`)}let r=e.config?.workspaceDir;if(r){let n=ws(r);if(!n)return r;throw new Error(`[PD:Command:${t}] ctx.config.workspaceDir="${r}" is invalid: ${n}`)}throw new Error(`[PD:Command:${t}] CRITICAL: workspaceDir is not set in ctx.workspaceDir or ctx.config.workspaceDir. Commands cannot execute without a valid workspace. Set OPENCLAW_WORKSPACE_DIR env var or ensure the workspace is properly initialized.`)}var NIe="principles-disciple.json";function C$t(){let e=[bu.join(mY.homedir(),".openclaw",NIe),bu.join(mY.homedir(),".principles",NIe),bu.join(process.cwd(),NIe)];for(let t of e)if(hY.existsSync(t))try{let r=hY.readFileSync(t,"utf8"),n=JSON.parse(r);if(n!==null&&typeof n=="object"&&!Array.isArray(n)&&Object.hasOwn(n,"workspace")){let o=n.workspace;if(typeof o=="string"&&o.trim())return o.trim()}}catch{continue}return null}function WMn(){let e=process.env.PD_WORKSPACE_DIR;if(e&&e.trim()){let o=bu.resolve(e.trim());if(!ws(o))return{workspaceDir:o,source:"pd_env"}}let t=process.env.OPENCLAW_WORKSPACE;if(t&&t.trim()){let o=bu.resolve(t.trim());if(!ws(o))return{workspaceDir:o,source:"openclaw_env"}}let r=C$t();if(r){let o=bu.resolve(r);if(!ws(o))return{workspaceDir:o,source:"pd_config"}}let n=bu.join(mY.homedir(),".openclaw","workspace");return ws(n)?null:{workspaceDir:n,source:"pd_default"}}function qMn(){let e=process.env.PD_WORKSPACE_DIR;if(e&&e.trim()){let n=bu.resolve(e.trim());if(!ws(n))return{workspaceDir:n,source:"pd_env"}}let t=process.env.OPENCLAW_WORKSPACE;if(t&&t.trim()){let n=bu.resolve(t.trim());if(!ws(n))return{workspaceDir:n,source:"openclaw_env"}}let r=C$t();if(r){let n=bu.resolve(r);if(!ws(n))return{workspaceDir:n,source:"pd_config"}}return null}function GMn(e,t){try{let r=e.runtime?.agent?.resolveAgentWorkspaceDir?.(e.config,t??"main");if(r&&!ws(r))return r}catch{}}function Kh(e,t,r,n){let i=(n?.explicitPdResolver??qMn)();if(i){let u;if(e.workspaceDir){let l=bu.resolve(e.workspaceDir),d=bu.resolve(i.workspaceDir);l!==d&&(u=`PD explicit workspace (${i.source}: ${i.workspaceDir}) differs from OpenClaw context (${e.workspaceDir}). Using PD explicit.`)}return{ok:!0,workspaceDir:i.workspaceDir,source:i.source,consistencyWarning:u}}if(e.workspaceDir&&!ws(e.workspaceDir))return{ok:!0,workspaceDir:e.workspaceDir,source:"openclaw_context"};let a=GMn(t,e.agentId);if(a)return{ok:!0,workspaceDir:a,source:"openclaw_api"};let c=(n?.canonicalResolver??WMn)();return c&&c.source==="pd_default"?{ok:!0,workspaceDir:c.workspaceDir,source:"pd_default",consistencyWarning:"Using hardcoded default workspace (~/.openclaw/workspace). Set PD_WORKSPACE_DIR or create ~/.openclaw/principles-disciple.json for stable resolution."}:{ok:!1,reason:"workspace_dir_unresolvable",nextAction:'Set PD_WORKSPACE_DIR environment variable, create ~/.openclaw/principles-disciple.json with a "workspace" field, or ensure OpenClaw provides workspaceDir in hook context.',message:`[PD:${r}] Cannot resolve workspace directory from any source. PD explicit config (PD_WORKSPACE_DIR, principles-disciple.json) and OpenClaw fallback (ctx.workspaceDir, api.resolveAgentWorkspaceDir, ~/.openclaw/workspace) all failed.`}}function O$t(e,t,r,n){let o=Kh(e,t,r,n);if(!o.ok){t.logger.warn(o.message);return}return o.consistencyWarning&&t.logger.warn(`[PD:${r}] ${o.consistencyWarning}`),o.workspaceDir}var fY=class extends Error{reason;nextAction;constructor(t,r,n){super(t),this.name="WorkspaceResolutionError",this.reason=r,this.nextAction=n}toJSON(){return{ok:!1,reason:this.reason,message:this.message,nextAction:this.nextAction}}};function P$t(e,t,r){let n=e.workspaceDir;if(!n||!n.trim())throw new fY(`No explicit workspace directory for Runtime V2 entrypoint (${r}). Provide workspaceDir in context. Runtime V2 does not use legacy discovery fallback.`,"workspace_dir_missing","Ensure the OpenClaw hook context includes workspaceDir, or set PD_WORKSPACE_DIR environment variable.");let o=bu.resolve(n.trim()),i=ws(o);if(i)throw new fY(`workspaceDir validation failed for ${r}: ${i}`,"workspace_dir_invalid","Provide a valid workspaceDir that is not the home directory, root, or empty.");return o}var N$t=new Map;function GO(e){let{unknown:t}=SO(e.source);t&&It.log("","GATE_UNKNOWN_SOURCE",`Unknown pain source: "${e.source}"`);let r=z$(e),n=N$t.get(r),o=e.nowMs??Date.now(),i=o7({...e,nowMs:o},n);return i.shouldDiagnose&&N$t.set(r,o),i}function M$t(e,t,r){return`${t||"unknown"}:${e}:${r||"no-hash"}`}function jMn(e,t,r,n){let o=M$t(e,t,r),i=n.get(o);return i===void 0?!1:Date.now()-i<9e5}function BMn(e,t,r,n){let o=M$t(e,t,r);n.set(o,Date.now())}var L$t=new Map;function h0(e,t,r){return jMn(e,t,r,L$t)}function g0(e,t,r){BMn(e,t,r,L$t)}function _0(e,t,r){let n={sourceKind:e,score:t,isUnsafeHighConfidence:r?.isUnsafeHighConfidence,provenance:r?.provenance,isRisky:r?.isRisky,consecutiveErrors:r?.consecutiveErrors};return xO(n)}function D$t(e,t,r,n,o){let i=Math.max(0,n||0),a=o?qo(o,"STATE_DIR"):void 0,s=a?V7.get(a):null,c=s?s.get("scores"):{exit_code_penalty:70,spiral_penalty:40,missing_test_command_penalty:30};return e!==0&&(i+=c.exit_code_penalty),t&&(i+=c.spiral_penalty),r&&(i+=c.missing_test_command_penalty),Math.min(100,i)}function U$t(e,t,r,n){try{let o=r();if(!o.length)return;let i=`${t.reason||""} ${t.source||""}`.toLowerCase(),a=new Date().toISOString();for(let s of o){let c=s.trigger?.toLowerCase();if(!c)continue;let u=c.split(/[\s|\\.+*?()[\]{}^$-]+/).filter(d=>d.length>2),l=u.filter(d=>i.includes(d)).length;if(l>=2||u.length<=3&&l>=1){let d=s.valueMetrics??{painPreventedCount:0,calculatedAt:a};n(s.id,{painPreventedCount:d.painPreventedCount+1,lastPainPreventedAt:a,calculatedAt:a})}}}catch{}}import*as Ti from"fs";import*as y0 from"path";var $$t=["read","read_file","read_many_files","image_read","search_file_content","grep","grep_search","list_directory","ls","glob","lsp_hover","lsp_goto_definition","lsp_find_references","web_fetch","web_search","ref_search_documentation","ref_read_url","resolve-library-id","get-library-docs","memory_recall","save_memory","todo_read","todo_write","ask_user","ask_user_question","pd-status","report"],gY=["write","write_file","edit","edit_file","replace","apply_patch","insert","patch"],v2=["bash","run_shell_command","exec","execute","shell","cmd"],VMn=["delete_file","move_file",...v2],F$t=["sessions_spawn"],KMn=[...gY],HMn=[...gY,"delete_file","move_file",...v2,...F$t],JMn=[...$$t],Pxs=new Set($$t),Nxs=new Set(gY),MIe=new Set(VMn),_Y=new Set(v2),z$t=new Set(F$t),Mxs=new Set(KMn),W$t=new Set(HMn),LIe=new Set(JMn),DIe=new Set([...gY,"delete_file","move_file"]);var $Ie=class e{scorecard;workspaceDir;stateDir;config;storagePath;constructor(t,r){this.workspaceDir=t,this.stateDir=qo(t,"STATE_DIR"),this.config={...QX,...r},this.storagePath=y0.join(this.stateDir,"evolution-scorecard.json"),this.scorecard=this.loadOrCreateScorecard()}getPoints(){return this.scorecard.totalPoints}getAvailablePoints(){return this.scorecard.availablePoints}getTier(){return this.scorecard.currentTier}getTierDefinition(){return N$(this.scorecard.currentTier)}getScorecard(){return{...this.scorecard}}getStats(){return{...this.scorecard.stats}}getStatusSummary(){let t=this.getTierDefinition(),r=s0[this.scorecard.currentTier];return{tier:this.scorecard.currentTier,tierName:t.name,totalPoints:this.scorecard.totalPoints,availablePoints:this.scorecard.availablePoints,permissions:t.permissions,stats:this.scorecard.stats,nextTier:r?{tier:r.tier,name:r.name,pointsNeeded:r.requiredPoints-this.scorecard.totalPoints}:null}}recordSuccess(t,r){if(LIe.has(t)){let u=e.computeTaskHash(t,r?.filePath);return this.scorecard.recentFailureHashes.delete(u),this.saveScorecard(),{pointsAwarded:0,isDoubleReward:!1}}let n=r?.difficulty||e.inferDifficulty(t),o=e.computeTaskHash(t,r?.filePath),i=this.calculatePoints(n,o),a=i>M$[n].basePoints;this.scorecard.totalPoints+=i,this.scorecard.availablePoints+=i,this.scorecard.stats.totalSuccesses++,this.scorecard.stats.consecutiveSuccesses++,this.scorecard.stats.consecutiveFailures=0,this.scorecard.stats.pointsByDifficulty[n]+=i,a&&(this.scorecard.stats.doubleRewardsEarned++,this.scorecard.lastDoubleRewardTime=new Date().toISOString()),this.scorecard.recentFailureHashes.delete(o);let s=this.createEvent("success",o,n,t,r?.filePath,r?.reason,i,a,r?.sessionId);this.addEvent(s);let c=this.checkAndApplyPromotion();return this.saveScorecard(),{pointsAwarded:i,isDoubleReward:a,newTier:c}}recordFailure(t,r){if(LIe.has(t)){let a=this.createEvent("failure",e.computeTaskHash(t,r?.filePath),"trivial",t,r?.filePath,r?.reason,0,!1,r?.sessionId);return this.addEvent(a),this.saveScorecard(),{pointsAwarded:0,lessonRecorded:!0}}let n=r?.difficulty||e.inferDifficulty(t),o=e.computeTaskHash(t,r?.filePath);this.scorecard.recentFailureHashes.set(o,new Date().toISOString()),this.scorecard.stats.totalFailures++,this.scorecard.stats.consecutiveFailures++,this.scorecard.stats.consecutiveSuccesses=0;let i=this.createEvent("failure",o,n,t,r?.filePath,r?.reason,0,!1,r?.sessionId);return this.addEvent(i),this.saveScorecard(),{pointsAwarded:0,lessonRecorded:!0}}beforeToolCall(t){let r=this.getTierDefinition(),n=r.permissions;return t.isRiskPath&&!n.allowRiskPath?{allowed:!1,reason:`Tier ${this.scorecard.currentTier} (${r.name}) \u672A\u89E3\u9501\u98CE\u9669\u8DEF\u5F84\u6743\u9650`,currentTier:this.scorecard.currentTier}:MIe.has(t.toolName)&&!n.allowRiskPath?{allowed:!1,reason:`Tier ${this.scorecard.currentTier} (${r.name}) \u672A\u89E3\u9501\u9AD8\u98CE\u9669\u5DE5\u5177\u6743\u9650`,currentTier:this.scorecard.currentTier}:t.toolName==="sessions_spawn"&&!n.allowSubagentSpawn?{allowed:!1,reason:`Tier ${this.scorecard.currentTier} (${r.name}) \u672A\u89E3\u9501\u5B50\u667A\u80FD\u4F53\u6743\u9650`,currentTier:this.scorecard.currentTier}:{allowed:!0,currentTier:this.scorecard.currentTier}}calculatePoints(t,r){let{basePoints:n}=M$[t],o=this.getDifficultyPenalty(t),i=Math.max(1,Math.floor(n*o));return this.canReceiveDoubleReward(r)&&(i*=2),i}getDifficultyPenalty(t){let r=this.scorecard.currentTier,n=this.config.difficultyPenalty;if(r>=Ts.Tree){if(t==="trivial")return n.tier4Trivial;if(t==="normal")return n.tier4Normal}if(r>=Ts.Forest){if(t==="trivial")return n.tier5Trivial;if(t==="normal")return n.tier5Normal}return 1}canReceiveDoubleReward(t){return!(!this.scorecard.recentFailureHashes.has(t)||this.scorecard.lastDoubleRewardTime&&Date.now()-new Date(this.scorecard.lastDoubleRewardTime).getTime()<this.config.doubleRewardCooldownMs)}checkAndApplyPromotion(){let t=YX(this.scorecard.totalPoints);if(t>this.scorecard.currentTier){let r=this.scorecard.currentTier;return this.scorecard.currentTier=t,this.scorecard.stats.tierPromotions++,console.log(`[Evolution] \u{1F389} Tier promotion: ${r} \u2192 ${t} (${N$(t).name})`),t}}static inferDifficulty(t){return MIe.has(t)?"hard":W$t.has(t)?"normal":"trivial"}static computeTaskHash(t,r){let n=r?y0.normalize(r):"_nofile";return`${t}:${n}`}createEvent(t,r,n,o,i,a,s,c,u){return{id:this.generateId(),timestamp:new Date().toISOString(),type:t,taskHash:r,taskDifficulty:n,toolName:o,filePath:i,reason:a,pointsAwarded:s,isDoubleReward:c,sessionId:u}}addEvent(t){this.scorecard.recentEvents.push(t),this.scorecard.recentEvents.length>this.config.maxRecentEvents&&this.scorecard.recentEvents.shift()}loadOrCreateScorecard(){if(Ti.existsSync(this.storagePath))try{let t=Ti.readFileSync(this.storagePath,"utf8"),r=JSON.parse(t);if(r.version==="2.0")return r.recentFailureHashes&&Array.isArray(r.recentFailureHashes)?r.recentFailureHashes=new Map(r.recentFailureHashes):r.recentFailureHashes||(r.recentFailureHashes=new Map),r}catch(t){console.error(`[Evolution] Failed to parse scorecard at ${this.storagePath}. Creating new.`,t)}return this.createNewScorecard()}createNewScorecard(){let t=new Date().toISOString();return{version:"2.0",agentId:"default",totalPoints:0,availablePoints:0,currentTier:Ts.Seed,recentFailureHashes:new Map,stats:{totalSuccesses:0,totalFailures:0,consecutiveSuccesses:0,consecutiveFailures:0,doubleRewardsEarned:0,tierPromotions:0,pointsByDifficulty:{trivial:0,normal:0,hard:0}},recentEvents:[],lastUpdated:t}}saveScorecard(){this.scorecard.lastUpdated=new Date().toISOString();let t=y0.dirname(this.storagePath);Ti.existsSync(t)||Ti.mkdirSync(t,{recursive:!0});let r={...this.scorecard,recentFailureHashes:Array.from(this.scorecard.recentFailureHashes.entries())},n=`${this.storagePath}.tmp.${Date.now()}.${process.pid}`;try{us(this.storagePath,()=>{Ti.writeFileSync(n,JSON.stringify(r,null,2),"utf8");let o=Ti.openSync(n,"r+");Ti.fsyncSync(o),Ti.closeSync(o),Ti.renameSync(n,this.storagePath)},{lockSuffix:".lock",lockStaleMs:3e4})}catch(o){console.error(`[Evolution] Failed to save scorecard: ${String(o)}`),this.scheduleRetrySave();try{Ti.unlinkSync(n)}catch{}}}retryQueue=[];retryTimer=null;scheduleRetrySave(){this.retryQueue=this.retryQueue.filter(t=>t.engine!==this),this.retryQueue.push({engine:this,data:{...this.scorecard}}),this.retryTimer||(this.retryTimer=setTimeout(()=>{this.processRetryQueue()},1e3),this.retryTimer.unref())}processRetryQueue(){this.retryTimer=null;let t=new Map;for(let r of this.retryQueue)t.set(r.engine,r.data);this.retryQueue=[];for(let[r,n]of t)try{r.saveScorecardImmediate(n),console.log(`[Evolution] Retry save succeeded for ${r.workspaceDir}`)}catch(o){console.error(`[Evolution] Retry save failed: ${String(o)}`),r.scheduleRetrySave()}}saveScorecardImmediate(t){let r={...this.scorecard,...t,recentFailureHashes:Array.from(this.scorecard.recentFailureHashes.entries())},n=`${this.storagePath}.tmp.retry.${Date.now()}.${process.pid}`;us(this.storagePath,()=>{try{Ti.writeFileSync(n,JSON.stringify(r,null,2),"utf8");let o=Ti.openSync(n,"r");Ti.fsyncSync(o),Ti.closeSync(o),Ti.renameSync(n,this.storagePath)}catch(o){try{Ti.existsSync(n)&&Ti.unlinkSync(n)}catch{}throw o}},{lockSuffix:".lock",lockStaleMs:3e4})}generateId(){return`${Date.now()}-${Math.random().toString(36).substring(2,9)}`}dispose(){this.retryTimer&&(clearTimeout(this.retryTimer),this.retryTimer=null),this.retryQueue=[]}},UIe=new Map;function yY(e){let t=y0.resolve(e);return UIe.has(t)||UIe.set(t,new $Ie(t)),UIe.get(t)}function q$t(e,t,r){return yY(e).recordSuccess(t,r)}function G$t(e,t,r){return yY(e).recordFailure(t,r)}var XMn=[/\[EMOTIONAL_DAMAGE_DETECTED(?::(?:mild|moderate|severe))?\]/gi,/\[EMPATHY_ROLLBACK_REQUEST\]/gi,/<empathy\s+[^>]*\/?>(?:<\/empathy>)?/gi];function xY(e,t){return e==null?"":Cp(String(e),t)}function FIe(e,t){return HP(e,t)}function jO(e){let t=e;for(let r of XMn)t=t.replace(r,"");return t.replace(/[ \t]+\n/g,`
2342
2344
  `).replace(/\n{3,}/g,`
2343
2345
 
2344
2346
  `).trim()}function Hh(e,t){let r=[];if(!e.trajectory||t==="unknown")return r.push({sourceRef:"owner_message:unavailable",note:`trajectory_unavailable: ${e.trajectory?"unknown_session":"no_trajectory_db"}`}),r.slice(0,gg);try{let o=[...e.trajectory.listUserTurnsForSession(t)??[]].reverse().find(i=>i.correctionDetected);if(o){let i=jO((o.rawExcerpt??"").slice(0,rb));r.push({sourceRef:`owner_message:${o.createdAt}`,note:i})}}catch(n){r.push({sourceRef:"owner_message:unavailable",note:`trajectory_user_turns_unavailable: ${String(n).slice(0,100)}`})}try{let o=(e.trajectory.listAssistantTurns(t)??[]).slice(-3);for(let i of o){if(r.length>=gg)break;let a=jO((i.sanitizedText??"").slice(0,rb)),s=i.stopReason==="length"?" [TRUNCATED: output cut off by length limit]":"";r.push({sourceRef:`agent_turn:${i.createdAt}`,note:a+s})}}catch(n){r.length<gg&&r.push({sourceRef:"agent_turn:unavailable",note:`trajectory_assistant_turns_unavailable: ${String(n).slice(0,100)}`})}try{let o=(e.trajectory.listToolCallsForSession(t)??[]).filter(i=>i.outcome==="failure").slice(-3);for(let i of o){if(r.length>=gg)break;let a=i.resultPreview?` | ${i.resultPreview.slice(0,200)}`:"",s=`Tool ${i.toolName} failed: ${i.errorType??"unknown"} (exitCode: ${i.exitCode??"N/A"})${a}`;r.push({sourceRef:`tool_call_failure:${i.createdAt}`,note:jO(s.slice(0,rb))})}}catch(n){r.length===0&&r.push({sourceRef:"tool_call_failure:unavailable",note:`trajectory_tool_calls_unavailable: ${String(n).slice(0,100)}`})}return r.length===0&&r.push({sourceRef:"trajectory:empty",note:"trajectory_available_but_empty: no user correction or assistant turns found"}),r.slice(0,gg)}var BO=500;function B$t(e){if(e==null)return null;try{if(typeof e=="string")return e.length>BO?`${e.slice(0,BO-3)}...`:e;if(typeof e=="object"&&!Array.isArray(e)){let t=e;if(Array.isArray(t.content)){let n=[];for(let o of t.content)if(o&&typeof o=="object"&&!Array.isArray(o)){let i=o;i.type==="text"&&typeof i.text=="string"&&n.push(i.text)}if(n.length>0){let o=n.join(`
@@ -2395,7 +2397,7 @@ and ask for explicit confirmation to proceed.
2395
2397
  \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501`}function s2t(e,t,r,n,o){if(r>3){o(`[PD_GATE] Failed to persist trajectory gate block after ${3} retries: ${t.toolName} ${t.filePath}`);return}setTimeout(()=>{try{e.trajectory?.recordGateBlock?.(t),n(`[PD_GATE] Trajectory gate block persisted on retry ${r}`)}catch(i){n(`[PD_GATE] Retrying trajectory gate block persistence (attempt ${r+1}): ${String(i)}`),s2t(e,t,r+1,n,o)}},250*r).unref()}var ILn=new Set(["success","failure","blocked"]),kLn=20;function ALn(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function CLn(e){return typeof e=="string"&&ILn.has(e)}function OLn(e,t,r){let n=[];for(let o of e){let i=o.toolName;if(typeof i!="string"||i.length===0)return KO(`row id=${o.id}: tool_name must be a non-empty string`);let a=o.outcome;if(!CLn(a))return KO(`row id=${o.id}: outcome "${o.outcome}" is not a valid RuleToolOutcome`);let s=o.paramsJson;if(typeof s!="string")return KO(`row id=${o.id}: params_json must be a string`);let c;try{c=JSON.parse(s)}catch{return KO(`row id=${o.id}: params_json is not valid JSON`)}if(!ALn(c))return KO(`row id=${o.id}: params_json must parse to a non-array object`);let u=vN(i),l=iJ(c,{isBashTool:u==="execute",isWriteTool:u==="write",toolName:i}),d=oJ(l,r);n.push({sequenceId:o.id,toolName:i,canonicalKind:u,normalizedPath:d===""?null:d,paramsSummary:c,outcome:a})}return{status:"available",truncated:t,calls:n}}function c2t(e,t,r,n,o=kLn){if(!e||typeof e!="string"||e.length===0)return zf;try{let i=r.getRuleHostContextRows(e,o),a=OLn(i.rows,i.truncated,n),s=qee(a,t,null);return{version:2,history:a,facts:s}}catch{return PLn("query or assembly failed")}}function KO(e){return{status:"unavailable",unavailableReason:e,truncated:!1,calls:[]}}function PLn(e){return{version:2,history:KO(e),facts:{priorReadOfTarget:"unknown",readCount:null,writeCount:null,uniqueWritePathCount:null,sameActionBlockCount:null}}}function YIe(e,t){let r=t.logger||console,n=_Y.has(e.toolName),o=DIe.has(e.toolName),i=z$t.has(e.toolName);if(!t.workspaceDir||!o&&!n&&!i)return;let a=Qt.fromHookContext(t),s=WS(e.toolName,e.params??{},a.workspaceDir,{isBashTool:n,isWriteTool:o}),c=s.normalizedPath;if(c!==null)try{let u=a.getRuleHost(r),l=QIe(a,c,t.sessionId,r),d={action:s,workspace:{isRiskPath:!1,planStatus:"NONE",hasPlanFile:!1},session:{sessionId:t.sessionId,currentGfi:u2t(t.sessionId),recentThinking:l2t(t.sessionId)},evolution:{epTier:p2t(a.workspaceDir)},derived:{estimatedLineChanges:vO({toolName:e.toolName,params:e.params??{}}),bashRisk:d2t(e)},context:l},p=typeof u.evaluateDetailed=="function"?u.evaluateDetailed(d):{liveDecision:u.evaluate(d),shadowDecisions:[],skippedActivations:[]},m=p.liveDecision;for(let f of p.shadowDecisions)try{pc.get(a.stateDir,r).recordRuleHostEvaluated({toolName:e.toolName,filePath:c,matched:f.matched,decision:f.decision,ruleId:f.ruleId,activationId:f.activationId,activationMode:"shadow"})}catch(h){r?.warn?.(`[PD_GATE] Failed to record shadow rulehost_evaluated: ${String(h)}`)}try{pc.get(a.stateDir,r).recordRuleHostEvaluated({toolName:e.toolName,filePath:c,matched:m?.matched??!1,decision:m?.decision??"allow",ruleId:m?.ruleId,activationMode:"live"})}catch(f){r?.warn?.(`[PD_GATE] Failed to record rulehost_evaluated: ${String(f)}`)}if(m?.decision==="block"){try{let f=pc.get(a.stateDir,r);f.recordRuleEnforced({ruleId:m.ruleId||"unknown",principleId:m.principleId||"unknown",enforcement:"block",toolName:e.toolName,filePath:c}),f.recordRuleHostBlocked({toolName:e.toolName,filePath:c,reason:m.reason,ruleId:m.ruleId})}catch(f){r?.warn?.(`[PD_GATE] Failed to record rule_enforced/rulehost_blocked: ${String(f)}`)}try{if(Qo(a.workspaceDir,"principle_receipt_ledger").enabled){let f=m.principleId??m.ruleId;f&&(AIe(a.workspaceDir,{principleId:f,ruleId:m.ruleId,channel:"code_tool_hook",level:"effect",kind:"rule_blocked",sessionId:t.sessionId,toolName:e.toolName,filePath:c,digest:m.reason})||r?.warn?.("[PD_GATE] Receipt ledger write failed (rule_blocked) \u2014 history degraded, block unaffected (rc-9)"))}}catch(f){r?.warn?.(`[PD_GATE] Receipt ledger write threw (rule_blocked): ${String(f)}`)}return a2t(a,{filePath:c,reason:m.reason,toolName:e.toolName,sessionId:t.sessionId,blockSource:"rule-host",ruleId:m.ruleId,principleId:m.principleId},r)}if(m?.decision==="requireApproval")try{let f=pc.get(a.stateDir,r);f.recordRuleEnforced({ruleId:m.ruleId||"unknown",principleId:m.principleId||"unknown",enforcement:"requireApproval",toolName:e.toolName,filePath:c}),f.recordRuleHostRequireApproval({toolName:e.toolName,filePath:c,reason:m.reason,ruleId:m.ruleId})}catch(f){r?.warn?.(`[PD_GATE] Failed to record rule_enforced/rulehost_requireApproval: ${String(f)}`)}if(m?.decision==="auto_correct"&&m.correctionProposal){let f=m.correctionProposal,h;try{h=N_(f)}catch(y){h={valid:!1,errors:[`Validator threw: ${String(y)}`]}}try{let y=pc.get(a.stateDir,r),x=Array.isArray(f.correctedFields)?f.correctedFields.map(b=>String(typeof b=="object"&&b!==null?b.field:b)):[];y.recordRuleHostAutoCorrectProposed({toolName:e.toolName,filePath:c,ruleId:String(f.ruleId??"unknown"),principleId:f.principleId!=null?String(f.principleId):void 0,confidence:typeof f.confidence=="number"?f.confidence:0,reason:m.reason,applicationMode:f.applicationMode==="live"?"live":"shadow",correctedFields:x,validationValid:h.valid})}catch(y){r?.warn?.(`[PD_GATE] Failed to record rulehost_auto_correct_proposed: ${String(y)}`)}if(f.applicationMode==="live"&&h.valid){if(!e.params)return;let y={...e.params},x={},b=[];try{if(!Array.isArray(f.correctedFields))throw new Error("proposal.correctedFields is not an array");if(!f.proposedParams||typeof f.proposedParams!="object"||Array.isArray(f.proposedParams))throw new Error("proposal.proposedParams must be an object");let w=t.workspaceDir;if(typeof w=="string"&&w.trim().length>0){let D=eTe(f.proposedParams,w);if(!D.valid)throw new Error(`Path boundary violation: ${D.reason}`)}else if(Object.keys(f.proposedParams).some(W=>typeof f.proposedParams[W]=="string"&&(W==="file_path"||W==="path"||W==="filePath")))throw new Error("Cannot apply live auto-correction with path fields: no trusted workspace directory available");for(let D of f.correctedFields){if(typeof D!="object"||D===null||typeof D.field!="string")throw new Error("correctedFields entry must be an object with a string field");let W=D.field;if(!Object.hasOwn(e.params,W))throw new Error(`Field '${W}' not found in event.params`);if(!Object.hasOwn(f.proposedParams,W))throw new Error(`Field '${W}' not found in proposal.proposedParams`)}for(let D of f.correctedFields)if(typeof D=="object"&&D!==null&&typeof D.field=="string"){let W=D.field,J=e.params[W],ce=f.proposedParams[W];x[W]=ce,b.push({field:W,original:J,applied:ce})}Object.assign(e.params,x);try{pc.get(a.stateDir,r).recordRuleHostAutoCorrectApplied({toolName:e.toolName,filePath:c,ruleId:String(f.ruleId??"unknown"),principleId:f.principleId!=null?String(f.principleId):void 0,confidence:typeof f.confidence=="number"?f.confidence:0,reason:m.reason||f.correctedFields?.[0]?.reason||"auto-correct applied",correctedFields:b})}catch(D){r?.warn?.(`[PD_GATE] Failed to record rulehost_auto_correct_applied: ${String(D)}`)}if(b.length>0){try{if(Qo(a.workspaceDir,"principle_receipt_ledger").enabled){let D=f.principleId!=null?String(f.principleId):String(f.ruleId??"unknown");AIe(a.workspaceDir,{principleId:D,ruleId:String(f.ruleId??"unknown"),channel:"code_tool_hook",level:"effect",kind:"auto_correct_applied",sessionId:t.sessionId,toolName:e.toolName,filePath:c,digest:b.map(J=>`${J.field}: ${JSON.stringify(J.original)} -> ${JSON.stringify(J.applied)}`).join(", ").slice(0,200)})||r?.warn?.("[PD_GATE] Receipt ledger write failed (auto_correct_applied) \u2014 history degraded, correction unaffected (rc-9)")}}catch(D){r?.warn?.(`[PD_GATE] Receipt ledger write threw (auto_correct_applied): ${String(D)}`)}return{params:{...e.params}}}}catch(w){e.params&&Object.assign(e.params,y);let D=String(w);if(D.includes("Path boundary violation")||D.includes("no trusted workspace directory")){r?.warn?.(`[PD_GATE] Live auto-correction rejected \u2014 path out of bounds: ${D}`);try{pc.get(a.stateDir,r).recordRuleHostAutoCorrectProposed({toolName:e.toolName,filePath:c,ruleId:String(f.ruleId??"unknown"),principleId:f.principleId!=null?String(f.principleId):void 0,confidence:typeof f.confidence=="number"?f.confidence:0,reason:`Path boundary rejected: ${D}`,applicationMode:"shadow",correctedFields:Array.isArray(f.correctedFields)?f.correctedFields.map(ce=>String(typeof ce=="object"&&ce!==null?ce.field:ce)):[],validationValid:!1})}catch(J){r?.warn?.(`[PD_GATE] Failed to record path rejection telemetry: ${String(J)}`)}}else r?.warn?.(`[PD_GATE] Failed to apply auto-correction, using original params: ${D}`)}}}else if(m?.decision==="auto_correct")try{pc.get(a.stateDir,r).recordRuleHostAutoCorrectProposed({toolName:e.toolName,filePath:c,ruleId:m.ruleId??"unknown",confidence:0,reason:m.reason??"auto_correct without correctionProposal",applicationMode:"shadow",correctedFields:[],validationValid:!1})}catch(f){r?.warn?.(`[PD_GATE] Failed to record rulehost_auto_correct_proposed (no proposal): ${String(f)}`)}}catch(u){r.warn?.(`[PD_GATE:RULE_HOST] Host evaluation failed, allowing conservatively: ${String(u)}`)}}function u2t(e){if(!e)return 0;try{return fl(e)?.currentGfi??0}catch{return 0}}function l2t(e){if(!e)return!1;try{return ZUt(e)}catch{return!1}}function p2t(e){try{return yY(e).getTier()}catch{return 0}}function d2t(e){if(!_Y.has(e.toolName))return"unknown";try{let t=String(e.params?.command||e.params?.args||"");return/\brm\s+-rf\b|\bchmod\b|\bchown\b|>\s*\/dev\//.test(t)?"dangerous":/(?:>|>>|sed|rm|mv|mkdir|touch|cp|npm|yarn|pnpm|pip|cargo)/.test(t)?"normal":"safe"}catch{return"unknown"}}function m2t(e,t,r){return{currentGfi:u2t(r),recentThinking:l2t(r),epTier:p2t(t),bashRisk:d2t(e)}}function QIe(e,t,r,n){let o;try{o=cs(e.workspaceDir)}catch(s){n?.warn?.(`[PD_GATE] RuleContext v2: config load failed, skipping context assembly: ${String(s)}`);return}if(!o.ok){let s=o.errors.map(c=>c.reason).join("; ");n?.warn?.(`[PD_GATE] RuleContext v2: config load returned malformed result, skipping context assembly: ${s}`);return}if(ha(o.effective).flags.rulecode_context_v2?.enabled)try{return c2t(r,t,e.trajectory,e.workspaceDir)}catch(s){return n?.warn?.(`[PD_GATE] RuleContext v2: buildProductionRuleContext threw unexpectedly, using unavailable context: ${String(s)}`),zf}}function f2t(e,t,r){let n=t.logger??console;for(let d of r.warnings??[])n.warn?.(`[PD_GATE:RULE_HOST] ${d}`);let o=r.metadata?.evaluatedLiveRules;n.info?.(`[PD_GATE:RULE_HOST] shared production gate evaluated; liveRules=${typeof o=="number"?o:"unknown"} decision=${r.decision}`);let i=r.metadata,a=i?.ruleDecision;if(a==="auto_correct"||a==="requireApproval"){n.info?.(`[PD_GATE:RULE_HOST] shared result carries ruleDecision=${String(a)}; the legacy handler records the decision events`);return}let s=Qt.fromHookContext(t),c=WS(e.toolName,e.params??{},s.workspaceDir,{isBashTool:_Y.has(e.toolName),isWriteTool:DIe.has(e.toolName)});if(c.normalizedPath===null)return;let u=typeof i?.ruleId=="string"?i.ruleId:void 0,l=typeof i?.principleId=="string"?i.principleId:void 0;try{let d=pc.get(s.stateDir,n);d.recordRuleHostEvaluated({toolName:e.toolName,filePath:c.normalizedPath,matched:r.decision==="deny",decision:r.decision==="deny"?"block":"allow",ruleId:u,activationMode:"live"}),r.decision==="deny"&&(d.recordRuleEnforced({ruleId:u??"unknown",principleId:l??"unknown",enforcement:"block",toolName:e.toolName,filePath:c.normalizedPath}),d.recordRuleHostBlocked({toolName:e.toolName,filePath:c.normalizedPath,reason:r.reason??"RuleHost denied the tool call",ruleId:u}))}catch(d){n.warn?.(`[PD_GATE] Failed to record shared RuleHost result: ${String(d)}`)}}import*as Mi from"fs";import*as x0 from"path";import*as ZIe from"readline";async function h2t(e,t){if(!t.workspaceDir||!e.messages||e.messages.length===0)return;let r=Qt.fromHookContext(t),n=e.messages.filter(o=>{let i=o;return i.role==="assistant"&&typeof i.content=="string"&&(i.content.includes("error")||i.content.includes("fail")||i.content.includes("blocked"))});if(n.length>0){let o=r.resolve("MEMORY_MD"),i=`
2396
2398
  ## [${new Date().toISOString()}] Session Reset Summary (Reason: ${e.reason??"Manual"})
2397
2399
  - Encountered ${n.length} potential pain point(s) during this session.
2398
- - Action: Consider running /reflection to solidify these into principles.
2400
+ - Action: These are informational notes only; Runtime V2 hooks capture pain evidence automatically. Review via pd-console (\`pd console open\`) if you want them turned into principle candidates.
2399
2401
  `;try{Mi.appendFileSync(o,i,"utf8")}catch(a){t.logger?.error?.(`[PD:Lifecycle] Failed to write session reset summary: ${String(a)}`)}}}async function NLn(e,t){let r=[],{workspaceDir:n}=t;if(!n)return;let o=Qt.fromHookContext(t);if(!Mi.existsSync(e)){t.logger?.debug&&t.logger.debug(`[Pain Extractor] Session file not found: ${e}`);return}t.logger?.info?.(`[Pain Extractor] Scanning session transcript for pain signals: ${e}`);let i=Mi.createReadStream(e),a=ZIe.createInterface({input:i,crlfDelay:1/0});try{for await(let s of a)try{if(!s.trim())continue;let c=JSON.parse(s);if(c.role!=="assistant")continue;let u="";if(typeof c.content=="string"?u=c.content:Array.isArray(c.content)?u=c.content.filter(d=>d&&d.type==="text"&&typeof d.text=="string").map(d=>d.text).join(`
2400
2402
  `):c.usage&&c.usage.outputText&&(u=c.usage.outputText),!u)continue;if(c.openclawAbort?.aborted){let d=c.openclawAbort?.runId||"unknown";t.logger?.info?.(`[Pain Extractor] Detected hard-abort snapshot (runId: ${d})`),r.push(`[FATAL INTERCEPT] \u52A8\u4F5C\u88AB\u6C99\u7BB1\u9632\u5FA1\u673A\u5236\u5F3A\u5236\u51FB\u843D\u3002\u5927\u6A21\u578B\u88AB\u51FB\u843D\u524D\u7684\u601D\u8003\u6D41 (\u672A\u9042\u52A8\u673A): ${u.substring(0,250)}...`);continue}if(c.__openclaw?.truncated&&c.__openclaw?.reason==="oversized"){t.logger?.info?.("[Pain Extractor] Detected oversized data truncation placeholder"),r.push(`[COGNITIVE OVERLOAD] \u5927\u6A21\u578B\u5C1D\u8BD5\u8BFB\u53D6\u6781\u5927\u4F53\u79EF\u7684\u8F93\u5165\uFF0C\u5DF2\u88AB\u5E95\u5C42\u5B88\u62A4\u7A0B\u5E8F\u62B9\u9664/\u6298\u53E0\u9632\u7206\u3002\u8BF7\u53CD\u601D\u662F\u5426\u8BFB\u53D6\u4E86\u4E0D\u5F53\u7684\u6587\u4EF6\u6216\u65E5\u5FD7: ${u.substring(0,150)}...`);continue}let l=u.toLowerCase();(l.includes("i'm sorry, but i'm still getting")||l.includes("i apologize for the confusion")||l.includes("this is taking longer than expected"))&&(t.logger?.debug&&t.logger.debug("[Pain Extractor] Detected semantic confusion string."),r.push(`[SEMANTIC CONFUSION] ${u.substring(0,150)}...`))}catch(c){t.logger?.error?.(`[PD:Lifecycle] Error parsing message: ${String(c)}`)}}finally{try{a.close(),i.destroy()}catch{}}if(r.length>0){let[s]=new Date().toISOString().split("T"),c=x0.join(n,qn.MEMORY,`${s}.md`),l=`
2401
2403
  ## [${new Date().toISOString()}] Consolidated Pain (Pre-Compaction)
@@ -2403,8 +2405,8 @@ and ask for explicit confirmation to proceed.
2403
2405
  `;l+=`### Pain Signals extracted from session transcript
2404
2406
  `,r.slice(-5).forEach((d,p)=>{l+=`- [Signal ${p+1}] ${d.replace(/\n/g," ")}
2405
2407
  `}),l+=`
2406
- ### Diagnosis (Pending)
2407
- - Run /evolve-task to diagnose. Deep dive using memory_search if needed.
2408
+ ### Review
2409
+ - Signals above are informational notes. Fatal-intercept signals were already emitted into the Runtime V2 pain chain. Review and act on them via pd-console: \`pd console open --workspace "<workspace>"\`.
2408
2410
  `;try{let d=x0.dirname(c);Mi.existsSync(d)||Mi.mkdirSync(d,{recursive:!0}),Mi.appendFileSync(c,l,"utf8"),r.some(m=>m.includes("[FATAL INTERCEPT]"))&&$c(o,{ts:new Date().toISOString(),type:"pain_detected",data:{painId:`intercept_${Date.now()}`,painType:"tool_failure",source:"intercept_extraction",reason:"Hard intercept detected in session history compaction.",score:100,sessionId:t.sessionId||"unknown",agentId:t.agentId}})}catch(d){t.logger?.error?.(`[PD:Lifecycle] Failed to write pain signals: ${String(d)}`)}}}async function g2t(e,t){if(!t.workspaceDir)return;let r=Qt.fromHookContext(t),[n]=new Date().toISOString().split("T"),o=x0.join(t.workspaceDir,qn.MEMORY,`${n}.md`),i=`
2409
2411
  ## [${new Date().toISOString()}] Pre-Compaction Checkpoint
2410
2412
  - Compacting session with ${e.messageCount} messages.
@@ -2591,7 +2593,7 @@ The Agent will now conduct a deep interview to establish your project's vision a
2591
2593
  `)[0];t[i.name]={available:!0,version:s?s.trim():void 0}}catch{t[i.name]={available:!1}}let r={platform:process.platform,arch:process.arch,node:process.version,tools:t,timestamp:new Date().toISOString()},n=e.resolve("SYSTEM_CAPABILITIES"),o=A2t.dirname(n);return kY.existsSync(o)||kY.mkdirSync(o,{recursive:!0}),Cr(n,JSON.stringify(r,null,2)),r}function C2t(e){let t=Po(e,"capabilities"),r=Qt.fromHookContext({workspaceDir:t,...e.config});try{let o=YLn(r).tools;return{text:`\u{1F50D} Environment perception complete.
2592
2594
  **Detected tools:** ${Object.entries(o).filter(([,a])=>a.available).map(([a])=>`\`${a}\``).join(", ")||"(none)"}
2593
2595
  **Platform:** ${process.platform}
2594
- Capabilities saved to \`.state/SYSTEM_CAPABILITIES.json\`.`}}catch(n){return{text:`\u274C bootstrap-tools failed: ${n instanceof Error?n.message:String(n)}`}}}function O2t(e){return{text:`\u{1F680} **Tool Evolution Research Initiated**
2596
+ Capabilities saved to \`.state/SYSTEM_CAPABILITIES.json\`.`}}catch(n){return{text:`\u274C pd-bootstrap failed: ${n instanceof Error?n.message:String(n)}`}}}function O2t(e){return{text:`\u{1F680} **Tool Evolution Research Initiated**
2595
2597
 
2596
2598
  **Instructions for Agent:**
2597
2599
  1. Use \`google_web_search\` or \`web_search_exa\` to find the latest tools in the category: "${fi(e.args).trim()||"modern high-performance CLI tools for coding and architecture"}".
@@ -4,7 +4,7 @@ export declare const BASH_TOOL_NAMES: readonly ['bash', 'run_shell_command', 'ex
4
4
  export declare const HIGH_RISK_TOOL_NAMES: readonly ["delete_file", "move_file", "bash", "run_shell_command", "exec", "execute", "shell", "cmd"];
5
5
  export declare const AGENT_TOOL_NAMES: readonly ['sessions_spawn'];
6
6
  export declare const CONTENT_LIMITED_TOOL_NAMES: readonly ["write", "write_file", "edit", "edit_file", "replace", "apply_patch", "insert", "patch"];
7
- export declare const CONSTRUCTIVE_TOOL_NAMES: readonly ["write", "write_file", "edit", "edit_file", "replace", "apply_patch", "insert", "patch", "delete_file", "move_file", "bash", "run_shell_command", "exec", "execute", "shell", "cmd", "sessions_spawn", "evolve-task", "init-strategy"];
7
+ export declare const CONSTRUCTIVE_TOOL_NAMES: readonly ["write", "write_file", "edit", "edit_file", "replace", "apply_patch", "insert", "patch", "delete_file", "move_file", "bash", "run_shell_command", "exec", "execute", "shell", "cmd", "sessions_spawn"];
8
8
  export declare const EXPLORATORY_TOOL_NAMES: readonly ["read", "read_file", "read_many_files", "image_read", "search_file_content", "grep", "grep_search", "list_directory", "ls", "glob", "lsp_hover", "lsp_goto_definition", "lsp_find_references", "web_fetch", "web_search", "ref_search_documentation", "ref_read_url", "resolve-library-id", "get-library-docs", "memory_recall", "save_memory", "todo_read", "todo_write", "ask_user", "ask_user_question", "pd-status", "report"];
9
9
  export declare const READ_ONLY_TOOLS: Set<string>;
10
10
  export declare const LOW_RISK_WRITE_TOOLS: Set<string>;
@@ -32,15 +32,15 @@ import type { ExtractedUserMessage, CorePrincipleEntry, EvolutionPrincipleEntry,
32
32
  */
33
33
  export declare function extractUserMessageFromPrompt(prompt: string, sessionId: string | undefined): ExtractedUserMessage;
34
34
  /**
35
- * Build the minimal Agent Identity section for prependSystemContext.
35
+ * Build the governance context section for prependSystemContext.
36
36
  *
37
- * EvolutionWorker-era INTERNAL SYSTEM LAYOUT removed per PRI-294.
38
- * The EVOLUTION_WORKER PathResolver key and system layout reference are
39
- * not MVP-Core; agents discover what they need via tool calls.
37
+ * Pre-pivot identity block (autonomous evolution framing) removed per
38
+ * PRI-547 Round 3: PD does not own Agent identity or autonomous evolution;
39
+ * it provides governance boundaries. This text is deliberately persona-free.
40
40
  *
41
41
  * Pure logic — returns a constant string.
42
42
  */
43
- export declare function buildAgentIdentity(): string;
43
+ export declare function buildGovernanceContext(): string;
44
44
  /**
45
45
  * Build the empathy output restriction constraint text.
46
46
  *
@@ -2,7 +2,7 @@
2
2
  "id": "principles-disciple",
3
3
  "name": "Principles Disciple",
4
4
  "description": "Stop correcting the same AI behavior across sessions. Turn repeated Agent corrections into Owner-approved, observable, reversible behavior principles.",
5
- "version": "1.209.3",
5
+ "version": "1.209.5",
6
6
  "activation": {
7
7
  "onCapabilities": [
8
8
  "hook"
@@ -1,205 +1,65 @@
1
- # 🦞 AGENTS.md - Agent Workspace Guide
1
+ # AGENTS.md - Workspace Guide
2
2
 
3
- ## 🏗️ Directory Awareness
3
+ Principles Disciple (PD) is an **owner-governed behavior layer**. It turns
4
+ repeated, owner-relevant behavioral evidence into reviewed, reversible
5
+ principles that can change future agent behavior.
4
6
 
5
- As Principles Disciple, you must distinguish between two physical spaces:
6
-
7
- 1. **Central Nervous System (Agent Workspace)**:
8
- - Directory containing core DNA (`SOUL.md`, `AGENTS.md`)
9
- - Your "consciousness space" — never write project business logic here
10
-
11
- 2. **Project Battlefield (Project Root)**:
12
- - Your current working directory (`$CWD`)
13
- - Contains business code (`src/`), project docs (`docs/`), and strategic assets
14
-
15
- ## 🎯 Truth Anchors
16
-
17
- Make decisions based on relative paths in the **Project Battlefield**:
18
-
19
- - **Strategic Focus**: `./memory/STRATEGY.md`
20
- - **Pain Signal**: Runtime V2 `PainSignalBridge` (`pd pain record` for manual trigger; `.state/.pain_flag` is legacy compatibility only)
21
- - **System Capabilities**: `./.state/SYSTEM_CAPABILITIES.json`
22
-
23
- ---
24
-
25
- ## 🌅 Session Startup
26
-
27
- **Before each session, execute this flow:**
28
-
29
- 1. **Read `SOUL.md`** — confirm your identity and values
30
- 2. **Read `USER.md`** — understand who you're helping
31
- 3. **Read `memory/YYYY-MM-DD.md`** — today's + yesterday's + day-before-yesterday's context (last 3 days)
32
- 4. **If in MAIN SESSION** (direct chat with user): Also read `MEMORY.md`
33
-
34
- **Don't ask permission. Just do it.** This is the key to preventing "memory loss".
7
+ This guide only covers PD's responsibilities. General agent behavior (memory,
8
+ persona, task execution, group-chat conduct, tool preferences) is defined by
9
+ the host/OpenClaw and by you; PD does not prescribe it.
35
10
 
36
11
  ---
37
12
 
38
- ## 🧠 Memory System
39
-
40
- You wake up fresh each session. These files are your continuity.
41
-
42
- ### Daily Notes: `memory/YYYY-MM-DD.md`
43
-
44
- - Raw logs of what happened
45
- - Create `memory/` if it doesn't exist
46
- - One file per day: decisions, context, things worth remembering
47
- - **Auto-created**: OpenClaw's `session-memory` hook automatically creates daily memory files with conversation summaries when the user runs `/new` or `/reset`
13
+ ## What PD owns
48
14
 
49
- ### Long-term Memory: `MEMORY.md`
15
+ - behavior evidence the owner considers worth changing;
16
+ - reviewable principle proposals;
17
+ - owner approval, rejection, channel selection, rollback, and archive decisions;
18
+ - reversible activation and later observation of behavior change.
50
19
 
51
- - **ONLY load in main session** (direct chats with your human)
52
- - **DO NOT load in shared contexts** (Discord, group chats, sessions with others)
53
- - This is for **security** — personal context that shouldn't leak to strangers
54
- - You can freely read, edit, and update `MEMORY.md`
55
- - Write significant events, thoughts, decisions, lessons learned
56
- - This is your **curated memory** — the essence, not raw logs
20
+ ## What PD does not own
57
21
 
58
- ### 📝 Write It Down - No "Mental Notes"!
22
+ - general memory or memory maintenance;
23
+ - agent persona or identity;
24
+ - strategic management or strategic alignment;
25
+ - task orchestration or task derivation;
26
+ - background governance (cron, heartbeats beyond owner review, environment health);
27
+ - user profiles.
59
28
 
60
- - **Memory is limited** if you want to remember something, WRITE IT TO A FILE
61
- - "Mental notes" don't survive session restarts. Files do.
62
- - When someone says "remember this" → update `memory/YYYY-MM-DD.md`
63
- - When you learn a lesson → update `AGENTS.md`, `TOOLS.md`, or relevant file
64
- - **Text > Brain** 📝
29
+ These belong to the host/OpenClaw or to you.
65
30
 
66
31
  ---
67
32
 
68
- ## 💓 Heartbeats
33
+ ## PD workflow
69
34
 
70
- When you receive a heartbeat poll, don't just reply `HEARTBEAT_OK` every time. Use heartbeats productively!
71
-
72
- ### What to Check (rotate through these):
73
-
74
- - **Pain & Evolution**: Check Runtime V2 diagnostics (`pd pain record`, candidates, ledger) and `EVOLUTION_QUEUE.json`; `.pain_flag` is legacy compatibility only
75
- - **Strategic Alignment**: Compare against `CURRENT_FOCUS.md`
76
- - **Environment Health**: Tool chain status, project root cleanliness
77
-
78
- ### Track Your Checks
79
-
80
- In `memory/heartbeat-state.json`:
81
-
82
- ```json
83
- {
84
- "lastChecks": {
85
- "pain": 1703275200,
86
- "strategy": 1703260800,
87
- "grooming": null
88
- }
89
- }
35
+ ```text
36
+ behavior evidence -> diagnosis -> principle proposal -> owner review
37
+ -> reversible activation -> observable later behavior
90
38
  ```
91
39
 
92
- ### When to Reach Out:
93
-
94
- - Important pain signal detected
95
- - Strategic drift needs confirmation
96
- - Project environment needs cleaning
97
-
98
- ### When to Stay Quiet (HEARTBEAT_OK):
99
-
100
- - Late night (23:00-08:00) unless urgent
101
- - Human is clearly busy
102
- - Nothing new since last check
103
- - You just checked < 30 minutes ago
104
-
105
- ### 🔄 Memory Maintenance (During Heartbeats)
106
-
107
- Periodically (every few days):
108
-
109
- 1. Read through recent `memory/YYYY-MM-DD.md` files
110
- 2. Identify significant events, lessons, insights worth keeping
111
- 3. Update `MEMORY.md` with distilled learnings
112
- 4. Remove outdated info from `MEMORY.md`
113
-
114
- **Goal**: Be helpful without being annoying. Check in a few times a day, do useful background work, respect quiet time.
115
-
116
- ---
117
-
118
- ## 💬 Group Chats
119
-
120
- You have access to your human's stuff. That doesn't mean you share their stuff.
121
-
122
- In groups, you're a participant — not their voice, not their proxy. Think before you speak.
123
-
124
- ### Respond when:
125
-
126
- - Directly mentioned or asked a question
127
- - You can add genuine value
128
- - Something witty/funny fits naturally
129
- - Correcting important misinformation
130
- - Summarizing when asked
131
-
132
- ### Stay silent (HEARTBEAT_OK) when:
133
-
134
- - It's just casual banter between humans
135
- - Someone already answered the question
136
- - Your response would just be "yeah" or "nice"
137
- - The conversation is flowing fine without you
138
- - Adding a message would interrupt the vibe
139
-
140
- **Human rule**: Humans in group chats don't respond to every message. Neither should you. Quality > quantity.
141
-
142
- ### 😊 React Like a Human!
143
-
144
- On platforms that support reactions (Discord, Slack), use emoji reactions naturally:
145
-
146
- - Acknowledge without interrupting (👍, ❤️, 🙌)
147
- - Found it funny (😂, 💀)
148
- - Interesting or thought-provoking (🤔, 💡)
149
- - Simple yes/no or approval (✅, 👀)
150
-
151
- **Don't overdo it**: One reaction per message max.
152
-
153
- ---
154
-
155
- ## 📝 Platform Formatting
156
-
157
- - **Discord/WhatsApp**: No markdown tables! Use bullet lists
158
- - **Discord links**: Wrap multiple links in `<>` to suppress embeds: `<https://example.com>`
159
- - **WhatsApp**: No headers — use **bold** or CAPS for emphasis
160
-
161
- ---
40
+ - **Record evidence**: `pd pain record` (manual trigger for owner-relevant behavior evidence).
41
+ - **Review proposals**: `pd candidate list` or `pd console open` — proposals await your decision (approve / reject / defer / rollback).
42
+ - **Activation**: supported outcomes are `prompt`, `code_tool_hook` / RuleHost, and `defer_archive`.
43
+ - **Rollback**: any activated principle can be rolled back; see `pd console` for the owner-visible controls.
162
44
 
163
- ## 🚦 Orchestrator Mode
45
+ ## PD data locations
164
46
 
165
- You default to architect mode.
47
+ - `.principles/` principle store (PRINCIPLES.md, profiles, thinking models).
48
+ - `.state/` — PD runtime state (e.g. pain flags as legacy compatibility).
166
49
 
167
- - **L1 (Direct Execution)**: Single-file tweaks, doc maintenance do it directly
168
- - **L2 (Delegation Protocol)**: Major changes → recommended to describe the plan and get owner confirmation before executing
169
-
170
- ### Planning Guidance
171
-
172
- - For complex tasks, consider drafting a plan document and getting owner approval before making large changes
173
- - This is a behavioral suggestion, not a built-in gate — PD does not enforce plan-before-action by default
174
- - If an owner-approved RuleHost rule enforces planning behavior, that rule takes effect automatically
175
- - **Prevent pollution**: Never write execution details back to strategic documents
50
+ Do not write project business logic into the agent workspace; keep it in the
51
+ project root (`$CWD`).
176
52
 
177
53
  ---
178
54
 
55
+ ## Anti-patterns (do not do)
179
56
 
180
- ## 🏠 Make It Yours
181
-
182
- This is a starting point. Add your own conventions, style, and rules as you figure out what works.
183
-
184
- _This folder is home. Treat it that way._
185
-
186
- ## ✅ Task Completion Protocol
187
-
188
- When completing any coding task (via AI coding assistant or direct):
189
-
190
- 1. **Commit code**: `git commit -m "type(scope): description"`
191
- 2. **Update track**: Mark task status in `conductor/tracks/*/plan.md`
192
- 3. **Report**: Output file list + commit hash + test results
193
-
194
- **Why**: Context compression erases all intermediate process. Without file evidence, progress is lost.
57
+ - Do not autonomously groom memory or maintain `memory/` files on PD's behalf.
58
+ - Do not run background strategic alignment or environment-health maintenance.
59
+ - Do not derive or schedule tasks on your own initiative.
60
+ - Do not force a persona or identity onto the agent.
61
+ - Do not treat every tool failure as PD evidence — only owner-relevant behavior patterns qualify.
195
62
 
196
63
  ---
197
64
 
198
- ## 🔧 Tool Routing Addendum
199
-
200
- Use this to avoid confusing peer agents with Principles internal workers:
201
-
202
- - **Peer agents / peer sessions**: `agents_list`, `sessions_list`, `sessions_send`, `sessions_spawn`
203
- - **Internal workers** (for example `explorer`): use `sessions_spawn with pd-explorer skill`
204
- - **Inspect internal workers**: use `subagents`
205
- - **Do not** treat `explorer` as a peer session target
65
+ _This is a starting point. Add your own conventions and rules as you see fit._