create-principles-disciple 1.95.0 → 1.97.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.
- package/console/dist/server/config/pd-config-store.js +49 -12
- package/console/dist/server/index.js +4 -3
- package/console/dist/server/models/IntentPageModel.d.ts +36 -2
- package/console/dist/server/models/IntentPageModel.js +213 -11
- package/console/dist/server/routes/intent.d.ts +5 -1
- package/console/dist/server/routes/intent.js +200 -12
- package/console/dist/types.d.ts +1 -0
- package/console/dist/ui/App.js +0 -53
- package/console/dist/ui/api.d.ts +18 -4
- package/console/dist/ui/api.js +38 -5
- package/console/dist/ui/components/layout/app-sidebar.js +12 -12
- package/console/dist/ui/components/ui/badge.d.ts +1 -1
- package/console/dist/ui/i18n/en.json +142 -3
- package/console/dist/ui/i18n/zh-CN.json +142 -3
- package/console/dist/ui/pages/control-center/AgentCard.d.ts +31 -0
- package/console/dist/ui/pages/control-center/AgentCard.js +156 -0
- package/console/dist/ui/pages/control-center/AgentGroup.d.ts +26 -0
- package/console/dist/ui/pages/control-center/AgentGroup.js +38 -0
- package/console/dist/ui/pages/control-center/ControlCenterPage.js +77 -41
- package/console/dist/ui/pages/control-center/WorkflowDiagram.d.ts +17 -0
- package/console/dist/ui/pages/control-center/WorkflowDiagram.js +55 -0
- package/console/dist/ui/pages/intent/IntentOnboarding.d.ts +67 -0
- package/console/dist/ui/pages/intent/IntentOnboarding.js +289 -0
- package/console/dist/ui/pages/intent/IntentPage.js +117 -6
- package/console/dist/ui/utils/agent-metadata.d.ts +58 -0
- package/console/dist/ui/utils/agent-metadata.js +275 -0
- package/console/dist/ui/utils/control-center-helpers.d.ts +19 -0
- package/console/dist/ui/utils/control-center-helpers.js +37 -0
- package/console/dist/ui/utils/validators.d.ts +37 -0
- package/console/dist/ui/utils/validators.js +130 -0
- package/console/dist/web/assets/app.css +360 -3
- package/console/dist/web/assets/app.js +2952 -1143
- package/console/package.json +1 -1
- package/core/dist/runtime-v2/__tests__/architecture-regression.test.js +27 -35
- package/core/dist/runtime-v2/__tests__/architecture-regression.test.js.map +1 -1
- package/core/dist/runtime-v2/__tests__/evaluator-runner-vslice-v2.test.js +85 -7
- package/core/dist/runtime-v2/__tests__/evaluator-runner-vslice-v2.test.js.map +1 -1
- package/core/dist/runtime-v2/__tests__/golden-trace-replay-validator.test.js +70 -0
- package/core/dist/runtime-v2/__tests__/golden-trace-replay-validator.test.js.map +1 -1
- package/core/dist/runtime-v2/__tests__/golden-trace.test.js +136 -1
- package/core/dist/runtime-v2/__tests__/golden-trace.test.js.map +1 -1
- package/core/dist/runtime-v2/__tests__/v2-adversarial-cases.test.d.ts +2 -0
- package/core/dist/runtime-v2/__tests__/v2-adversarial-cases.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/__tests__/v2-adversarial-cases.test.js +211 -0
- package/core/dist/runtime-v2/__tests__/v2-adversarial-cases.test.js.map +1 -0
- package/core/dist/runtime-v2/activation/writers/__tests__/rule-host-writer.test.js +93 -0
- package/core/dist/runtime-v2/activation/writers/__tests__/rule-host-writer.test.js.map +1 -1
- package/core/dist/runtime-v2/activation/writers/rule-host-writer.d.ts +11 -0
- package/core/dist/runtime-v2/activation/writers/rule-host-writer.d.ts.map +1 -1
- package/core/dist/runtime-v2/activation/writers/rule-host-writer.js +22 -0
- package/core/dist/runtime-v2/activation/writers/rule-host-writer.js.map +1 -1
- package/core/dist/runtime-v2/feature-flags/__tests__/rulecode-context-v2-flag.test.d.ts +2 -0
- package/core/dist/runtime-v2/feature-flags/__tests__/rulecode-context-v2-flag.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/feature-flags/__tests__/rulecode-context-v2-flag.test.js +74 -0
- package/core/dist/runtime-v2/feature-flags/__tests__/rulecode-context-v2-flag.test.js.map +1 -0
- package/core/dist/runtime-v2/feature-flags/__tests__/surface-guard-policy.test.d.ts +2 -0
- package/core/dist/runtime-v2/feature-flags/__tests__/surface-guard-policy.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/feature-flags/__tests__/surface-guard-policy.test.js +246 -0
- package/core/dist/runtime-v2/feature-flags/__tests__/surface-guard-policy.test.js.map +1 -0
- package/core/dist/runtime-v2/feature-flags/feature-flag-contract.d.ts.map +1 -1
- package/core/dist/runtime-v2/feature-flags/feature-flag-contract.js +7 -0
- package/core/dist/runtime-v2/feature-flags/feature-flag-contract.js.map +1 -1
- package/core/dist/runtime-v2/feature-flags/index.d.ts +2 -0
- package/core/dist/runtime-v2/feature-flags/index.d.ts.map +1 -1
- package/core/dist/runtime-v2/feature-flags/index.js +2 -0
- package/core/dist/runtime-v2/feature-flags/index.js.map +1 -1
- package/{plugin/dist/core/surface-guard.d.ts → core/dist/runtime-v2/feature-flags/surface-guard-policy.d.ts} +15 -5
- package/core/dist/runtime-v2/feature-flags/surface-guard-policy.d.ts.map +1 -0
- package/{plugin/dist/core/surface-guard.js → core/dist/runtime-v2/feature-flags/surface-guard-policy.js} +14 -2
- package/core/dist/runtime-v2/feature-flags/surface-guard-policy.js.map +1 -0
- package/core/dist/runtime-v2/golden-trace-replay-validator.js +1 -1
- package/core/dist/runtime-v2/golden-trace-replay-validator.js.map +1 -1
- package/core/dist/runtime-v2/golden-trace.d.ts +19 -3
- package/core/dist/runtime-v2/golden-trace.d.ts.map +1 -1
- package/core/dist/runtime-v2/golden-trace.js +2 -0
- package/core/dist/runtime-v2/golden-trace.js.map +1 -1
- package/core/dist/runtime-v2/index.d.ts +15 -3
- package/core/dist/runtime-v2/index.d.ts.map +1 -1
- package/core/dist/runtime-v2/index.js +11 -2
- package/core/dist/runtime-v2/index.js.map +1 -1
- package/core/dist/runtime-v2/intent/__tests__/intent-doc-version.test.d.ts +2 -0
- package/core/dist/runtime-v2/intent/__tests__/intent-doc-version.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/intent/__tests__/intent-doc-version.test.js +88 -0
- package/core/dist/runtime-v2/intent/__tests__/intent-doc-version.test.js.map +1 -0
- package/core/dist/runtime-v2/intent/__tests__/intent-doc.test.js +91 -1
- package/core/dist/runtime-v2/intent/__tests__/intent-doc.test.js.map +1 -1
- package/core/dist/runtime-v2/intent/index.d.ts +2 -0
- package/core/dist/runtime-v2/intent/index.d.ts.map +1 -1
- package/core/dist/runtime-v2/intent/index.js +2 -0
- package/core/dist/runtime-v2/intent/index.js.map +1 -1
- package/core/dist/runtime-v2/intent/intent-browser.d.ts +23 -0
- package/core/dist/runtime-v2/intent/intent-browser.d.ts.map +1 -0
- package/core/dist/runtime-v2/intent/intent-browser.js +21 -0
- package/core/dist/runtime-v2/intent/intent-browser.js.map +1 -0
- package/core/dist/runtime-v2/intent/intent-doc-version.d.ts +28 -0
- package/core/dist/runtime-v2/intent/intent-doc-version.d.ts.map +1 -0
- package/core/dist/runtime-v2/intent/intent-doc-version.js +21 -0
- package/core/dist/runtime-v2/intent/intent-doc-version.js.map +1 -0
- package/core/dist/runtime-v2/intent/intent-doc.d.ts +17 -1
- package/core/dist/runtime-v2/intent/intent-doc.d.ts.map +1 -1
- package/core/dist/runtime-v2/intent/intent-doc.js +95 -7
- package/core/dist/runtime-v2/intent/intent-doc.js.map +1 -1
- package/core/dist/runtime-v2/intent/intent-hash.d.ts +2 -0
- package/core/dist/runtime-v2/intent/intent-hash.d.ts.map +1 -0
- package/core/dist/runtime-v2/intent/intent-hash.js +10 -0
- package/core/dist/runtime-v2/intent/intent-hash.js.map +1 -0
- package/core/dist/runtime-v2/internalization/__tests__/artificer-prompt-builder.test.js +41 -1
- package/core/dist/runtime-v2/internalization/__tests__/artificer-prompt-builder.test.js.map +1 -1
- package/core/dist/runtime-v2/internalization/__tests__/artificer-rule-output.test.js +130 -2
- package/core/dist/runtime-v2/internalization/__tests__/artificer-rule-output.test.js.map +1 -1
- package/core/dist/runtime-v2/internalization/__tests__/behavior-example-pack.test.d.ts +2 -0
- package/core/dist/runtime-v2/internalization/__tests__/behavior-example-pack.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/internalization/__tests__/behavior-example-pack.test.js +228 -0
- package/core/dist/runtime-v2/internalization/__tests__/behavior-example-pack.test.js.map +1 -0
- package/core/dist/runtime-v2/internalization/__tests__/diag-chain-e2e.test.js +41 -11
- package/core/dist/runtime-v2/internalization/__tests__/diag-chain-e2e.test.js.map +1 -1
- package/core/dist/runtime-v2/internalization/__tests__/refiner-sandbox-wrapper.test.js +135 -0
- package/core/dist/runtime-v2/internalization/__tests__/refiner-sandbox-wrapper.test.js.map +1 -1
- package/core/dist/runtime-v2/internalization/__tests__/rule-context-v2.test.d.ts +2 -0
- package/core/dist/runtime-v2/internalization/__tests__/rule-context-v2.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/internalization/__tests__/rule-context-v2.test.js +449 -0
- package/core/dist/runtime-v2/internalization/__tests__/rule-context-v2.test.js.map +1 -0
- package/core/dist/runtime-v2/internalization/adversarial-case.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/adversarial-case.js +24 -0
- package/core/dist/runtime-v2/internalization/adversarial-case.js.map +1 -1
- package/core/dist/runtime-v2/internalization/artificer-output.d.ts +10 -0
- package/core/dist/runtime-v2/internalization/artificer-output.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/artificer-output.js +45 -0
- package/core/dist/runtime-v2/internalization/artificer-output.js.map +1 -1
- package/core/dist/runtime-v2/internalization/artificer-prompt-builder.d.ts +2 -2
- package/core/dist/runtime-v2/internalization/artificer-prompt-builder.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/artificer-prompt-builder.js +7 -2
- package/core/dist/runtime-v2/internalization/artificer-prompt-builder.js.map +1 -1
- package/core/dist/runtime-v2/internalization/behavior-example-pack.d.ts +66 -0
- package/core/dist/runtime-v2/internalization/behavior-example-pack.d.ts.map +1 -0
- package/core/dist/runtime-v2/internalization/behavior-example-pack.js +183 -0
- package/core/dist/runtime-v2/internalization/behavior-example-pack.js.map +1 -0
- package/core/dist/runtime-v2/internalization/evaluator-output.d.ts +8 -0
- package/core/dist/runtime-v2/internalization/evaluator-output.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/evaluator-output.js +10 -0
- package/core/dist/runtime-v2/internalization/evaluator-output.js.map +1 -1
- package/core/dist/runtime-v2/internalization/evaluator-runner.d.ts +17 -0
- package/core/dist/runtime-v2/internalization/evaluator-runner.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/evaluator-runner.js +118 -24
- package/core/dist/runtime-v2/internalization/evaluator-runner.js.map +1 -1
- package/core/dist/runtime-v2/internalization/refiner-sandbox-wrapper.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/refiner-sandbox-wrapper.js +1 -1
- package/core/dist/runtime-v2/internalization/refiner-sandbox-wrapper.js.map +1 -1
- package/core/dist/runtime-v2/internalization/rule-context-v2.d.ts +61 -0
- package/core/dist/runtime-v2/internalization/rule-context-v2.d.ts.map +1 -0
- package/core/dist/runtime-v2/internalization/rule-context-v2.js +301 -0
- package/core/dist/runtime-v2/internalization/rule-context-v2.js.map +1 -0
- package/core/dist/runtime-v2/internalization/rule-host-contracts.d.ts +9 -0
- package/core/dist/runtime-v2/internalization/rule-host-contracts.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/v2-adversarial-cases.d.ts +55 -0
- package/core/dist/runtime-v2/internalization/v2-adversarial-cases.d.ts.map +1 -0
- package/core/dist/runtime-v2/internalization/v2-adversarial-cases.js +131 -0
- package/core/dist/runtime-v2/internalization/v2-adversarial-cases.js.map +1 -0
- package/core/dist/runtime-v2/pain-signal-observability.d.ts.map +1 -1
- package/core/dist/runtime-v2/pain-signal-observability.js +24 -1
- package/core/dist/runtime-v2/pain-signal-observability.js.map +1 -1
- package/core/dist/runtime-v2/risk/__tests__/risk-calculator-policy.test.d.ts +2 -0
- package/core/dist/runtime-v2/risk/__tests__/risk-calculator-policy.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/risk/__tests__/risk-calculator-policy.test.js +95 -0
- package/core/dist/runtime-v2/risk/__tests__/risk-calculator-policy.test.js.map +1 -0
- package/core/dist/runtime-v2/risk/index.d.ts +7 -0
- package/core/dist/runtime-v2/risk/index.d.ts.map +1 -0
- package/core/dist/runtime-v2/risk/index.js +6 -0
- package/core/dist/runtime-v2/risk/index.js.map +1 -0
- package/core/dist/runtime-v2/risk/risk-calculator-policy.d.ts +18 -0
- package/core/dist/runtime-v2/risk/risk-calculator-policy.d.ts.map +1 -0
- package/core/dist/runtime-v2/risk/risk-calculator-policy.js +47 -0
- package/core/dist/runtime-v2/risk/risk-calculator-policy.js.map +1 -0
- package/core/dist/runtime-v2/store/intent/__tests__/sqlite-intent-doc-version-store.test.d.ts +2 -0
- package/core/dist/runtime-v2/store/intent/__tests__/sqlite-intent-doc-version-store.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/store/intent/__tests__/sqlite-intent-doc-version-store.test.js +83 -0
- package/core/dist/runtime-v2/store/intent/__tests__/sqlite-intent-doc-version-store.test.js.map +1 -0
- package/core/dist/runtime-v2/store/intent/index.d.ts +2 -1
- package/core/dist/runtime-v2/store/intent/index.d.ts.map +1 -1
- package/core/dist/runtime-v2/store/intent/index.js +2 -1
- package/core/dist/runtime-v2/store/intent/index.js.map +1 -1
- package/core/dist/runtime-v2/store/intent/sqlite-intent-doc-version-store.d.ts +28 -0
- package/core/dist/runtime-v2/store/intent/sqlite-intent-doc-version-store.d.ts.map +1 -0
- package/core/dist/runtime-v2/store/intent/sqlite-intent-doc-version-store.js +88 -0
- package/core/dist/runtime-v2/store/intent/sqlite-intent-doc-version-store.js.map +1 -0
- package/core/dist/runtime-v2/store/sqlite-connection.d.ts.map +1 -1
- package/core/dist/runtime-v2/store/sqlite-connection.js +14 -0
- package/core/dist/runtime-v2/store/sqlite-connection.js.map +1 -1
- package/core/dist/runtime-v2/thinking-models/__tests__/thinking-models-policy.test.d.ts +2 -0
- package/core/dist/runtime-v2/thinking-models/__tests__/thinking-models-policy.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/thinking-models/__tests__/thinking-models-policy.test.js +149 -0
- package/core/dist/runtime-v2/thinking-models/__tests__/thinking-models-policy.test.js.map +1 -0
- package/core/dist/runtime-v2/thinking-models/index.d.ts +3 -0
- package/core/dist/runtime-v2/thinking-models/index.d.ts.map +1 -0
- package/core/dist/runtime-v2/thinking-models/index.js +3 -0
- package/core/dist/runtime-v2/thinking-models/index.js.map +1 -0
- package/core/dist/runtime-v2/thinking-models/thinking-models-policy.d.ts +73 -0
- package/core/dist/runtime-v2/thinking-models/thinking-models-policy.d.ts.map +1 -0
- package/core/dist/runtime-v2/thinking-models/thinking-models-policy.js +227 -0
- package/core/dist/runtime-v2/thinking-models/thinking-models-policy.js.map +1 -0
- package/core/dist/runtime-v2/tools/__tests__/artificer-l2-tool-contract.test.js +40 -1
- package/core/dist/runtime-v2/tools/__tests__/artificer-l2-tool-contract.test.js.map +1 -1
- package/core/dist/runtime-v2/tools/artificer-l2-tool-contract.d.ts.map +1 -1
- package/core/dist/runtime-v2/tools/artificer-l2-tool-contract.js +28 -1
- package/core/dist/runtime-v2/tools/artificer-l2-tool-contract.js.map +1 -1
- package/core/dist/runtime-v2/tools/artificer-output-typebox.d.ts +3 -0
- package/core/dist/runtime-v2/tools/artificer-output-typebox.d.ts.map +1 -1
- package/core/dist/runtime-v2/tools/artificer-output-typebox.js +3 -0
- package/core/dist/runtime-v2/tools/artificer-output-typebox.js.map +1 -1
- package/core/package.json +4 -0
- package/package.json +1 -1
- package/pd-cli/dist/commands/__tests__/intent-flag-wiring.test.js +74 -3
- package/pd-cli/dist/commands/__tests__/intent-flag-wiring.test.js.map +1 -1
- package/pd-cli/dist/commands/intent.d.ts +21 -4
- package/pd-cli/dist/commands/intent.d.ts.map +1 -1
- package/pd-cli/dist/commands/intent.js +88 -27
- package/pd-cli/dist/commands/intent.js.map +1 -1
- package/plugin/dist/commands/pain.js +2 -2
- package/plugin/dist/core/behavior-example-pack-assembler.d.ts +43 -0
- package/plugin/dist/core/behavior-example-pack-assembler.js +247 -0
- package/plugin/dist/core/intent-doc-reader-adapter.d.ts +13 -5
- package/plugin/dist/core/intent-doc-reader-adapter.js +25 -5
- package/plugin/dist/core/intent-doc-reader.d.ts +13 -4
- package/plugin/dist/core/intent-doc-reader.js +45 -24
- package/plugin/dist/core/rule-context-assembler.d.ts +45 -0
- package/plugin/dist/core/rule-context-assembler.js +148 -0
- package/plugin/dist/core/thinking-models.d.ts +12 -57
- package/plugin/dist/core/thinking-models.js +18 -224
- package/plugin/dist/core/trajectory-types.d.ts +18 -0
- package/plugin/dist/core/trajectory.d.ts +34 -2
- package/plugin/dist/core/trajectory.js +103 -0
- package/plugin/dist/hooks/gate.js +59 -2
- package/plugin/dist/hooks/pain.js +2 -2
- package/plugin/dist/hooks/prompt.js +2 -1
- package/plugin/dist/index.js +1 -1
- package/plugin/package.json +1 -1
- package/plugin/dist/core/evolution-migration.d.ts +0 -5
- package/plugin/dist/core/evolution-migration.js +0 -65
- package/plugin/dist/core/risk-calculator.d.ts +0 -22
- package/plugin/dist/core/risk-calculator.js +0 -88
- package/plugin/dist/core/rule-host-helpers.d.ts +0 -8
- package/plugin/dist/core/rule-host-helpers.js +0 -7
- package/plugin/dist/core/rule-host-types.d.ts +0 -7
- package/plugin/dist/core/rule-host-types.js +0 -7
- package/plugin/dist/core/schema/db-types.d.ts +0 -11
- package/plugin/dist/core/schema/db-types.js +0 -5
- package/plugin/dist/core/schema/index.d.ts +0 -17
- package/plugin/dist/core/schema/index.js +0 -15
- package/plugin/dist/core/schema/migration-runner.d.ts +0 -53
- package/plugin/dist/core/schema/migration-runner.js +0 -170
- package/plugin/dist/core/schema/migrations/001-init-trajectory.d.ts +0 -6
- package/plugin/dist/core/schema/migrations/001-init-trajectory.js +0 -190
- package/plugin/dist/core/schema/migrations/002-init-central.d.ts +0 -5
- package/plugin/dist/core/schema/migrations/002-init-central.js +0 -108
- package/plugin/dist/core/schema/migrations/003-init-workflow.d.ts +0 -5
- package/plugin/dist/core/schema/migrations/003-init-workflow.js +0 -50
- package/plugin/dist/core/schema/migrations/004-add-thinking-and-gfi.d.ts +0 -8
- package/plugin/dist/core/schema/migrations/004-add-thinking-and-gfi.js +0 -66
- package/plugin/dist/core/schema/migrations/index.d.ts +0 -16
- package/plugin/dist/core/schema/migrations/index.js +0 -27
- package/plugin/dist/core/schema/schema-definitions.d.ts +0 -46
- package/plugin/dist/core/schema/schema-definitions.js +0 -599
- package/plugin/scripts/db-migrate.mjs +0 -170
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PRI-480 — Phase 1 Core ABI (rule-context-v2.ts)
|
|
3
|
+
*
|
|
4
|
+
* Pure logic: types + canonicalize + validators + behavior-facts computation.
|
|
5
|
+
* Zero I/O — this module MUST NOT import node:fs / node:path / better-sqlite3 /
|
|
6
|
+
* any network module. The runtime-v2 architecture-regression test enforces the
|
|
7
|
+
* file boundary.
|
|
8
|
+
*
|
|
9
|
+
* Err-prevention:
|
|
10
|
+
* - ERR-001 (validate-as-unknown): every public validator takes `unknown` and
|
|
11
|
+
* validates structurally. No `as` bypass on parsed input.
|
|
12
|
+
* - ERR-076 (prototype-pollution / host-realm independence): structural checks
|
|
13
|
+
* use Object.keys + a PROTO_KEYS set. We never touch the host realm's
|
|
14
|
+
* prototype chain (no `instanceof`, no `in`).
|
|
15
|
+
* - rc-2: no `as` casts on parsed input.
|
|
16
|
+
* - rc-5: Object.hasOwn / Object.keys over the `in` operator.
|
|
17
|
+
*
|
|
18
|
+
* Spec: docs/superpowers/specs/2026-06-27-rulecode-context-vision-design.md §4.
|
|
19
|
+
*/
|
|
20
|
+
// ── internal constants ─────────────────────────────────────────────────────
|
|
21
|
+
const CANONICAL_KINDS = new Set([
|
|
22
|
+
'read',
|
|
23
|
+
'search',
|
|
24
|
+
'write',
|
|
25
|
+
'execute',
|
|
26
|
+
'agent',
|
|
27
|
+
'other',
|
|
28
|
+
]);
|
|
29
|
+
const EVIDENCE_STATES = new Set(['yes', 'no', 'unknown']);
|
|
30
|
+
const TOOL_OUTCOMES = new Set(['success', 'failure', 'blocked']);
|
|
31
|
+
const HISTORY_STATUSES = new Set(['available', 'unavailable']);
|
|
32
|
+
const PROTO_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
|
|
33
|
+
const OK_RESULT = { valid: true, errors: [] };
|
|
34
|
+
function fail(errors) {
|
|
35
|
+
return errors.length === 0 ? OK_RESULT : { valid: false, errors };
|
|
36
|
+
}
|
|
37
|
+
function isPlainObjectLike(value) {
|
|
38
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
39
|
+
}
|
|
40
|
+
function hasNoProtoKeys(value) {
|
|
41
|
+
for (const key of Object.keys(value)) {
|
|
42
|
+
if (PROTO_KEYS.has(key))
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
function isFiniteNumber(value) {
|
|
48
|
+
return typeof value === 'number' && Number.isFinite(value);
|
|
49
|
+
}
|
|
50
|
+
function isNullOrNonNegativeFinite(value) {
|
|
51
|
+
return value === null || (typeof value === 'number' && Number.isFinite(value) && value >= 0);
|
|
52
|
+
}
|
|
53
|
+
// ── canonicalizeToolKind (static alias table, spec §4.4) ────────────────────
|
|
54
|
+
//
|
|
55
|
+
// NOTE: the authoritative source for canonical kinds SHOULD be a host declaration
|
|
56
|
+
// (spec §4.4 anti-drift note), so that `core` never owns a growing hardcoded
|
|
57
|
+
// tool list. The first version uses a static alias table (ticket-bounded); a
|
|
58
|
+
// later phase will let hosts declare `ruleCanonicalKind` overrides. core only
|
|
59
|
+
// owns the CLOSED CanonicalKind enum + this pure lookup function.
|
|
60
|
+
const TOOL_ALIAS = {
|
|
61
|
+
read: 'read',
|
|
62
|
+
read_file: 'read',
|
|
63
|
+
read_many_files: 'read',
|
|
64
|
+
grep: 'search',
|
|
65
|
+
grep_search: 'search',
|
|
66
|
+
search_file_content: 'search',
|
|
67
|
+
glob: 'search',
|
|
68
|
+
write: 'write',
|
|
69
|
+
write_file: 'write',
|
|
70
|
+
edit: 'write',
|
|
71
|
+
edit_file: 'write',
|
|
72
|
+
replace: 'write',
|
|
73
|
+
apply_patch: 'write',
|
|
74
|
+
bash: 'execute',
|
|
75
|
+
exec: 'execute',
|
|
76
|
+
execute: 'execute',
|
|
77
|
+
run_shell_command: 'execute',
|
|
78
|
+
sessions_spawn: 'agent',
|
|
79
|
+
};
|
|
80
|
+
export function canonicalizeToolKind(toolName) {
|
|
81
|
+
if (typeof toolName !== 'string')
|
|
82
|
+
return 'other';
|
|
83
|
+
// ERR-076: Object.hasOwn guards against inherited Object.prototype keys
|
|
84
|
+
// (__proto__, constructor, toString, hasOwnProperty, ...) that direct
|
|
85
|
+
// indexing would otherwise leak as non-CanonicalKind values (e.g. the
|
|
86
|
+
// Object.prototype object, the Object constructor function). Without this
|
|
87
|
+
// guard `TOOL_ALIAS['__proto__']` returns Object.prototype, not undefined.
|
|
88
|
+
if (!Object.hasOwn(TOOL_ALIAS, toolName))
|
|
89
|
+
return 'other';
|
|
90
|
+
const hit = TOOL_ALIAS[toolName];
|
|
91
|
+
return hit !== undefined ? hit : 'other';
|
|
92
|
+
}
|
|
93
|
+
// ── validators ─────────────────────────────────────────────────────────────
|
|
94
|
+
export function validateRuleToolCallRecord(value) {
|
|
95
|
+
if (!isPlainObjectLike(value)) {
|
|
96
|
+
return { valid: false, errors: ['record must be a plain object'] };
|
|
97
|
+
}
|
|
98
|
+
if (!hasNoProtoKeys(value)) {
|
|
99
|
+
return { valid: false, errors: ['record must not carry prototype-pollution keys'] };
|
|
100
|
+
}
|
|
101
|
+
const errors = [];
|
|
102
|
+
if (!isFiniteNumber(value.sequenceId)) {
|
|
103
|
+
errors.push('sequenceId must be a finite number');
|
|
104
|
+
}
|
|
105
|
+
const { toolName } = value;
|
|
106
|
+
if (typeof toolName !== 'string' || toolName.length === 0) {
|
|
107
|
+
errors.push('toolName must be a non-empty string');
|
|
108
|
+
}
|
|
109
|
+
const { canonicalKind } = value;
|
|
110
|
+
if (typeof canonicalKind !== 'string' || !CANONICAL_KINDS.has(canonicalKind)) {
|
|
111
|
+
errors.push('canonicalKind must be a valid CanonicalKind');
|
|
112
|
+
}
|
|
113
|
+
const { normalizedPath } = value;
|
|
114
|
+
if (normalizedPath !== null && typeof normalizedPath !== 'string') {
|
|
115
|
+
errors.push('normalizedPath must be a string or null');
|
|
116
|
+
}
|
|
117
|
+
if (!isPlainObjectLike(value.paramsSummary)) {
|
|
118
|
+
errors.push('paramsSummary must be a plain object');
|
|
119
|
+
}
|
|
120
|
+
const { outcome } = value;
|
|
121
|
+
if (typeof outcome !== 'string' || !TOOL_OUTCOMES.has(outcome)) {
|
|
122
|
+
errors.push('outcome must be success | failure | blocked');
|
|
123
|
+
}
|
|
124
|
+
return fail(errors);
|
|
125
|
+
}
|
|
126
|
+
export function validateRuleHistoryWindow(value) {
|
|
127
|
+
if (!isPlainObjectLike(value)) {
|
|
128
|
+
return { valid: false, errors: ['history window must be a plain object'] };
|
|
129
|
+
}
|
|
130
|
+
if (!hasNoProtoKeys(value)) {
|
|
131
|
+
return { valid: false, errors: ['history window must not carry prototype-pollution keys'] };
|
|
132
|
+
}
|
|
133
|
+
const errors = [];
|
|
134
|
+
const { status } = value;
|
|
135
|
+
if (typeof status !== 'string' || !HISTORY_STATUSES.has(status)) {
|
|
136
|
+
errors.push('status must be available | unavailable');
|
|
137
|
+
}
|
|
138
|
+
const { unavailableReason } = value;
|
|
139
|
+
if (unavailableReason !== undefined && typeof unavailableReason !== 'string') {
|
|
140
|
+
errors.push('unavailableReason must be a string or undefined');
|
|
141
|
+
}
|
|
142
|
+
if (typeof value.truncated !== 'boolean') {
|
|
143
|
+
errors.push('truncated must be a boolean');
|
|
144
|
+
}
|
|
145
|
+
const { calls } = value;
|
|
146
|
+
if (!Array.isArray(calls)) {
|
|
147
|
+
errors.push('calls must be an array');
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
for (let i = 0; i < calls.length; i++) {
|
|
151
|
+
const recordResult = validateRuleToolCallRecord(calls[i]);
|
|
152
|
+
if (!recordResult.valid) {
|
|
153
|
+
errors.push(`calls[${i}] invalid: ${recordResult.errors.join('; ')}`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return fail(errors);
|
|
158
|
+
}
|
|
159
|
+
export function validateRuleBehaviorFacts(value) {
|
|
160
|
+
if (!isPlainObjectLike(value)) {
|
|
161
|
+
return { valid: false, errors: ['facts must be a plain object'] };
|
|
162
|
+
}
|
|
163
|
+
if (!hasNoProtoKeys(value)) {
|
|
164
|
+
return { valid: false, errors: ['facts must not carry prototype-pollution keys'] };
|
|
165
|
+
}
|
|
166
|
+
const errors = [];
|
|
167
|
+
const { priorReadOfTarget } = value;
|
|
168
|
+
if (typeof priorReadOfTarget !== 'string' || !EVIDENCE_STATES.has(priorReadOfTarget)) {
|
|
169
|
+
errors.push('priorReadOfTarget must be yes | no | unknown');
|
|
170
|
+
}
|
|
171
|
+
if (!isNullOrNonNegativeFinite(value.readCount)) {
|
|
172
|
+
errors.push('readCount must be a non-negative finite number or null');
|
|
173
|
+
}
|
|
174
|
+
if (!isNullOrNonNegativeFinite(value.writeCount)) {
|
|
175
|
+
errors.push('writeCount must be a non-negative finite number or null');
|
|
176
|
+
}
|
|
177
|
+
if (!isNullOrNonNegativeFinite(value.uniqueWritePathCount)) {
|
|
178
|
+
errors.push('uniqueWritePathCount must be a non-negative finite number or null');
|
|
179
|
+
}
|
|
180
|
+
if (!isNullOrNonNegativeFinite(value.sameActionBlockCount)) {
|
|
181
|
+
errors.push('sameActionBlockCount must be a non-negative finite number or null');
|
|
182
|
+
}
|
|
183
|
+
return fail(errors);
|
|
184
|
+
}
|
|
185
|
+
export function validateRuleContextV2(value) {
|
|
186
|
+
if (!isPlainObjectLike(value)) {
|
|
187
|
+
return { valid: false, errors: ['context must be a plain object'] };
|
|
188
|
+
}
|
|
189
|
+
if (!hasNoProtoKeys(value)) {
|
|
190
|
+
return { valid: false, errors: ['context must not carry prototype-pollution keys'] };
|
|
191
|
+
}
|
|
192
|
+
const errors = [];
|
|
193
|
+
if (value.version !== 2) {
|
|
194
|
+
errors.push('version must be 2');
|
|
195
|
+
}
|
|
196
|
+
const historyResult = validateRuleHistoryWindow(value.history);
|
|
197
|
+
if (!historyResult.valid) {
|
|
198
|
+
errors.push(`history invalid: ${historyResult.errors.join('; ')}`);
|
|
199
|
+
}
|
|
200
|
+
const factsResult = validateRuleBehaviorFacts(value.facts);
|
|
201
|
+
if (!factsResult.valid) {
|
|
202
|
+
errors.push(`facts invalid: ${factsResult.errors.join('; ')}`);
|
|
203
|
+
}
|
|
204
|
+
// Unavailable invariant (acceptance C): when history.status === 'unavailable',
|
|
205
|
+
// facts MUST be the canonical unavailable posture — priorReadOfTarget='unknown'
|
|
206
|
+
// and every count null. Any drift is rejected so downstream gates can't be
|
|
207
|
+
// fooled by a host that fabricates numbers while claiming history is missing.
|
|
208
|
+
const { history } = value;
|
|
209
|
+
const { facts } = value;
|
|
210
|
+
if (historyResult.valid &&
|
|
211
|
+
factsResult.valid &&
|
|
212
|
+
isPlainObjectLike(history) &&
|
|
213
|
+
isPlainObjectLike(facts) &&
|
|
214
|
+
history.status === 'unavailable') {
|
|
215
|
+
if (facts.priorReadOfTarget !== 'unknown') {
|
|
216
|
+
errors.push('unavailable invariant: priorReadOfTarget must be "unknown" when history is unavailable');
|
|
217
|
+
}
|
|
218
|
+
if (facts.readCount !== null) {
|
|
219
|
+
errors.push('unavailable invariant: readCount must be null when history is unavailable');
|
|
220
|
+
}
|
|
221
|
+
if (facts.writeCount !== null) {
|
|
222
|
+
errors.push('unavailable invariant: writeCount must be null when history is unavailable');
|
|
223
|
+
}
|
|
224
|
+
if (facts.uniqueWritePathCount !== null) {
|
|
225
|
+
errors.push('unavailable invariant: uniqueWritePathCount must be null when history is unavailable');
|
|
226
|
+
}
|
|
227
|
+
if (facts.sameActionBlockCount !== null) {
|
|
228
|
+
errors.push('unavailable invariant: sameActionBlockCount must be null when history is unavailable');
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return fail(errors);
|
|
232
|
+
}
|
|
233
|
+
// ── computeBehaviorFacts (pure) ────────────────────────────────────────────
|
|
234
|
+
export function computeBehaviorFacts(window, targetPath, sameActionBlockCount) {
|
|
235
|
+
if (window.status === 'unavailable') {
|
|
236
|
+
return {
|
|
237
|
+
priorReadOfTarget: 'unknown',
|
|
238
|
+
readCount: null,
|
|
239
|
+
writeCount: null,
|
|
240
|
+
uniqueWritePathCount: null,
|
|
241
|
+
sameActionBlockCount: null,
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
let readCount = 0;
|
|
245
|
+
let writeCount = 0;
|
|
246
|
+
const writePaths = new Set();
|
|
247
|
+
let priorReadOfTarget = targetPath === null ? 'unknown' : 'no';
|
|
248
|
+
const { calls } = window;
|
|
249
|
+
for (const call of calls) {
|
|
250
|
+
const kind = call.canonicalKind;
|
|
251
|
+
if (kind === 'read' || kind === 'search') {
|
|
252
|
+
readCount++;
|
|
253
|
+
if (targetPath !== null && call.normalizedPath === targetPath) {
|
|
254
|
+
priorReadOfTarget = 'yes';
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
else if (kind === 'write') {
|
|
258
|
+
writeCount++;
|
|
259
|
+
if (typeof call.normalizedPath === 'string') {
|
|
260
|
+
writePaths.add(call.normalizedPath);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
return {
|
|
265
|
+
priorReadOfTarget,
|
|
266
|
+
readCount,
|
|
267
|
+
writeCount,
|
|
268
|
+
uniqueWritePathCount: writePaths.size,
|
|
269
|
+
sameActionBlockCount,
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
// ── UNAVAILABLE_RULE_CONTEXT sentinel (deep-frozen) ────────────────────────
|
|
273
|
+
//
|
|
274
|
+
// The canonical "host gave us no history" context. Downstream code compares
|
|
275
|
+
// against this (or checks history.status) instead of null-checking, so the
|
|
276
|
+
// unavailable posture is always well-typed. Deep-frozen so a buggy host cannot
|
|
277
|
+
// mutate the shared sentinel and poison every subsequent rule evaluation.
|
|
278
|
+
const _UNAVAILABLE_FACTS = {
|
|
279
|
+
priorReadOfTarget: 'unknown',
|
|
280
|
+
readCount: null,
|
|
281
|
+
writeCount: null,
|
|
282
|
+
uniqueWritePathCount: null,
|
|
283
|
+
sameActionBlockCount: null,
|
|
284
|
+
};
|
|
285
|
+
Object.freeze(_UNAVAILABLE_FACTS);
|
|
286
|
+
const _UNAVAILABLE_HISTORY = {
|
|
287
|
+
status: 'unavailable',
|
|
288
|
+
unavailableReason: 'host did not provide a history window',
|
|
289
|
+
truncated: false,
|
|
290
|
+
calls: [],
|
|
291
|
+
};
|
|
292
|
+
Object.freeze(_UNAVAILABLE_HISTORY.calls);
|
|
293
|
+
Object.freeze(_UNAVAILABLE_HISTORY);
|
|
294
|
+
const _UNAVAILABLE_VALUE = {
|
|
295
|
+
version: 2,
|
|
296
|
+
history: _UNAVAILABLE_HISTORY,
|
|
297
|
+
facts: _UNAVAILABLE_FACTS,
|
|
298
|
+
};
|
|
299
|
+
Object.freeze(_UNAVAILABLE_VALUE);
|
|
300
|
+
export const UNAVAILABLE_RULE_CONTEXT = _UNAVAILABLE_VALUE;
|
|
301
|
+
//# sourceMappingURL=rule-context-v2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule-context-v2.js","sourceRoot":"","sources":["../../../src/runtime-v2/internalization/rule-context-v2.ts"],"names":[],"mappings":"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"}
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
* - No filesystem, process, require, dynamic import, eval, or network access
|
|
12
12
|
*/
|
|
13
13
|
import type { CorrectionProposal } from './correction-proposal.js';
|
|
14
|
+
import type { RuleContextV2 } from './rule-context-v2.js';
|
|
14
15
|
export interface RuleHostInput {
|
|
15
16
|
action: {
|
|
16
17
|
toolName: string;
|
|
@@ -34,6 +35,14 @@ export interface RuleHostInput {
|
|
|
34
35
|
estimatedLineChanges: number;
|
|
35
36
|
bashRisk: 'safe' | 'normal' | 'dangerous' | 'unknown';
|
|
36
37
|
};
|
|
38
|
+
/**
|
|
39
|
+
* PRI-480 (RuleContext v2 — Phase 1): optional structured context describing
|
|
40
|
+
* the recent tool-call history and derived behavior facts. Optional on purpose
|
|
41
|
+
* — v1 rule implementations that never read this field see `undefined` and
|
|
42
|
+
* behave exactly as before. Hosts opt in by populating the field; downstream
|
|
43
|
+
* phases will gate new rule behavior on `context?.history.status === 'available'`.
|
|
44
|
+
*/
|
|
45
|
+
context?: RuleContextV2;
|
|
37
46
|
}
|
|
38
47
|
export type RuleHostDecision = 'allow' | 'block' | 'requireApproval' | 'auto_correct';
|
|
39
48
|
export interface RuleHostMeta {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rule-host-contracts.d.ts","sourceRoot":"","sources":["../../../src/runtime-v2/internalization/rule-host-contracts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"rule-host-contracts.d.ts","sourceRoot":"","sources":["../../../src/runtime-v2/internalization/rule-host-contracts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAM1D,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE;QACN,QAAQ,EAAE,MAAM,CAAC;QACjB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;QAC9B,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACxC,CAAC;IACF,SAAS,EAAE;QACT,UAAU,EAAE,OAAO,CAAC;QACpB,UAAU,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS,CAAC;QACnD,WAAW,EAAE,OAAO,CAAC;KACtB,CAAC;IACF,OAAO,EAAE;QACP,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;QACnB,cAAc,EAAE,OAAO,CAAC;KACzB,CAAC;IACF,SAAS,EAAE;QACT,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,OAAO,EAAE;QACP,oBAAoB,EAAE,MAAM,CAAC;QAC7B,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAAG,WAAW,GAAG,SAAS,CAAC;KACvD,CAAC;IACF;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAMD,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,OAAO,GAAG,iBAAiB,GAAG,cAAc,CAAC;AAMtF,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;CACzB;AAMD,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uFAAuF;IACvF,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;CACzC;AAMD,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,YAAY,CAAC;IACnB,QAAQ,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,cAAc,CAAC;CACrD"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PRI-485 Phase 6 — v2 adversarial case generator (pure logic).
|
|
3
|
+
*
|
|
4
|
+
* Auto-generates 5 deterministic adversarial cases that defend against the
|
|
5
|
+
* most common false-positive patterns when a RuleCode consumes a v2
|
|
6
|
+
* RuleContext. Each case carries a fabricated `ruleContext` that exercises
|
|
7
|
+
* one spec-defined edge (spec §7.4, §10.1):
|
|
8
|
+
*
|
|
9
|
+
* 1. v2-unavailable — host provided no history; rule must allow.
|
|
10
|
+
* 2. v2-truncated — history was truncated; rule must define a
|
|
11
|
+
* conservative (fail-open) strategy.
|
|
12
|
+
* 3. v2-alias — write_file after read_file on the same path must
|
|
13
|
+
* be allowed (canonicalKind match, not toolName).
|
|
14
|
+
* 4. v2-path-boundary — targetPath.bak must NOT be treated as a prior
|
|
15
|
+
* read of targetPath (no substring matching).
|
|
16
|
+
* 5. v2-combination — v2 priorRead=yes must NOT override a v1
|
|
17
|
+
* action-only risk-path block.
|
|
18
|
+
*
|
|
19
|
+
* Pure logic: zero I/O. The generated cases flow through the existing
|
|
20
|
+
* adversarialCasesToGoldenTrace → evaluateRefinerRuleHostGate path.
|
|
21
|
+
*
|
|
22
|
+
* Err-prevention:
|
|
23
|
+
* - ERR-069: generated cases share the AdversarialCase schema; the caller
|
|
24
|
+
* (Evaluator runner) validates them via DefaultEvaluatorValidator.
|
|
25
|
+
* - ERR-001 / rc-1 / rc-2: every ruleContext is a real RuleContextV2 value
|
|
26
|
+
* (UNAVAILABLE_RULE_CONTEXT sentinel or a freshly-built object that
|
|
27
|
+
* satisfies validateRuleContextV2). No `as` casts.
|
|
28
|
+
* - rc-9: every case carries a non-empty rationale explaining the edge.
|
|
29
|
+
*
|
|
30
|
+
* Spec: docs/superpowers/specs/2026-06-27-rulecode-context-vision-design.md
|
|
31
|
+
* §7.4 Evaluator responsibilities, §10.1 acceptance scenarios.
|
|
32
|
+
*/
|
|
33
|
+
import type { CanonicalKind } from './rule-context-v2.js';
|
|
34
|
+
import type { AdversarialCase } from './evaluator-output.js';
|
|
35
|
+
/**
|
|
36
|
+
* Inputs the generator needs to fabricate path-realistic cases.
|
|
37
|
+
* - `toolName` is the action tool the rule governs (e.g. 'write_file').
|
|
38
|
+
* - `targetPath` is the workspace path used in positive cases.
|
|
39
|
+
* - `canonicalKind` is the canonical kind of `toolName` (caller pre-computes
|
|
40
|
+
* via canonicalizeToolKind so this module stays pure and doesn't re-import
|
|
41
|
+
* the alias table).
|
|
42
|
+
*/
|
|
43
|
+
export interface V2AdversarialCaseSpec {
|
|
44
|
+
readonly toolName: string;
|
|
45
|
+
readonly targetPath: string;
|
|
46
|
+
readonly canonicalKind: CanonicalKind;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Generate the 5 canonical v2 adversarial cases for the given spec.
|
|
50
|
+
*
|
|
51
|
+
* The output is deterministic and stable in caseId order:
|
|
52
|
+
* v2-unavailable, v2-truncated, v2-alias, v2-path-boundary, v2-combination.
|
|
53
|
+
*/
|
|
54
|
+
export declare function generateV2ContextAdversarialCases(spec: V2AdversarialCaseSpec): readonly AdversarialCase[];
|
|
55
|
+
//# sourceMappingURL=v2-adversarial-cases.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"v2-adversarial-cases.d.ts","sourceRoot":"","sources":["../../../src/runtime-v2/internalization/v2-adversarial-cases.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAQ1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D;;;;;;;GAOG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;CACvC;AA6DD;;;;;GAKG;AACH,wBAAgB,iCAAiC,CAAC,IAAI,EAAE,qBAAqB,GAAG,SAAS,eAAe,EAAE,CAmGzG"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { UNAVAILABLE_RULE_CONTEXT, } from './rule-context-v2.js';
|
|
2
|
+
const RISK_PATH = '/etc/passwd';
|
|
3
|
+
function makeCall(spec) {
|
|
4
|
+
return {
|
|
5
|
+
sequenceId: spec.sequenceId,
|
|
6
|
+
toolName: spec.toolName,
|
|
7
|
+
canonicalKind: spec.canonicalKind,
|
|
8
|
+
normalizedPath: spec.normalizedPath,
|
|
9
|
+
paramsSummary: spec.normalizedPath !== null ? { path: spec.normalizedPath } : {},
|
|
10
|
+
outcome: 'success',
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
function makeHistory(spec) {
|
|
14
|
+
return {
|
|
15
|
+
status: spec.status,
|
|
16
|
+
truncated: spec.truncated,
|
|
17
|
+
calls: spec.calls,
|
|
18
|
+
...(spec.unavailableReason !== undefined ? { unavailableReason: spec.unavailableReason } : {}),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
function makeFacts(spec) {
|
|
22
|
+
// sameActionBlockCount is informational only; null is the canonical
|
|
23
|
+
// "host did not provide" value per the unavailable invariant.
|
|
24
|
+
return {
|
|
25
|
+
priorReadOfTarget: spec.priorReadOfTarget,
|
|
26
|
+
readCount: spec.readCount,
|
|
27
|
+
writeCount: spec.writeCount,
|
|
28
|
+
uniqueWritePathCount: spec.uniqueWritePathCount,
|
|
29
|
+
sameActionBlockCount: null,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function makeContext(history, facts) {
|
|
33
|
+
return { version: 2, history, facts };
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Generate the 5 canonical v2 adversarial cases for the given spec.
|
|
37
|
+
*
|
|
38
|
+
* The output is deterministic and stable in caseId order:
|
|
39
|
+
* v2-unavailable, v2-truncated, v2-alias, v2-path-boundary, v2-combination.
|
|
40
|
+
*/
|
|
41
|
+
export function generateV2ContextAdversarialCases(spec) {
|
|
42
|
+
// ── case 1: unavailable ──────────────────────────────────────────────
|
|
43
|
+
// The host provided no history window. The rule MUST allow — it cannot
|
|
44
|
+
// infer "no prior read" from missing context (spec §7.4, §10.1 row 6).
|
|
45
|
+
const unavailable = {
|
|
46
|
+
caseId: 'v2-unavailable',
|
|
47
|
+
attackType: 'boundary',
|
|
48
|
+
toolName: spec.toolName,
|
|
49
|
+
params: { path: spec.targetPath },
|
|
50
|
+
expectedDecision: 'allow',
|
|
51
|
+
rationale: 'history unavailable — rule must allow because absent context cannot be treated as evidence of no-read (spec §7.4)',
|
|
52
|
+
ruleContext: UNAVAILABLE_RULE_CONTEXT,
|
|
53
|
+
};
|
|
54
|
+
// ── case 2: truncated ────────────────────────────────────────────────
|
|
55
|
+
// History is available but was truncated. The rule MUST define a
|
|
56
|
+
// conservative strategy: when no calls survived truncation, it fails
|
|
57
|
+
// open (allow) rather than fabricate a "no-read" verdict (spec §10.1
|
|
58
|
+
// row 7). facts are all null/unknown because computeBehaviorFacts would
|
|
59
|
+
// produce them from an empty calls array — but we set them explicitly
|
|
60
|
+
// to the conservative posture so the rule sees the same shape.
|
|
61
|
+
const truncatedHistory = makeHistory({ status: 'available', truncated: true, calls: [] });
|
|
62
|
+
const truncatedFacts = makeFacts({ priorReadOfTarget: 'unknown', readCount: null, writeCount: null, uniqueWritePathCount: null });
|
|
63
|
+
const truncated = {
|
|
64
|
+
caseId: 'v2-truncated',
|
|
65
|
+
attackType: 'omission',
|
|
66
|
+
toolName: spec.toolName,
|
|
67
|
+
params: { path: spec.targetPath },
|
|
68
|
+
expectedDecision: 'allow',
|
|
69
|
+
rationale: 'history truncated — rule must define a conservative (fail-open) strategy when no calls survived (spec §10.1 row 7)',
|
|
70
|
+
ruleContext: makeContext(truncatedHistory, truncatedFacts),
|
|
71
|
+
};
|
|
72
|
+
// ── case 3: alias ────────────────────────────────────────────────────
|
|
73
|
+
// The host recorded a prior read_file on targetPath. The action is now
|
|
74
|
+
// write_file (alias of write). The rule MUST use canonicalKind for
|
|
75
|
+
// behavior matching: read_file → read, write_file → write, so
|
|
76
|
+
// write-after-read is allowed (spec §4.4, §10.1 row 8).
|
|
77
|
+
const aliasCalls = [makeCall({ sequenceId: 1, toolName: 'read_file', canonicalKind: 'read', normalizedPath: spec.targetPath })];
|
|
78
|
+
const aliasHistory = makeHistory({ status: 'available', truncated: false, calls: aliasCalls });
|
|
79
|
+
// facts mirror what computeBehaviorFacts would produce — priorRead=yes,
|
|
80
|
+
// 1 read, 0 writes. We set them explicitly so the rule sees a valid
|
|
81
|
+
// context even if it doesn't recompute from history.
|
|
82
|
+
const aliasFacts = makeFacts({ priorReadOfTarget: 'yes', readCount: 1, writeCount: 0, uniqueWritePathCount: 0 });
|
|
83
|
+
const alias = {
|
|
84
|
+
caseId: 'v2-alias',
|
|
85
|
+
attackType: 'boundary',
|
|
86
|
+
toolName: spec.toolName,
|
|
87
|
+
params: { path: spec.targetPath },
|
|
88
|
+
expectedDecision: 'allow',
|
|
89
|
+
rationale: 'write_file after read_file on same path — rule must match by canonicalKind (read→write), not by toolName equality (spec §4.4)',
|
|
90
|
+
ruleContext: makeContext(aliasHistory, aliasFacts),
|
|
91
|
+
};
|
|
92
|
+
// ── case 4: path-boundary ────────────────────────────────────────────
|
|
93
|
+
// The host recorded a prior read on targetPath, but the action targets
|
|
94
|
+
// targetPath + '.bak'. The rule MUST NOT substring-match — these are
|
|
95
|
+
// different files (spec §10.1 row 9). priorReadOfTarget is 'no' because
|
|
96
|
+
// the action's path is targetPath.bak, not targetPath.
|
|
97
|
+
const boundaryCalls = [makeCall({ sequenceId: 1, toolName: 'read_file', canonicalKind: 'read', normalizedPath: spec.targetPath })];
|
|
98
|
+
const boundaryHistory = makeHistory({ status: 'available', truncated: false, calls: boundaryCalls });
|
|
99
|
+
// computeBehaviorFacts would compute priorReadOfTarget='no' here because
|
|
100
|
+
// the action's normalizedPath (targetPath.bak) ≠ targetPath. We set it
|
|
101
|
+
// explicitly to mirror that computation.
|
|
102
|
+
const boundaryFacts = makeFacts({ priorReadOfTarget: 'no', readCount: 1, writeCount: 0, uniqueWritePathCount: 0 });
|
|
103
|
+
const pathBoundary = {
|
|
104
|
+
caseId: 'v2-path-boundary',
|
|
105
|
+
attackType: 'boundary',
|
|
106
|
+
toolName: spec.toolName,
|
|
107
|
+
params: { path: `${spec.targetPath}.bak` },
|
|
108
|
+
expectedDecision: 'block',
|
|
109
|
+
rationale: 'targetPath.bak is a different file from targetPath — rule must not substring-match paths (spec §10.1 row 9)',
|
|
110
|
+
ruleContext: makeContext(boundaryHistory, boundaryFacts),
|
|
111
|
+
};
|
|
112
|
+
// ── case 5: combination ──────────────────────────────────────────────
|
|
113
|
+
// The v2 context fabricates priorRead=yes on a known risk path
|
|
114
|
+
// (/etc/passwd). The rule MUST still block because the v1 action-only
|
|
115
|
+
// risk-path check dominates — v2 context augments but does not override
|
|
116
|
+
// action-level safety (spec §7.4, §10.1 row 10).
|
|
117
|
+
const combinationCalls = [makeCall({ sequenceId: 1, toolName: 'read_file', canonicalKind: 'read', normalizedPath: RISK_PATH })];
|
|
118
|
+
const combinationHistory = makeHistory({ status: 'available', truncated: false, calls: combinationCalls });
|
|
119
|
+
const combinationFacts = makeFacts({ priorReadOfTarget: 'yes', readCount: 1, writeCount: 0, uniqueWritePathCount: 0 });
|
|
120
|
+
const combination = {
|
|
121
|
+
caseId: 'v2-combination',
|
|
122
|
+
attackType: 'inversion',
|
|
123
|
+
toolName: spec.toolName,
|
|
124
|
+
params: { path: RISK_PATH },
|
|
125
|
+
expectedDecision: 'block',
|
|
126
|
+
rationale: 'v2 context says priorRead=yes on a risk path, but v1 action-only risk-path check must still dominate (block over allow, spec §7.4)',
|
|
127
|
+
ruleContext: makeContext(combinationHistory, combinationFacts),
|
|
128
|
+
};
|
|
129
|
+
return [unavailable, truncated, alias, pathBoundary, combination];
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=v2-adversarial-cases.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"v2-adversarial-cases.js","sourceRoot":"","sources":["../../../src/runtime-v2/internalization/v2-adversarial-cases.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pain-signal-observability.d.ts","sourceRoot":"","sources":["../../src/runtime-v2/pain-signal-observability.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAGhE,MAAM,WAAW,6BAA6B;IAC5C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,oCAAoC;IACnD,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,gBAAgB,CAAC;IACvB,oFAAoF;IACpF,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,6EAA6E;IAC7E,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;
|
|
1
|
+
{"version":3,"file":"pain-signal-observability.d.ts","sourceRoot":"","sources":["../../src/runtime-v2/pain-signal-observability.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAGhE,MAAM,WAAW,6BAA6B;IAC5C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,oCAAoC;IACnD,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,gBAAgB,CAAC;IACvB,oFAAoF;IACpF,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,6EAA6E;IAC7E,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAmZD;;;;GAIG;AACH,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,oCAAoC,GACzC,6BAA6B,CAiE/B"}
|
|
@@ -41,6 +41,13 @@ function getSessionsColumns(db) {
|
|
|
41
41
|
const cols = db.prepare('PRAGMA table_info(sessions)').all();
|
|
42
42
|
return cols.map((c) => c.name);
|
|
43
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* Type guard: narrows `object` to `{ name: unknown }` without `as` casts.
|
|
46
|
+
* Used for PRAGMA table_info rows (rc-2-no-as-bypass).
|
|
47
|
+
*/
|
|
48
|
+
function hasNameField(row) {
|
|
49
|
+
return Object.hasOwn(row, 'name');
|
|
50
|
+
}
|
|
44
51
|
/**
|
|
45
52
|
* Ensure trajectory.db has the full schema (all 16 tables + indexes + migrations).
|
|
46
53
|
*
|
|
@@ -87,6 +94,8 @@ function ensureTrajectorySchema(db) {
|
|
|
87
94
|
empathy_signal_json TEXT NOT NULL,
|
|
88
95
|
blob_ref TEXT,
|
|
89
96
|
raw_excerpt TEXT,
|
|
97
|
+
stop_reason TEXT,
|
|
98
|
+
thinking_blocks_count INTEGER,
|
|
90
99
|
created_at TEXT NOT NULL
|
|
91
100
|
);
|
|
92
101
|
CREATE TABLE IF NOT EXISTS user_turns (
|
|
@@ -113,6 +122,7 @@ function ensureTrajectorySchema(db) {
|
|
|
113
122
|
gfi_before REAL,
|
|
114
123
|
gfi_after REAL,
|
|
115
124
|
params_json TEXT NOT NULL,
|
|
125
|
+
result_preview TEXT,
|
|
116
126
|
created_at TEXT NOT NULL
|
|
117
127
|
);
|
|
118
128
|
CREATE TABLE IF NOT EXISTS pain_events (
|
|
@@ -125,6 +135,8 @@ function ensureTrajectorySchema(db) {
|
|
|
125
135
|
origin TEXT,
|
|
126
136
|
confidence REAL,
|
|
127
137
|
text TEXT,
|
|
138
|
+
canonical_pain_id TEXT,
|
|
139
|
+
runtime_task_id TEXT,
|
|
128
140
|
created_at TEXT NOT NULL
|
|
129
141
|
);
|
|
130
142
|
CREATE TABLE IF NOT EXISTS gate_blocks (
|
|
@@ -203,6 +215,12 @@ function ensureTrajectorySchema(db) {
|
|
|
203
215
|
started_at TEXT,
|
|
204
216
|
completed_at TEXT,
|
|
205
217
|
resolution TEXT,
|
|
218
|
+
task_kind TEXT,
|
|
219
|
+
priority TEXT,
|
|
220
|
+
retry_count INTEGER,
|
|
221
|
+
max_retries INTEGER,
|
|
222
|
+
last_error TEXT,
|
|
223
|
+
result_ref TEXT,
|
|
206
224
|
created_at TEXT NOT NULL,
|
|
207
225
|
updated_at TEXT NOT NULL
|
|
208
226
|
);
|
|
@@ -279,7 +297,12 @@ function ensureTrajectorySchema(db) {
|
|
|
279
297
|
];
|
|
280
298
|
for (const col of v2Columns) {
|
|
281
299
|
const exists = db.prepare(`PRAGMA table_info(evolution_tasks)`).all()
|
|
282
|
-
.some((row) =>
|
|
300
|
+
.some((row) => {
|
|
301
|
+
if (typeof row !== 'object' || row === null)
|
|
302
|
+
return false;
|
|
303
|
+
// Use type guard predicate to narrow without `as` (rc-2-no-as-bypass)
|
|
304
|
+
return hasNameField(row) && row.name === col.name;
|
|
305
|
+
});
|
|
283
306
|
if (!exists) {
|
|
284
307
|
db.exec(`ALTER TABLE evolution_tasks ADD COLUMN ${col.name} ${col.type}`);
|
|
285
308
|
}
|