principles-disciple 1.161.0 → 1.162.0

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.
@@ -12,12 +12,14 @@ import { normalizePath } from '../utils/io.js';
12
12
  import { WorkspaceContext } from '../core/workspace-context.js';
13
13
  import { recordGateBlockAndReturn } from './gate-block-helper.js';
14
14
  import { RuleHost } from '../core/rule-host.js';
15
- import { validateCorrectionProposal, validateProposedPathBounds } from '@principles/core/runtime-v2';
15
+ import { validateCorrectionProposal, validateProposedPathBounds, computeFeatureFlagsFromConfig, UNAVAILABLE_RULE_CONTEXT } from '@principles/core/runtime-v2';
16
16
  import { AGENT_TOOLS, BASH_TOOLS_SET, WRITE_TOOLS } from '../constants/tools.js';
17
17
  import { getSession, hasRecentThinking } from '../core/session-tracker.js';
18
18
  import { getEvolutionEngine } from '../core/evolution-engine.js';
19
19
  import { EventLogService } from '../core/event-log.js';
20
20
  import { estimateLineChanges } from '@principles/core/runtime-v2';
21
+ import { loadPdConfigForPlugin } from '../core/pd-config-loader.js';
22
+ import { buildProductionRuleContext } from '../core/rule-context-assembler.js';
21
23
  export function handleBeforeToolCall(event, ctx) {
22
24
  const logger = ctx.logger || console;
23
25
  // 1. Identify tool type
@@ -53,6 +55,10 @@ export function handleBeforeToolCall(event, ctx) {
53
55
  // 3. Rule Host Evaluation — sole gate
54
56
  try {
55
57
  const ruleHost = new RuleHost(wctx.stateDir, logger, { workspaceDir: ctx.workspaceDir });
58
+ // PRI-483 Phase 4: assemble RuleContextV2 when `rulecode_context_v2` flag is ON.
59
+ // flag OFF → undefined (v1 zero-change, no trajectory access).
60
+ // flag ON → RuleContextV2 (available or unavailable). Never throws (ERR-024).
61
+ const ruleContext = _buildRuleContextIfEnabled(wctx, relPath, ctx.sessionId, logger);
56
62
  const hostInput = {
57
63
  action: {
58
64
  toolName: event.toolName,
@@ -80,6 +86,7 @@ export function handleBeforeToolCall(event, ctx) {
80
86
  estimatedLineChanges: estimateLineChanges({ toolName: event.toolName, params: event.params ?? {} }),
81
87
  bashRisk: _getBashRisk(event),
82
88
  },
89
+ context: ruleContext,
83
90
  };
84
91
  const hostResult = ruleHost.evaluate(hostInput);
85
92
  // Always emit rulehost_evaluated
@@ -379,3 +386,53 @@ function _getBashRisk(event) {
379
386
  return 'unknown';
380
387
  }
381
388
  }
389
+ /**
390
+ * PRI-483 Phase 4 — Build RuleContextV2 for RuleHost.evaluate when the
391
+ * `rulecode_context_v2` feature flag is ON. Returns `undefined` when the flag
392
+ * is OFF (v1 zero-change — does NOT touch trajectory) or when config loading
393
+ * fails (conservative fail-soft: can't determine flag state → v1-style).
394
+ *
395
+ * ERR-024 prevention: context assembly failures never skip RuleHost.evaluate.
396
+ * - loadPdConfigForPlugin throws → return undefined (v1-style)
397
+ * - buildProductionRuleContext throws → return UNAVAILABLE_RULE_CONTEXT
398
+ * (structured unavailable so v2 rules see "context unavailable" and allow)
399
+ *
400
+ * Spec: docs/superpowers/specs/2026-06-27-rulecode-context-vision-design.md §5.3
401
+ */
402
+ function _buildRuleContextIfEnabled(wctx, targetPath, sessionId, logger) {
403
+ // Step 1: load PD config (flag-gated). If this throws, we can't safely
404
+ // determine whether v2 context is required — fall back to v1 (undefined).
405
+ let configResult;
406
+ try {
407
+ configResult = loadPdConfigForPlugin(wctx.workspaceDir);
408
+ }
409
+ catch (err) {
410
+ logger?.warn?.(`[PD_GATE] RuleContext v2: config load failed, skipping context assembly: ${String(err)}`);
411
+ return undefined;
412
+ }
413
+ // Step 2: compute effective flags and check rulecode_context_v2.
414
+ // Explicit ok:false guard (rc-9-no-silent-fallback): when config is malformed,
415
+ // do NOT silently fall through to flag computation on defaults — log and
416
+ // return v1-style undefined so config issues surface to the operator.
417
+ if (!configResult.ok) {
418
+ const reasons = configResult.errors.map(e => e.reason).join('; ');
419
+ logger?.warn?.(`[PD_GATE] RuleContext v2: config load returned malformed result, skipping context assembly: ${reasons}`);
420
+ return undefined;
421
+ }
422
+ const flagsResult = computeFeatureFlagsFromConfig(configResult.effective);
423
+ const v2Flag = flagsResult.flags.rulecode_context_v2;
424
+ if (!v2Flag?.enabled) {
425
+ // Flag OFF → v1 zero-change. Do NOT access trajectory (spec §10.1).
426
+ return undefined;
427
+ }
428
+ // Step 3: flag ON → assemble context via production data source.
429
+ // buildProductionRuleContext is fail-soft internally (returns unavailable),
430
+ // but wrap in try/catch as defense-in-depth (ERR-024).
431
+ try {
432
+ return buildProductionRuleContext(sessionId, targetPath, wctx.trajectory, wctx.workspaceDir);
433
+ }
434
+ catch (err) {
435
+ logger?.warn?.(`[PD_GATE] RuleContext v2: buildProductionRuleContext threw unexpectedly, using unavailable context: ${String(err)}`);
436
+ return UNAVAILABLE_RULE_CONTEXT;
437
+ }
438
+ }
@@ -2,7 +2,7 @@
2
2
  "id": "principles-disciple",
3
3
  "name": "Principles Disciple",
4
4
  "description": "Evolutionary programming agent framework with strategic guardrails and reflection loops.",
5
- "version": "1.161.0",
5
+ "version": "1.162.0",
6
6
  "activation": {
7
7
  "onCapabilities": [
8
8
  "hook"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "principles-disciple",
3
- "version": "1.161.0",
3
+ "version": "1.162.0",
4
4
  "description": "Native OpenClaw plugin for Principles Disciple",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",