create-principles-disciple 1.147.1 → 1.147.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/_release/product-identity.json +1 -1
  2. package/codex-adapter/dist/ingestion/admission.d.ts +5 -10
  3. package/codex-adapter/dist/ingestion/admission.js +19 -77
  4. package/codex-adapter/dist/ingestion/explicit-owner-statement.js +1 -1
  5. package/codex-adapter/dist/ingestion/ingestion.d.ts +0 -2
  6. package/codex-adapter/dist/ingestion/ingestion.js +6 -4
  7. package/codex-adapter/dist/pd-hook.js +5 -7
  8. package/codex-adapter/package.json +1 -1
  9. package/core/dist/runtime-v2/evidence-triage/index.d.ts +0 -1
  10. package/core/dist/runtime-v2/evidence-triage/index.d.ts.map +1 -1
  11. package/core/dist/runtime-v2/evidence-triage/index.js +0 -2
  12. package/core/dist/runtime-v2/evidence-triage/index.js.map +1 -1
  13. package/core/dist/runtime-v2/evidence-triage/source-descriptors.d.ts +3 -8
  14. package/core/dist/runtime-v2/evidence-triage/source-descriptors.d.ts.map +1 -1
  15. package/core/dist/runtime-v2/evidence-triage/source-descriptors.js +5 -17
  16. package/core/dist/runtime-v2/evidence-triage/source-descriptors.js.map +1 -1
  17. package/core/dist/runtime-v2/evidence-triage/triage-policy.d.ts +11 -9
  18. package/core/dist/runtime-v2/evidence-triage/triage-policy.d.ts.map +1 -1
  19. package/core/dist/runtime-v2/evidence-triage/triage-policy.js +10 -103
  20. package/core/dist/runtime-v2/evidence-triage/triage-policy.js.map +1 -1
  21. package/core/dist/runtime-v2/evidence-triage/trigger-controller.js +1 -1
  22. package/core/dist/runtime-v2/evidence-triage/trigger-controller.js.map +1 -1
  23. package/core/dist/runtime-v2/evidence-triage/types.d.ts +4 -16
  24. package/core/dist/runtime-v2/evidence-triage/types.d.ts.map +1 -1
  25. package/core/dist/runtime-v2/evidence-triage/types.js.map +1 -1
  26. package/core/dist/runtime-v2/index.d.ts +1 -1
  27. package/core/dist/runtime-v2/index.d.ts.map +1 -1
  28. package/core/dist/runtime-v2/index.js +1 -1
  29. package/core/dist/runtime-v2/index.js.map +1 -1
  30. package/core/package.json +1 -1
  31. package/dist/installer.d.ts +20 -0
  32. package/dist/installer.d.ts.map +1 -1
  33. package/dist/installer.js +49 -97
  34. package/dist/installer.js.map +1 -1
  35. package/dist/mvp-config.d.ts +11 -0
  36. package/dist/mvp-config.d.ts.map +1 -1
  37. package/dist/mvp-config.js.map +1 -1
  38. package/dist/update/release-metadata.d.ts +13 -5
  39. package/dist/update/release-metadata.d.ts.map +1 -1
  40. package/dist/update/release-metadata.js.map +1 -1
  41. package/host-runtime/dist/governance-signal-admission.d.ts +1 -77
  42. package/host-runtime/dist/governance-signal-admission.js +34 -294
  43. package/host-runtime/dist/production-pain-evidence.d.ts +8 -69
  44. package/host-runtime/dist/production-pain-evidence.js +19 -157
  45. package/host-runtime/package.json +1 -1
  46. package/package.json +4 -3
  47. package/pd-cli/package.json +1 -1
  48. package/pd-mcp-server/dist/version.d.ts +1 -1
  49. package/pd-mcp-server/dist/version.js +1 -1
  50. package/pd-mcp-server/package.json +1 -1
  51. package/plugin/dist/bundle.js +411 -412
  52. package/plugin/dist/hooks/after-tool-call-helpers.d.ts +2 -35
  53. package/plugin/dist/hooks/after-tool-call-types.d.ts +1 -30
  54. package/plugin/dist/hooks/pain.d.ts +6 -19
  55. package/plugin/dist/hooks/trajectory-evidence.d.ts +3 -10
  56. package/plugin/dist/hooks/triage-adapter.d.ts +7 -20
  57. package/plugin/dist/host-runtime/openclaw-host-runtime.d.ts +0 -1
  58. package/plugin/dist/openclaw.plugin.json +1 -1
  59. package/plugin/openclaw.plugin.json +1 -1
  60. package/plugin/package.json +1 -1
  61. package/release-manager/dist/installer.js +49 -97
  62. package/release-manager/package.json +2 -1
  63. package/workbuddy-adapter/dist/pd-hook.js +0 -26
  64. package/workbuddy-adapter/dist/worker/workspace-worker.d.ts +1 -7
  65. package/workbuddy-adapter/dist/worker/workspace-worker.js +11 -21
  66. package/workbuddy-adapter/package.json +1 -1
@@ -4,7 +4,7 @@
4
4
  * Extracted functions from handleAfterToolCall that implement
5
5
  * individual pipeline stages. Each function has a focused responsibility.
6
6
  *
7
- * Pipeline order: classify → record → triage → gate → emit
7
+ * Pipeline order: classify → record → friction tracking → hygiene
8
8
  *
9
9
  * ERR checklist:
10
10
  * - ERR-001: No `as` casts on untrusted runtime values.
@@ -16,7 +16,7 @@ import { normalizeProfile } from '../core/profile.js';
16
16
  import { type SessionState } from '../core/session-tracker.js';
17
17
  import { WorkspaceContext } from '../core/workspace-context.js';
18
18
  import type { PluginHookAfterToolCallEvent } from '../openclaw-sdk.js';
19
- import type { ToolCallOutcome, ToolCallObservation, PainAdmissionDecision } from './after-tool-call-types.js';
19
+ import type { ToolCallOutcome, ToolCallObservation } from './after-tool-call-types.js';
20
20
  /**
21
21
  * Extract a preview string from tool call result for diagnostic evidence.
22
22
  * Pure function — no I/O, no side effects. ERR-001 / ERR-014 compliant.
@@ -59,36 +59,3 @@ export declare function handleFrictionTrackingForSuccess(sessionId: string, even
59
59
  * Record hygiene tracking for memory/plan persistence actions on success.
60
60
  */
61
61
  export declare function recordHygieneTracking(event: PluginHookAfterToolCallEvent, observation: ToolCallObservation, wctx: WorkspaceContext): void;
62
- /**
63
- * Evaluate whether a tool failure should trigger pain diagnosis.
64
- *
65
- * PRI-363: Single-gate architecture — only TriggerController decides.
66
- *
67
- * Combines:
68
- * 1. Write-tool check — only write tools on failures enter this path
69
- * 2. PEAT-B1 triage — evidence triage (always enabled now)
70
- * 3. PEAT-B2 trigger controller — single source of truth for task creation
71
- * 4. Cooldown tracking — plugin layer owns this state
72
- *
73
- * Returns a structured decision with reason and stage.
74
- */
75
- export declare function evaluatePainAdmissionForToolCall(event: PluginHookAfterToolCallEvent, observation: ToolCallObservation, outcome: ToolCallOutcome, latestFailureState: SessionState | undefined, sessionState: SessionState | undefined, sessionId: string, workspaceDir: string, _config: {
76
- get: (key: string) => unknown;
77
- }): PainAdmissionDecision;
78
- /**
79
- * Emit pain signal after admission.
80
- *
81
- * Records to trajectory, event log, principle value tracker,
82
- * and emits the pain_detected event.
83
- *
84
- * Only called when the admission decision is 'admitted'.
85
- */
86
- export declare function emitPainIfAdmitted(wctx: WorkspaceContext, event: PluginHookAfterToolCallEvent, observation: ToolCallObservation, outcome: ToolCallOutcome, admission: PainAdmissionDecision, sessionId: string, agentId: string | undefined, workspaceDir: string, emitPainDetectedEvent: (wctx: WorkspaceContext, event: import('../core/evolution-types.js').EvolutionLoopEvent, options?: {
87
- recordObservability?: boolean;
88
- }) => Promise<void>): void;
89
- export { buildTrajectoryEvidence } from './trajectory-evidence.js';
90
- /**
91
- * Reset trigger cooldown state (for tests).
92
- * PRI-454: Delegates to shared cooldown Map reset.
93
- */
94
- export declare function resetTriggerCooldownForTest(): void;
@@ -10,7 +10,6 @@
10
10
  * - ERR-002: Every decision/result carries structured reason + nextAction.
11
11
  * - EP-01: These types document boundaries, not runtime validation targets.
12
12
  */
13
- import type { SessionState } from '../core/session-tracker.js';
14
13
  /**
15
14
  * Result of classifying what happened in a tool call event.
16
15
  *
@@ -27,7 +26,7 @@ export interface ToolCallOutcome {
27
26
  /**
28
27
  * Normalized observation built from the tool call event and context.
29
28
  *
30
- * Used by friction tracking, event recording, and pain admission.
29
+ * Used by friction tracking, event log recording, and trajectory recording.
31
30
  * Constructed after classification, before any I/O.
32
31
  */
33
32
  export interface ToolCallObservation {
@@ -56,31 +55,3 @@ export interface ToolCallObservation {
56
55
  /** Trace ID for this observation chain */
57
56
  readonly traceId: string;
58
57
  }
59
- /**
60
- * Result of evaluating whether a tool failure should trigger pain diagnosis.
61
- *
62
- * Encapsulates the single-gate trigger controller decision.
63
- */
64
- export interface PainAdmissionDecision {
65
- /** Whether the tool failure should proceed to pain emission */
66
- readonly admitted: boolean;
67
- /** The admission stage that made the decision */
68
- readonly stage: 'not_applicable' | 'trigger_admitted' | 'trigger_rejected';
69
- /** Human-readable reason for the decision */
70
- readonly reason: string;
71
- /** Detail about the decision */
72
- readonly detail: string;
73
- }
74
- /**
75
- * Result of friction tracking for a tool call.
76
- */
77
- export interface FrictionUpdateResult {
78
- /** GFI before this update */
79
- readonly gfiBefore: number;
80
- /** GFI after this update */
81
- readonly gfiAfter: number;
82
- /** Updated session state (if failure) */
83
- readonly sessionState: SessionState | undefined;
84
- /** The error hash used for tracking */
85
- readonly errorHash: string;
86
- }
@@ -1,32 +1,23 @@
1
1
  /**
2
2
  * Pain Hook — PRI-326 decomposed
3
3
  *
4
- * After-tool-call hook that captures tool failures and emits pain signals.
4
+ * After-tool-call hook. Phase A retired every automatic Pain admission that
5
+ * was triggered by a technical tool failure: failures are still classified,
6
+ * recorded in the trajectory, and tracked for GFI health, but they never
7
+ * create a Pain Event or a Diagnostician task by themselves.
5
8
  *
6
- * Pipeline stages (delegated to after-tool-call-helpers):
9
+ * Remaining stages (delegated to after-tool-call-helpers):
7
10
  * 1. classifyToolCallOutcome — determine failure/success + source
8
11
  * 2. buildToolCallObservation — normalize event into observation
9
12
  * 3. handleFrictionTracking — GFI, event log, trajectory recording
10
- * 4. evaluatePainAdmission — triage + gate evaluation
11
- * 5. emitPainIfAdmitted — pain signal emission
12
13
  *
13
14
  * The manual pain path (toolName === 'pain') remains inline because it
14
- * has a different control flow (early return, no triage, no gate on cooldown).
15
+ * has a different control flow (early return, Owner-explicit admission).
15
16
  */
16
17
  import { WorkspaceContext } from '../core/workspace-context.js';
17
18
  import type { EvolutionLoopEvent } from '../core/evolution-types.js';
18
19
  import type { PluginHookAfterToolCallEvent, PluginHookToolContext, OpenClawPluginApi } from '../openclaw-sdk.js';
19
20
  import type { ProductionPainEnrichment } from '@principles/host-runtime';
20
- import type { HostEventResult } from '@principles/core/host';
21
- import { buildTrajectoryEvidence } from './trajectory-evidence.js';
22
- export { buildTrajectoryEvidence };
23
- /**
24
- * Host-owned best-effort continuation after durable shared persistence.
25
- * The hook may return once SQLite commits, while rejections remain observable
26
- * and tests/shutdown code can explicitly drain scheduled work.
27
- */
28
- export declare function schedulePainContinuation(workspaceDir: string, continuation: Promise<void>): void;
29
- export declare function drainPainContinuationsForTest(): Promise<void>;
30
21
  export declare function emitPainDetectedEvent(wctx: WorkspaceContext, event: EvolutionLoopEvent, options?: {
31
22
  recordObservability?: boolean;
32
23
  }): Promise<void>;
@@ -50,7 +41,3 @@ export declare function prepareOrdinaryAfterToolCallForSharedRuntime(event: Plug
50
41
  workspaceDir: string;
51
42
  pluginConfig?: Record<string, unknown>;
52
43
  }): ProductionPainEnrichment;
53
- /** Restore OpenClaw-owned pain UX/diagnosis after the shared atomic evidence write. */
54
- export declare function handleSharedPainEvidenceResult(event: PluginHookAfterToolCallEvent, ctx: PluginHookToolContext & {
55
- workspaceDir: string;
56
- }, result: HostEventResult): void;
@@ -7,10 +7,9 @@
7
7
  * Pure data extraction — reads from trajectory DB, sanitizes, returns evidence entries.
8
8
  *
9
9
  * PRI-642 Scope A adds the typed acquisition API `acquireTrajectoryEvidence`
10
- * (discriminated available/unavailable, SPEC §7.2). The legacy array API
11
- * `buildTrajectoryEvidence` remains as a compatibility wrapper for automatic
12
- * emitters and MUST keep its exact sentinel shapes until Scope B migrates
13
- * those consumers (frozen decision #3).
10
+ * (discriminated available/unavailable, SPEC §7.2). Phase A retired the last
11
+ * automatic emitter, so the legacy untyped array wrapper was removed: the
12
+ * Owner manual pain path is the only consumer and it uses the typed API.
14
13
  */
15
14
  import type { PainEvidenceEntry } from '@principles/core/runtime-v2';
16
15
  import type { WorkspaceContext } from '../core/workspace-context.js';
@@ -34,9 +33,3 @@ export type TrajectoryEvidenceAcquisition = {
34
33
  * as available evidence.
35
34
  */
36
35
  export declare function acquireTrajectoryEvidence(wctx: WorkspaceContext, sessionId: string): TrajectoryEvidenceAcquisition;
37
- /**
38
- * Legacy array API (compatibility wrapper, PRI-642 frozen decision #3).
39
- * Automatic emitters still consume this shape; Scope B migrates them to the
40
- * typed API one family at a time before this wrapper may be removed.
41
- */
42
- export declare function buildTrajectoryEvidence(wctx: WorkspaceContext, sessionId: string): PainEvidenceEntry[];
@@ -14,6 +14,10 @@
14
14
  * (TriggerController) is the only admission authority.
15
15
  * Core only sees SourceKind and TriageResult.
16
16
  *
17
+ * Phase A: the context-driven upgrade flags (unsafe-high-confidence,
18
+ * risky-high-score, repeated-failure) are retired. A descriptor decision is
19
+ * final; technical failures and RuleHost blocks never self-admit as Pain.
20
+ *
17
21
  * ERR checklist:
18
22
  * - ERR-001: Source kind derived from runtime values with guards, not `as` casts.
19
23
  * - ERR-002: Every triage result carries reason + nextAction.
@@ -30,30 +34,13 @@ import { type TriageResult, type SourceKind } from '@principles/core/runtime-v2'
30
34
  */
31
35
  export { resolveSourceKind, buildToolFailureObservation, type RawObservation } from './raw-observation-adapter.js';
32
36
  /**
33
- * Evaluate evidence triage for a given source kind and context.
37
+ * Evaluate evidence triage for a given source kind and score.
34
38
  *
35
39
  * This is the main entry point for hooks. It calls the pure triage policy
36
- * from principles-core and returns the result.
40
+ * from principles-core and returns the descriptor decision unchanged.
37
41
  *
38
42
  * PRI-752 reality check: the painEvidenceAdmission flag is NOT consulted by
39
43
  * any caller on this path — Gate B admission is unconditional. This doc block
40
44
  * previously described a flag check / fallback that does not exist as code.
41
45
  */
42
- export declare function evaluateEvidenceTriage(sourceKind: SourceKind, score: number, options?: {
43
- isUnsafeHighConfidence?: boolean;
44
- provenance?: 'host_context_bound' | 'owner_reported_no_host_trace' | 'automatic_hook';
45
- consecutiveErrors?: number;
46
- isRisky?: boolean;
47
- }): TriageResult;
48
- /**
49
- * Determine if a gate-blocked action is a high-confidence unsafe action.
50
- *
51
- * This is a heuristic that the plugin adapter owns. Core does not know about
52
- * these heuristics — it only receives the boolean flag.
53
- *
54
- * Criteria for high-confidence unsafe:
55
- * - Score >= 70 (high severity)
56
- * - Tool is in the risky write set
57
- * - Action would be irreversible (file deletion, force push, etc.)
58
- */
59
- export declare function isHighConfidenceUnsafeAction(score: number, isRisky: boolean): boolean;
46
+ export declare function evaluateEvidenceTriage(sourceKind: SourceKind, score: number): TriageResult;
@@ -7,7 +7,6 @@ export interface OpenClawHostRuntimeOptions {
7
7
  ruleInputEnrichmentProvider?(event: PluginHookBeforeToolCallEvent, context: PluginHookToolContext, request: ProductionRuleContextRequest): unknown | Promise<unknown>;
8
8
  onBeforeToolResult?(event: PluginHookBeforeToolCallEvent, context: PluginHookToolContext, result: HostEventResult): PluginHookBeforeToolCallResult | void;
9
9
  painEnrichmentProvider?(event: PluginHookAfterToolCallEvent, context: PluginHookToolContext): ProductionPainEnrichment | Promise<ProductionPainEnrichment>;
10
- onAfterToolResult?(event: PluginHookAfterToolCallEvent, context: PluginHookToolContext, result: HostEventResult): void | Promise<void>;
11
10
  }
12
11
  export interface OpenClawHostRuntime {
13
12
  readonly runtime: HostRuntime;
@@ -2,7 +2,7 @@
2
2
  "id": "principles-disciple",
3
3
  "name": "Principles Disciple",
4
4
  "description": "Principles Disciple is an AI Agent Governance System. Stop correcting the same AI behavior across sessions. Turn repeated Agent corrections into Owner-approved, observable, reversible behavior principles.",
5
- "version": "2.4.0",
5
+ "version": "2.5.0",
6
6
  "activation": {
7
7
  "onStartup": true,
8
8
  "onCapabilities": [
@@ -2,7 +2,7 @@
2
2
  "id": "principles-disciple",
3
3
  "name": "Principles Disciple",
4
4
  "description": "Principles Disciple is an AI Agent Governance System. Stop correcting the same AI behavior across sessions. Turn repeated Agent corrections into Owner-approved, observable, reversible behavior principles.",
5
- "version": "2.4.0",
5
+ "version": "2.5.0",
6
6
  "activation": {
7
7
  "onStartup": true,
8
8
  "onCapabilities": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "principles-disciple",
3
- "version": "2.4.0",
3
+ "version": "2.5.0",
4
4
  "description": "Principles Disciple is an AI Agent Governance System. Stop correcting the same AI behavior across sessions. Turn repeated Agent corrections into Owner-approved, observable, reversible behavior principles.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -133,9 +133,6 @@ function installsOpenClaw(host) {
133
133
  function installsWorkbuddy(host) {
134
134
  return host === 'workbuddy' || host === 'all';
135
135
  }
136
- function installedPluginDir() {
137
- return getInstalledPluginDir();
138
- }
139
136
  function pluginInstallDirs() {
140
137
  return installsOpenClaw(activeHostTarget)
141
138
  ? [getInstalledPluginDir(), getPluginExtDir()]
@@ -1909,77 +1906,13 @@ function syncPdCli(pluginDir) {
1909
1906
  if (existsSync(bundledNodeModules)) {
1910
1907
  cpSync(bundledNodeModules, path.join(installedPdCliDir, 'node_modules'), { recursive: true });
1911
1908
  }
1912
- // Create node_modules/@principles/core symlink so pd-cli can resolve
1913
- // its @principles/core dependency (rewritten to "file:../core" by bundle-plugin.mjs).
1914
- // Without this, `node dist/index.js --version` fails because static imports
1915
- // from @principles/core/runtime-v2 cannot be resolved.
1916
- const coreLinkDir = path.join(installedPdCliDir, 'node_modules', '@principles');
1917
- const coreLinkTarget = path.join(getPdRuntimeDir(), 'core');
1918
- mkdirSync(coreLinkDir, { recursive: true });
1919
- const coreLinkPath = path.join(coreLinkDir, 'core');
1920
- if (!existsSync(coreLinkPath)) {
1921
- if (isWindows()) {
1922
- // On Windows, use a junction (directory symlink) which doesn't require elevated privileges
1923
- symlinkSync(coreLinkTarget, coreLinkPath, 'junction');
1924
- }
1925
- else {
1926
- // On Unix, use a relative symlink for portability
1927
- symlinkSync('../../../core', coreLinkPath, 'dir');
1928
- }
1929
- }
1930
- // Create node_modules/@principles/host-runtime symlink so pd-cli can resolve
1931
- // its @principles/host-runtime dependency (rewritten to "file:../host-runtime"
1932
- // by bundle-plugin.mjs). Without this, `pd --version` crashes with
1933
- // ERR_MODULE_NOT_FOUND because pd-cli statically imports createProductionHostRuntime.
1934
- // host-runtime's own better-sqlite3 / js-yaml / @principles/core dependencies
1935
- // resolve through the plugin's <ext>/node_modules/ (shared via Node's upward
1936
- // module resolution), so no separate npm install is needed.
1937
- const hostRuntimeLinkTarget = path.join(getPdRuntimeDir(), 'host-runtime');
1938
- const hostRuntimeLinkPath = path.join(coreLinkDir, 'host-runtime');
1939
- if (!existsSync(hostRuntimeLinkPath)) {
1940
- if (isWindows()) {
1941
- symlinkSync(hostRuntimeLinkTarget, hostRuntimeLinkPath, 'junction');
1942
- }
1943
- else {
1944
- symlinkSync('../../../host-runtime', hostRuntimeLinkPath, 'dir');
1945
- }
1946
- }
1947
- // Create node_modules/@principles/codex-adapter symlink so pd-cli can resolve
1948
- // its @principles/codex-adapter dependency (rewritten to
1949
- // "file:../codex-adapter" by bundle-plugin.mjs). Without this, `pd codex
1950
- // worker` crashes with ERR_MODULE_NOT_FOUND (PRI-624).
1951
- const codexAdapterLinkTarget = path.join(getPdRuntimeDir(), 'codex-adapter');
1952
- const codexAdapterLinkPath = path.join(coreLinkDir, 'codex-adapter');
1953
- if (!existsSync(codexAdapterLinkPath)) {
1954
- if (isWindows()) {
1955
- symlinkSync(codexAdapterLinkTarget, codexAdapterLinkPath, 'junction');
1956
- }
1957
- else {
1958
- symlinkSync('../../../codex-adapter', codexAdapterLinkPath, 'dir');
1959
- }
1960
- }
1961
- // Create node_modules/principles-disciple symlink so pd-cli can resolve
1962
- // its principles-disciple dependency (the plugin package, rewritten to
1963
- // "file:../plugin" by bundle-plugin.mjs). The plugin is installed at the
1964
- // extension dir root (getPluginExtDir()), so the symlink target is the
1965
- // ext dir itself — Node resolves `import 'principles-disciple'` via the
1966
- // plugin's package.json exports field.
1967
- // Without this, `pd runtime init` crashes with ERR_MODULE_NOT_FOUND
1968
- // because runtime-init.ts statically imports initTrajectorySchema.
1969
- const pdLinkDir = path.join(installedPdCliDir, 'node_modules');
1970
- const pdLinkTarget = installedPluginDir();
1971
- mkdirSync(pdLinkDir, { recursive: true });
1972
- const pdLinkPath = path.join(pdLinkDir, 'principles-disciple');
1973
- if (!existsSync(pdLinkPath)) {
1974
- if (isWindows()) {
1975
- symlinkSync(pdLinkTarget, pdLinkPath, 'junction');
1976
- }
1977
- else {
1978
- // Relative from <ext>/pd-cli/node_modules/ to <ext>/: go up twice
1979
- // (node_modules → pd-cli → ext)
1980
- symlinkSync('../../', pdLinkPath, 'dir');
1981
- }
1982
- }
1909
+ // G3 §10.5: the pd-cli sibling links (core / host-runtime / codex-adapter /
1910
+ // workbuddy-adapter / install-layout / principles-disciple) are NO LONGER
1911
+ // hand-rolled here. install() materializes them via
1912
+ // ensurePdCliResolution() AFTER installPdCliDependencies(), so a physical
1913
+ // copy produced by the dependency stage can never be silently kept — this
1914
+ // block used to short-circuit on existsSync() and leave npm-materialized
1915
+ // copies in place.
1983
1916
  tryUpgradePdCliFromNpm(installedPdCliDir);
1984
1917
  const installedBinDir = getInstalledBinDir();
1985
1918
  mkdirSync(installedBinDir, { recursive: true });
@@ -2157,29 +2090,11 @@ function installConsole(consoleDir) {
2157
2090
  }
2158
2091
  rmSync(consoleDest, { recursive: true, force: true });
2159
2092
  cpSync(consoleSrc, consoleDest, { recursive: true });
2160
- const pluginLinkPath = path.join(consoleDest, 'node_modules', 'principles-disciple');
2161
- mkdirSync(path.dirname(pluginLinkPath), { recursive: true });
2162
- if (!existsSync(pluginLinkPath)) {
2163
- if (isWindows()) {
2164
- symlinkSync(installedPluginDir(), pluginLinkPath, 'junction');
2165
- }
2166
- else {
2167
- symlinkSync(path.relative(path.dirname(pluginLinkPath), installedPluginDir()), pluginLinkPath, 'dir');
2168
- }
2169
- }
2170
- // PRI-672: console resolves its create-principles-disciple dependency (the
2171
- // ReleaseManager authority module, rewritten to file:../release-manager by
2172
- // bundle-plugin.mjs) through this link into ~/.pd/runtime.
2173
- const releaseManagerLinkPath = path.join(consoleDest, 'node_modules', 'create-principles-disciple');
2174
- if (!existsSync(releaseManagerLinkPath)) {
2175
- mkdirSync(path.dirname(releaseManagerLinkPath), { recursive: true });
2176
- if (isWindows()) {
2177
- symlinkSync(getInstalledReleaseManagerDir(), releaseManagerLinkPath, 'junction');
2178
- }
2179
- else {
2180
- symlinkSync(path.relative(path.dirname(releaseManagerLinkPath), getInstalledReleaseManagerDir()), releaseManagerLinkPath, 'dir');
2181
- }
2182
- }
2093
+ // G3 §10.5: the console's sibling links (core / host-runtime / install-layout
2094
+ // / principles-disciple / create-principles-disciple) are materialized by
2095
+ // ensureConsoleResolution() AFTER installConsoleDependencies() — see
2096
+ // ensurePdCliResolution() for why the old existsSync() short-circuit was
2097
+ // removed instead of kept.
2183
2098
  }
2184
2099
  function getInstalledCoreDir() {
2185
2100
  return path.join(getPdRuntimeDir(), 'core');
@@ -2312,6 +2227,11 @@ function ensureComponentFileDependencyLinks(componentDir, componentLabel) {
2312
2227
  if (!existsSync(siblingDir)) {
2313
2228
  throw new Error(`${componentLabel} depends on ${ref} but the sibling runtime component is missing: ${siblingDir}`);
2314
2229
  }
2230
+ // rc-1: the dependency NAME is manifest input too — it becomes a path
2231
+ // segment under node_modules, so a crafted name must not escape it.
2232
+ if (!/^(@[A-Za-z0-9._-]+\/)?[A-Za-z0-9._-]+$/.test(name)) {
2233
+ throw new Error(`Installed ${componentLabel} declares an unsupported dependency name "${name}".`);
2234
+ }
2315
2235
  const linkPath = path.join(componentDir, 'node_modules', name);
2316
2236
  let stat;
2317
2237
  try {
@@ -2341,6 +2261,30 @@ function ensureComponentFileDependencyLinks(componentDir, componentLabel) {
2341
2261
  }
2342
2262
  }
2343
2263
  }
2264
+ /**
2265
+ * G3 §10.5: materialize the INSTALLED pd-cli's `file:../` sibling links
2266
+ * (core / host-runtime / codex-adapter / workbuddy-adapter / install-layout /
2267
+ * principles-disciple) through the shared helper. Replaces the hand-rolled
2268
+ * per-dependency blocks that used to live in syncPdCli(): those short-circuited
2269
+ * on existsSync(), so an npm-materialized physical copy silently won over the
2270
+ * intended runtime sibling.
2271
+ *
2272
+ * Ordering contract: MUST run after installPdCliDependencies() (the dependency
2273
+ * stage is what can (re)materialize node_modules) AND after every sibling is
2274
+ * deployed. A missing sibling fails the install loud (the helper).
2275
+ */
2276
+ export function ensurePdCliResolution() {
2277
+ ensureComponentFileDependencyLinks(getInstalledPdCliDir(), '@principles/pd-cli');
2278
+ }
2279
+ /**
2280
+ * G3 §10.5: same contract for the INSTALLED pd-console (core / host-runtime /
2281
+ * install-layout / principles-disciple / create-principles-disciple). Runs
2282
+ * after installConsoleDependencies() so npm-materialized copies are corrected
2283
+ * instead of silently kept.
2284
+ */
2285
+ export function ensureConsoleResolution() {
2286
+ ensureComponentFileDependencyLinks(getInstalledConsoleDir(), '@principles/pd-console');
2287
+ }
2344
2288
  /**
2345
2289
  * PRI-711: materialize node_modules links for the INSTALLED codex-adapter so
2346
2290
  * its declared `file:../<component>` dependencies resolve under ESM realpath
@@ -3805,6 +3749,10 @@ transaction) {
3805
3749
  if (pdCliSync.globalShim !== null)
3806
3750
  globalShimRecord = pdCliSync.globalShim;
3807
3751
  await installPdCliDependencies();
3752
+ // G3 §10.5: materialize the sibling links AFTER the dependency stage — every
3753
+ // sibling component is already deployed at this point, and a physical copy
3754
+ // the dependency stage produced is now corrected rather than silently kept.
3755
+ ensurePdCliResolution();
3808
3756
  stepIndex++;
3809
3757
  if (spinner)
3810
3758
  updateProgress(spinner, stepIndex, 'Preparing core library for pd-cli...');
@@ -3836,6 +3784,10 @@ transaction) {
3836
3784
  if (spinner)
3837
3785
  updateProgress(spinner, stepIndex, 'Validating bundled console dependencies...');
3838
3786
  await installConsoleDependencies();
3787
+ // G3 §10.5: same ordering contract as pd-cli — links after the dependency
3788
+ // stage, with every console sibling (plugin / release-manager / core /
3789
+ // host-runtime / install-layout) already deployed.
3790
+ ensureConsoleResolution();
3839
3791
  stepIndex++;
3840
3792
  // PRI-912 (SPEC-P1′-A): dedup the plugin's bundled @principles/core copy
3841
3793
  // into a canonical junction only after EVERY component is deployed, so a
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-principles-disciple",
3
- "version": "1.147.1",
3
+ "version": "1.147.3",
4
4
  "description": "Interactive CLI installer for Principles Disciple OpenClaw plugin",
5
5
  "type": "module",
6
6
  "bin": {
@@ -47,6 +47,7 @@
47
47
  "prepublishOnly": "npm run build:deps && npm run build && npm run bundle",
48
48
  "test": "vitest run",
49
49
  "test:fast": "vitest run --exclude tests/smoke-packaged-install.test.ts --exclude tests/release-asset-smoke.test.ts --exclude tests/release-upgrade-gate.test.ts --exclude tests/release-junction-lifecycle.test.ts",
50
+ "typecheck:tests": "tsc -p tsconfig.tests.json",
50
51
  "test:smoke:packaged": "vitest run tests/smoke-packaged-install.test.ts",
51
52
  "test:smoke:release-asset": "vitest run tests/release-asset-smoke.test.ts"
52
53
  },
@@ -400,32 +400,6 @@ export async function processWorkbuddyHookInvocation(rawStdin, channelEventName,
400
400
  currentToolCallId: event.context.toolCallId ?? '',
401
401
  toolSemantics: WORKBUDDY_TOOL_SEMANTICS,
402
402
  }),
403
- // Remediation R2 (candidate-level admission): the diagnostician's
404
- // candidates are admitted ONLY with input evidence (needs_evidence
405
- // otherwise), and Codex-style transcript promotion does not exist on
406
- // this host. OpenClaw-parity: the HOOK supplies the evidence — a
407
- // sourceRef to the durable raw event line (idempotent replay source,
408
- // SPEC §13.7) plus a bounded failure note. No raw tool output is copied
409
- // (ADR-0027 hook-log content rule).
410
- painEnrichmentProvider: (hostEvent) => {
411
- if (hostEvent.kind !== 'after_tool_call')
412
- return {};
413
- const toolName = hostEvent.context.toolName ?? 'unknown-tool';
414
- const output = hostEvent.context.toolOutput;
415
- const detail = typeof output === 'object' && output !== null && !Array.isArray(output)
416
- ? Object.hasOwn(output, 'tool_error_code')
417
- ? `tool_error_code=${String(output.tool_error_code)}`
418
- : Object.hasOwn(output, 'exitCode')
419
- ? `exitCode=${String(output.exitCode)}`
420
- : 'failure'
421
- : 'failure';
422
- return {
423
- evidence: [{
424
- sourceRef: `workbuddy-pd-hook-event-log:${hostEvent.context.sessionId}`,
425
- note: `${toolName} failed (${detail}); raw payload in the durable workbuddy hook event log for this session`,
426
- }],
427
- };
428
- },
429
403
  }).dispatch(event);
430
404
  const evaluationDiagnostics = recordRuleHostEvaluations(stateDir, event.context.sessionId, result.metadata?.evaluations);
431
405
  // Encode BEFORE recording an attributed deny: a runtime_verified
@@ -1,13 +1,7 @@
1
- import { type AdmitBareHostPainsResult, type InternalizationConsumerCycleOutcome, type ConsumerCycleLogger, type ReconcileGovernanceContinuationResult, type SignalLlmClassifier, type Stage2CorrectionCycleReport } from '@principles/host-runtime';
1
+ import { type InternalizationConsumerCycleOutcome, type ConsumerCycleLogger, type ReconcileGovernanceContinuationResult, type SignalLlmClassifier, type Stage2CorrectionCycleReport } from '@principles/host-runtime';
2
2
  export type WorkbuddyWorkerMode = 'ready' | 'manual_action_required' | 'paused' | 'degraded';
3
3
  export interface WorkbuddyWorkerCycleStepReport {
4
4
  readonly reconcile: ReconcileGovernanceContinuationResult;
5
- /**
6
- * Bare-pain admission sweep (review R2/P1): the WorkBuddy hook writes bare
7
- * failure pains with no inline admission, so the worker admits them into the
8
- * shared governance queue before the diagnostician step.
9
- */
10
- readonly admission: AdmitBareHostPainsResult;
11
5
  /** At most ONE diagnostician execution per cycle (bounded work). */
12
6
  readonly diagnostician: {
13
7
  readonly taskId: string;
@@ -7,10 +7,7 @@
7
7
  * the WorkBuddy MVP excludes transcript ingestion (SPEC §1 Excluded; the
8
8
  * hook itself is the only evidence producer):
9
9
  *
10
- * 1. run the idempotent reconciliation pass (shared host-runtime authority),
11
- * then admit the hook's BARE failure pains into the same governance
12
- * queue (review R2/P1 — no inline admission exists on this host; the
13
- * sweep reuses the ONE admission table and the crash-safe task ensure)
10
+ * 1. run the idempotent reconciliation pass (shared host-runtime authority)
14
11
  * 2. lease + run one Diagnostician execution, then ONE bounded downstream
15
12
  * consumer cycle through the SHARED host-neutral executor
16
13
  * (internalization_auto_consumer = workspace execution authority)
@@ -33,7 +30,7 @@
33
30
  import fs from 'node:fs';
34
31
  import path from 'node:path';
35
32
  import { computeFeatureFlagsFromConfig, createRuntimeStateHandle, createPainSignalBridge, isRetryWaitBackoffElapsed, PrincipleTreeLedgerAdapter, resolveDiagnosticianCapability, } from '@principles/core/runtime-v2';
36
- import { admitBareHostPains, loadPdConfigForPlugin, loadFeatureFlagFromConfig, reconcileGovernanceContinuation, runInternalizationConsumerCycle, runStage2CorrectionCycle, createSignalClassifierForWorkspace, saveHostToolDeclaration, } from '@principles/host-runtime';
33
+ import { loadPdConfigForPlugin, loadFeatureFlagFromConfig, reconcileGovernanceContinuation, runInternalizationConsumerCycle, runStage2CorrectionCycle, createSignalClassifierForWorkspace, saveHostToolDeclaration, } from '@principles/host-runtime';
37
34
  import { WORKBUDDY_TOOL_SEMANTICS, WORKBUDDY_TOOL_SEMANTIC_MAPPINGS } from '../tool-semantics.js';
38
35
  const WORKER_OWNER = 'companion-worker';
39
36
  const DEFAULT_DIAG_CANDIDATE_LIMIT = 5;
@@ -103,12 +100,6 @@ export async function runWorkbuddyWorkspaceWorkerCycle(options) {
103
100
  const diagnosticianDisabled = !capability.available;
104
101
  // Step 2 — Idempotent reconciliation (always runs; creates no LLM work).
105
102
  const reconcile = await reconcileGovernanceContinuation({ workspaceDir, conversationIngestionEnabled: false });
106
- // Step 2b — Bare-pain admission (review R2/P1): the hook leaves bare
107
- // workbuddy failure pains that no inline admission exists for. Without this
108
- // sweep the evidence rows never reach the diagnostician queue. Runs AFTER
109
- // reconcile (which continues already-admitted markers) and ensures tasks
110
- // through the same crash-safe seam; bounded and idempotent.
111
- const admission = await admitBareHostPains({ workspaceDir, hostKind: 'workbuddy' });
112
103
  // Steps 3–5 — execution authority: internalization_auto_consumer.
113
104
  let diagnostician = null;
114
105
  if (diagnosticianDisabled) {
@@ -125,7 +116,7 @@ export async function runWorkbuddyWorkspaceWorkerCycle(options) {
125
116
  mode: 'paused',
126
117
  reason: 'internalization_auto_consumer_disabled',
127
118
  nextAction: 'Automatic internalization execution is paused for this governance workspace; manual commands remain available: pd diagnose, pd runtime internalization run-once.',
128
- report: { reconcile, admission, diagnostician: null, downstream: null },
119
+ report: { reconcile, diagnostician: null, downstream: null },
129
120
  };
130
121
  }
131
122
  else {
@@ -174,7 +165,7 @@ export async function runWorkbuddyWorkspaceWorkerCycle(options) {
174
165
  mode: 'degraded',
175
166
  reason: `diagnostician_execution_failed:${detail}`,
176
167
  nextAction: 'Inspect the governance workspace runtime profile and provider configuration; the task keeps its pending/retry state and no evidence was mutated.',
177
- report: { reconcile, admission, diagnostician: null, downstream: null },
168
+ report: { reconcile, diagnostician: null, downstream: null },
178
169
  };
179
170
  }
180
171
  }
@@ -194,7 +185,7 @@ export async function runWorkbuddyWorkspaceWorkerCycle(options) {
194
185
  mode: 'degraded',
195
186
  reason: `host_tool_declaration_persist_failed:${declared.reason}`,
196
187
  nextAction: 'Repair WorkBuddy host declaration persistence (.pd/host-tool-semantics/workbuddy.json) before running the downstream internalization cycle; the worker retries automatically on the next cycle.',
197
- report: { reconcile, admission, diagnostician, downstream: null },
188
+ report: { reconcile, diagnostician, downstream: null },
198
189
  };
199
190
  }
200
191
  const downstream = await runInternalizationConsumerCycle(workspaceDir, {
@@ -226,16 +217,15 @@ export async function runWorkbuddyWorkspaceWorkerCycle(options) {
226
217
  onEvent: emitEvent,
227
218
  });
228
219
  const degradedReason = !reconcile.ok ? `reconcile:${reconcile.reason ?? 'failed'}`
229
- : !admission.ok ? `admission:${admission.reason ?? 'failed'}`
230
- : diagnostician?.status === 'failed' && diagnostician.errorCategory !== 'lease_conflict' ? `diagnostician_failed:${diagnostician.message ?? 'max_attempts_exceeded'}`
231
- : diagnostician?.status === 'degraded' ? `diagnostician_degraded:${diagnostician.message ?? 'unknown'}`
232
- : downstream.skipReason === 'runtime_config_error' || downstream.skipReason === 'cycle_error' || downstream.skipReason === 'config_malformed' ? `downstream:${downstream.skipReason}`
233
- : !stage2.ok ? `stage2:${stage2.reason ?? 'failed'}`
234
- : undefined;
220
+ : diagnostician?.status === 'failed' && diagnostician.errorCategory !== 'lease_conflict' ? `diagnostician_failed:${diagnostician.message ?? 'max_attempts_exceeded'}`
221
+ : diagnostician?.status === 'degraded' ? `diagnostician_degraded:${diagnostician.message ?? 'unknown'}`
222
+ : downstream.skipReason === 'runtime_config_error' || downstream.skipReason === 'cycle_error' || downstream.skipReason === 'config_malformed' ? `downstream:${downstream.skipReason}`
223
+ : !stage2.ok ? `stage2:${stage2.reason ?? 'failed'}`
224
+ : undefined;
235
225
  return {
236
226
  ...base,
237
227
  mode: degradedReason !== undefined ? 'degraded' : 'ready',
238
228
  ...(degradedReason !== undefined ? { reason: degradedReason, nextAction: 'Inspect the governance workspace .pd/config.yaml runtime profile and the per-step report above; the worker retries automatically on the next cycle.' } : {}),
239
- report: { reconcile, admission, diagnostician, downstream, stage2 },
229
+ report: { reconcile, diagnostician, downstream, stage2 },
240
230
  };
241
231
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@principles/workbuddy-adapter",
3
- "version": "0.4.1",
3
+ "version": "0.5.0",
4
4
  "description": "WorkBuddy host adapter for Principles Disciple — implements the HostAdapter interface for WorkBuddy's Git Bash command-hook model (ADR-0020 third host, SPEC workbuddy-host-adapter v0.3.0).",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",