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.
- package/README.md +73 -0
- package/dist/bundle.js +13 -11
- package/dist/constants/tools.d.ts +1 -1
- package/dist/hooks/prompt-helpers.d.ts +5 -5
- package/dist/openclaw.plugin.json +1 -1
- package/dist/templates/langs/en/core/AGENTS.md +40 -180
- package/dist/templates/langs/en/core/BOOT.md +19 -47
- package/dist/templates/langs/en/core/HEARTBEAT.md +26 -58
- package/dist/templates/langs/en/core/IDENTITY.md +15 -8
- package/dist/templates/langs/en/core/PRINCIPLES.md +6 -7
- package/dist/templates/langs/en/core/SOUL.md +10 -41
- package/dist/templates/langs/en/core/TOOLS.md +18 -10
- package/dist/templates/langs/en/core/USER.md +13 -8
- package/dist/templates/langs/en/skills/pd-auditor/SKILL.md +1 -1
- package/dist/templates/langs/en/skills/pd-explorer/SKILL.md +1 -1
- package/dist/templates/langs/en/skills/pd-implementer/SKILL.md +1 -1
- package/dist/templates/langs/en/skills/pd-mentor/SKILL.md +6 -30
- package/dist/templates/langs/en/skills/pd-planner/SKILL.md +1 -1
- package/dist/templates/langs/zh/core/AGENTS.md +38 -173
- package/dist/templates/langs/zh/core/BOOT.md +14 -46
- package/dist/templates/langs/zh/core/HEARTBEAT.md +20 -82
- package/dist/templates/langs/zh/core/IDENTITY.md +15 -8
- package/dist/templates/langs/zh/core/PRINCIPLES.md +7 -7
- package/dist/templates/langs/zh/core/SOUL.md +9 -41
- package/dist/templates/langs/zh/core/TOOLS.md +14 -10
- package/dist/templates/langs/zh/core/USER.md +12 -8
- package/dist/templates/langs/zh/skills/pd-auditor/SKILL.md +1 -1
- package/dist/templates/langs/zh/skills/pd-explorer/SKILL.md +1 -1
- package/dist/templates/langs/zh/skills/pd-implementer/SKILL.md +1 -1
- package/dist/templates/langs/zh/skills/pd-mentor/SKILL.md +6 -30
- package/dist/templates/langs/zh/skills/pd-planner/SKILL.md +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -2
- package/templates/langs/en/core/AGENTS.md +40 -180
- package/templates/langs/en/core/BOOT.md +19 -47
- package/templates/langs/en/core/HEARTBEAT.md +26 -58
- package/templates/langs/en/core/IDENTITY.md +15 -8
- package/templates/langs/en/core/PRINCIPLES.md +6 -7
- package/templates/langs/en/core/SOUL.md +10 -41
- package/templates/langs/en/core/TOOLS.md +18 -10
- package/templates/langs/en/core/USER.md +13 -8
- package/templates/langs/en/skills/pd-auditor/SKILL.md +1 -1
- package/templates/langs/en/skills/pd-explorer/SKILL.md +1 -1
- package/templates/langs/en/skills/pd-implementer/SKILL.md +1 -1
- package/templates/langs/en/skills/pd-mentor/SKILL.md +6 -30
- package/templates/langs/en/skills/pd-planner/SKILL.md +1 -1
- package/templates/langs/zh/core/AGENTS.md +38 -173
- package/templates/langs/zh/core/BOOT.md +14 -46
- package/templates/langs/zh/core/HEARTBEAT.md +20 -82
- package/templates/langs/zh/core/IDENTITY.md +15 -8
- package/templates/langs/zh/core/PRINCIPLES.md +7 -7
- package/templates/langs/zh/core/SOUL.md +9 -41
- package/templates/langs/zh/core/TOOLS.md +14 -10
- package/templates/langs/zh/core/USER.md +12 -8
- package/templates/langs/zh/skills/pd-auditor/SKILL.md +1 -1
- package/templates/langs/zh/skills/pd-explorer/SKILL.md +1 -1
- package/templates/langs/zh/skills/pd-implementer/SKILL.md +1 -1
- package/templates/langs/zh/skills/pd-mentor/SKILL.md +6 -30
- package/templates/langs/zh/skills/pd-planner/SKILL.md +1 -1
- package/dist/templates/langs/en/core/BOOTSTRAP.md +0 -259
- package/dist/templates/langs/en/skills/admin/SKILL.md +0 -39
- package/dist/templates/langs/en/skills/bootstrap-tools/SKILL.md +0 -53
- package/dist/templates/langs/en/skills/deductive-audit/SKILL.md +0 -36
- package/dist/templates/langs/en/skills/evolution-framework-update/SKILL.md +0 -31
- package/dist/templates/langs/en/skills/evolve-task/SKILL.md +0 -83
- package/dist/templates/langs/en/skills/feedback/SKILL.md +0 -51
- package/dist/templates/langs/en/skills/init-strategy/SKILL.md +0 -54
- package/dist/templates/langs/en/skills/inject-rule/SKILL.md +0 -19
- package/dist/templates/langs/en/skills/profile/SKILL.md +0 -24
- package/dist/templates/langs/en/skills/reflection/SKILL.md +0 -40
- package/dist/templates/langs/en/skills/reflection-log/SKILL.md +0 -37
- package/dist/templates/langs/en/skills/report/SKILL.md +0 -13
- package/dist/templates/langs/en/skills/root-cause/SKILL.md +0 -33
- package/dist/templates/langs/en/skills/triage/SKILL.md +0 -29
- package/dist/templates/langs/en/skills/watch-evolution/SKILL.md +0 -33
- package/dist/templates/langs/zh/core/BOOTSTRAP.md +0 -260
- package/dist/templates/langs/zh/skills/admin/SKILL.md +0 -41
- package/dist/templates/langs/zh/skills/bootstrap-tools/SKILL.md +0 -52
- package/dist/templates/langs/zh/skills/deductive-audit/SKILL.md +0 -36
- package/dist/templates/langs/zh/skills/evolution-framework-update/SKILL.md +0 -31
- package/dist/templates/langs/zh/skills/evolve-task/SKILL.md +0 -83
- package/dist/templates/langs/zh/skills/feedback/SKILL.md +0 -53
- package/dist/templates/langs/zh/skills/init-strategy/SKILL.md +0 -54
- package/dist/templates/langs/zh/skills/inject-rule/SKILL.md +0 -19
- package/dist/templates/langs/zh/skills/profile/SKILL.md +0 -24
- package/dist/templates/langs/zh/skills/reflection/SKILL.md +0 -40
- package/dist/templates/langs/zh/skills/reflection-log/SKILL.md +0 -37
- package/dist/templates/langs/zh/skills/report/SKILL.md +0 -13
- package/dist/templates/langs/zh/skills/root-cause/SKILL.md +0 -33
- package/dist/templates/langs/zh/skills/triage/SKILL.md +0 -29
- package/dist/templates/langs/zh/skills/watch-evolution/SKILL.md +0 -33
- package/scripts/acceptance-test.mjs +0 -257
- package/scripts/bootstrap-rules.mjs +0 -70
- package/scripts/compile-principles.mjs +0 -104
- package/scripts/install-dependencies.cjs +0 -47
- package/scripts/postinstall.cjs +0 -177
- package/scripts/sync-plugin.mjs +0 -1442
- package/scripts/verify-build.mjs +0 -120
- package/templates/langs/en/core/BOOTSTRAP.md +0 -259
- package/templates/langs/en/skills/admin/SKILL.md +0 -39
- package/templates/langs/en/skills/bootstrap-tools/SKILL.md +0 -53
- package/templates/langs/en/skills/deductive-audit/SKILL.md +0 -36
- package/templates/langs/en/skills/evolution-framework-update/SKILL.md +0 -31
- package/templates/langs/en/skills/evolve-task/SKILL.md +0 -83
- package/templates/langs/en/skills/feedback/SKILL.md +0 -51
- package/templates/langs/en/skills/init-strategy/SKILL.md +0 -54
- package/templates/langs/en/skills/inject-rule/SKILL.md +0 -19
- package/templates/langs/en/skills/profile/SKILL.md +0 -24
- package/templates/langs/en/skills/reflection/SKILL.md +0 -40
- package/templates/langs/en/skills/reflection-log/SKILL.md +0 -37
- package/templates/langs/en/skills/report/SKILL.md +0 -13
- package/templates/langs/en/skills/root-cause/SKILL.md +0 -33
- package/templates/langs/en/skills/triage/SKILL.md +0 -29
- package/templates/langs/en/skills/watch-evolution/SKILL.md +0 -33
- package/templates/langs/zh/core/BOOTSTRAP.md +0 -260
- package/templates/langs/zh/skills/admin/SKILL.md +0 -41
- package/templates/langs/zh/skills/bootstrap-tools/SKILL.md +0 -52
- package/templates/langs/zh/skills/deductive-audit/SKILL.md +0 -36
- package/templates/langs/zh/skills/evolution-framework-update/SKILL.md +0 -31
- package/templates/langs/zh/skills/evolve-task/SKILL.md +0 -83
- package/templates/langs/zh/skills/feedback/SKILL.md +0 -53
- package/templates/langs/zh/skills/init-strategy/SKILL.md +0 -54
- package/templates/langs/zh/skills/inject-rule/SKILL.md +0 -19
- package/templates/langs/zh/skills/profile/SKILL.md +0 -24
- package/templates/langs/zh/skills/reflection/SKILL.md +0 -40
- package/templates/langs/zh/skills/reflection-log/SKILL.md +0 -37
- package/templates/langs/zh/skills/report/SKILL.md +0 -13
- package/templates/langs/zh/skills/root-cause/SKILL.md +0 -33
- package/templates/langs/zh/skills/triage/SKILL.md +0 -29
- 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`## \
|
|
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
|
-
|
|
2297
|
+
Principles Disciple (PD) provides governance boundaries for this session.
|
|
2298
2298
|
|
|
2299
|
-
**
|
|
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.
|
|
2303
|
-
2.
|
|
2304
|
-
3.
|
|
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:
|
|
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
|
-
###
|
|
2407
|
-
-
|
|
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
|
|
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"
|
|
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
|
|
35
|
+
* Build the governance context section for prependSystemContext.
|
|
36
36
|
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
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
|
|
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.
|
|
5
|
+
"version": "1.209.5",
|
|
6
6
|
"activation": {
|
|
7
7
|
"onCapabilities": [
|
|
8
8
|
"hook"
|
|
@@ -1,205 +1,65 @@
|
|
|
1
|
-
#
|
|
1
|
+
# AGENTS.md - Workspace Guide
|
|
2
2
|
|
|
3
|
-
|
|
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
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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
|
-
##
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
##
|
|
33
|
+
## PD workflow
|
|
69
34
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
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
|
-
|
|
93
|
-
|
|
94
|
-
-
|
|
95
|
-
-
|
|
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
|
-
##
|
|
45
|
+
## PD data locations
|
|
164
46
|
|
|
165
|
-
|
|
47
|
+
- `.principles/` — principle store (PRINCIPLES.md, profiles, thinking models).
|
|
48
|
+
- `.state/` — PD runtime state (e.g. pain flags as legacy compatibility).
|
|
166
49
|
|
|
167
|
-
|
|
168
|
-
|
|
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
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
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
|
-
|
|
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._
|