@principles/host-runtime 0.1.0 → 0.1.1
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/dist/active-principle-prompt.js +5 -1
- package/dist/governance-observation-store.d.ts +172 -0
- package/dist/governance-observation-store.js +649 -0
- package/dist/host-liveness-contract.d.ts +3 -0
- package/dist/host-liveness-contract.js +18 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +9 -0
- package/dist/legacy-rule-contract-symbols.d.ts +20 -0
- package/dist/legacy-rule-contract-symbols.js +124 -0
- package/dist/product-telemetry/consent-store.d.ts +107 -0
- package/dist/product-telemetry/consent-store.js +329 -0
- package/dist/product-telemetry/eligibility.d.ts +53 -0
- package/dist/product-telemetry/eligibility.js +69 -0
- package/dist/product-telemetry/exporter.d.ts +46 -0
- package/dist/product-telemetry/exporter.js +71 -0
- package/dist/product-telemetry/milestone-readers.d.ts +61 -0
- package/dist/product-telemetry/milestone-readers.js +234 -0
- package/dist/product-telemetry/service.d.ts +142 -0
- package/dist/product-telemetry/service.js +532 -0
- package/dist/product-telemetry/workspace-scope.d.ts +38 -0
- package/dist/product-telemetry/workspace-scope.js +64 -0
- package/dist/production-pain-evidence.js +9 -2
- package/dist/production-rulehost-gate.d.ts +0 -1
- package/dist/production-rulehost-gate.js +47 -6
- package/dist/rule-implementation-runtime.js +0 -2
- package/package.json +7 -2
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { buildRuleHostAction, estimateLineChanges, mergeDecisions, SqliteConnection, UNAVAILABLE_RULE_CONTEXT, validateRuleContextV2, validateRuleHostResult, } from '@principles/core/runtime-v2';
|
|
4
|
+
import { scanRetiredContractSymbols } from './legacy-rule-contract-symbols.js';
|
|
4
5
|
import { createNodeRuleImplementationRuntime, MAX_ACTIVE_RULES, RULE_BATCH_SOURCE_BYTES, RULE_SOURCE_BYTES, } from './rule-implementation-runtime.js';
|
|
5
6
|
const WARNING_LIMIT = 500;
|
|
6
7
|
const MAX_WARNINGS = 16;
|
|
@@ -76,7 +77,7 @@ export function createProductionRuleHostGate(options = {}) {
|
|
|
76
77
|
if (action.normalizedPath === null)
|
|
77
78
|
return { decision: 'allow', source: event.source, metadata: { evaluatedLiveRules: 0 } };
|
|
78
79
|
let context;
|
|
79
|
-
let enrichment = { currentGfi: 0,
|
|
80
|
+
let enrichment = { currentGfi: 0, epTier: 0, bashRisk: 'unknown' };
|
|
80
81
|
const request = {
|
|
81
82
|
workspaceDir: event.context.workspaceDir, sessionId: event.context.sessionId,
|
|
82
83
|
targetPath: action.normalizedPath, toolName: input.toolName, rawPayload: event.rawPayload,
|
|
@@ -85,9 +86,9 @@ export function createProductionRuleHostGate(options = {}) {
|
|
|
85
86
|
try {
|
|
86
87
|
const candidate = await withinGateDeadline(options.ruleInputEnrichmentProvider(request), startedAt);
|
|
87
88
|
if (isRecord(candidate) && typeof candidate.currentGfi === 'number' && Number.isFinite(candidate.currentGfi)
|
|
88
|
-
&& typeof candidate.
|
|
89
|
+
&& typeof candidate.epTier === 'number' && Number.isFinite(candidate.epTier)
|
|
89
90
|
&& (candidate.bashRisk === 'safe' || candidate.bashRisk === 'normal' || candidate.bashRisk === 'dangerous' || candidate.bashRisk === 'unknown')) {
|
|
90
|
-
enrichment = { currentGfi: candidate.currentGfi,
|
|
91
|
+
enrichment = { currentGfi: candidate.currentGfi, epTier: candidate.epTier, bashRisk: candidate.bashRisk };
|
|
91
92
|
}
|
|
92
93
|
else
|
|
93
94
|
addWarning(warnings, 'rule_input_enrichment_invalid', 'repair the host enrichment provider');
|
|
@@ -127,11 +128,25 @@ export function createProductionRuleHostGate(options = {}) {
|
|
|
127
128
|
const connection = new SqliteConnection({ workspaceDir: event.context.workspaceDir, readonly: true, bootstrapIfMissing: false });
|
|
128
129
|
const candidates = [];
|
|
129
130
|
try {
|
|
131
|
+
const globalPause = connection.getDb().prepare(`
|
|
132
|
+
SELECT pause_id FROM global_rulecode_pauses WHERE status = 'paused' LIMIT 1
|
|
133
|
+
`).get();
|
|
134
|
+
if (globalPause !== undefined) {
|
|
135
|
+
return {
|
|
136
|
+
decision: 'allow',
|
|
137
|
+
source: event.source,
|
|
138
|
+
warnings: [boundedWarning('global_rulecode_pause_active', 'review the incident in the Owner Console before releasing the global pause')],
|
|
139
|
+
metadata: { evaluatedLiveRules: 0 },
|
|
140
|
+
};
|
|
141
|
+
}
|
|
130
142
|
const rows = connection.getDb().prepare(`
|
|
131
143
|
SELECT a.activation_id, a.artifact_id, a.target_ref, a.action,
|
|
144
|
+
c.enforcement, c.isolation_decision_id,
|
|
132
145
|
p.source_rule_id, p.source_principle_id,
|
|
133
146
|
length(CAST(p.content_json AS BLOB)) AS content_bytes
|
|
134
|
-
FROM activations a
|
|
147
|
+
FROM activations a
|
|
148
|
+
JOIN pi_artifacts p ON a.artifact_id = p.artifact_id
|
|
149
|
+
LEFT JOIN activation_control_states c ON a.activation_id = c.activation_id
|
|
135
150
|
WHERE a.channel = 'code_tool_hook' AND a.deactivated_at IS NULL
|
|
136
151
|
ORDER BY a.activated_at ASC
|
|
137
152
|
LIMIT ?
|
|
@@ -158,6 +173,15 @@ export function createProductionRuleHostGate(options = {}) {
|
|
|
158
173
|
addWarning(warnings, 'activation_row_invalid', 'deactivate and recreate the malformed activation');
|
|
159
174
|
continue;
|
|
160
175
|
}
|
|
176
|
+
const activationId = typeof row.activation_id === 'string' ? row.activation_id : 'unknown';
|
|
177
|
+
if (row.enforcement === 'safety_isolated') {
|
|
178
|
+
addWarning(warnings, `activation_safety_isolated: ${activationId}`, 'recover the activation to shadow after reviewing safety evidence');
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
if (row.enforcement !== 'eligible') {
|
|
182
|
+
addWarning(warnings, `activation_control_state_invalid: ${activationId}`, 'repair the activation control state before RuleCode enforcement');
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
161
185
|
const group = groups.get(row.target_ref) ?? [];
|
|
162
186
|
group.push(row);
|
|
163
187
|
groups.set(row.target_ref, group);
|
|
@@ -216,6 +240,23 @@ export function createProductionRuleHostGate(options = {}) {
|
|
|
216
240
|
}
|
|
217
241
|
const ruleId = typeof content.ruleId === 'string' ? content.ruleId : typeof row.source_rule_id === 'string' ? row.source_rule_id : artifactId;
|
|
218
242
|
const principleId = typeof content.principleId === 'string' ? content.principleId : typeof row.source_principle_id === 'string' ? row.source_principle_id : ruleId;
|
|
243
|
+
// Retired-contract backstop (2026-08-19; host-liveness correction
|
|
244
|
+
// 2026-08-21):
|
|
245
|
+
// persisted LIVE RuleCode that references removed RuleHost
|
|
246
|
+
// contract symbols can never run safely against the new contract
|
|
247
|
+
// — reads silently resolve to undefined and change owner-approved
|
|
248
|
+
// behavior. The incompatible activation is therefore skipped and
|
|
249
|
+
// surfaced with an actionable warning. It must not turn a runtime
|
|
250
|
+
// compatibility defect into a host-wide deny; healthy sibling
|
|
251
|
+
// rules continue to evaluate. The scan is a local copy (see
|
|
252
|
+
// legacy-rule-contract-symbols.ts) so the published bundle keeps
|
|
253
|
+
// working against the currently published core.
|
|
254
|
+
const retiredSymbols = scanRetiredContractSymbols(content.implementationCode);
|
|
255
|
+
if (retiredSymbols.length > 0) {
|
|
256
|
+
const nextAction = 'migrate the RuleCode off the retired contract symbols or deactivate the activation, then re-approve a migrated rule';
|
|
257
|
+
addWarning(warnings, `legacy_rule_contract_dependency: ${retiredSymbols.join(', ')} (activation=${activationId})`, nextAction);
|
|
258
|
+
continue;
|
|
259
|
+
}
|
|
219
260
|
const fallbackMeta = { name: activationId, version: '1', ruleId, coversCondition: 'all' };
|
|
220
261
|
candidates.push({ implId: activationId, ruleId, principleId, meta: isRuleMeta(content.meta) ? content.meta : fallbackMeta, source: content.implementationCode });
|
|
221
262
|
}
|
|
@@ -226,8 +267,8 @@ export function createProductionRuleHostGate(options = {}) {
|
|
|
226
267
|
}
|
|
227
268
|
const hostInput = {
|
|
228
269
|
action,
|
|
229
|
-
workspace: { isRiskPath: false
|
|
230
|
-
session: { sessionId: event.context.sessionId, currentGfi: enrichment.currentGfi
|
|
270
|
+
workspace: { isRiskPath: false },
|
|
271
|
+
session: { sessionId: event.context.sessionId, currentGfi: enrichment.currentGfi },
|
|
231
272
|
evolution: { epTier: enrichment.epTier },
|
|
232
273
|
derived: { estimatedLineChanges: estimateLineChanges({ toolName: input.toolName, params: input.params }), bashRisk: enrichment.bashRisk },
|
|
233
274
|
...(context ? { context } : {}),
|
|
@@ -37,8 +37,6 @@ try {
|
|
|
37
37
|
' getToolName: () => __pdCallInput.action.toolName,' +
|
|
38
38
|
' getEstimatedLineChanges: () => __pdCallInput.derived.estimatedLineChanges,' +
|
|
39
39
|
' getBashRisk: () => __pdCallInput.derived.bashRisk,' +
|
|
40
|
-
' hasPlanFile: () => __pdCallInput.workspace.hasPlanFile,' +
|
|
41
|
-
' getPlanStatus: () => __pdCallInput.workspace.planStatus,' +
|
|
42
40
|
' getEpTier: () => __pdCallInput.evolution.epTier' +
|
|
43
41
|
'});', { filename: rule.filename + '.bootstrap' }
|
|
44
42
|
).runInContext(context, { timeout: 1000 });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@principles/host-runtime",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Shared host-neutral orchestration for Principles Disciple MVP-Core hook paths.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -22,16 +22,21 @@
|
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"@principles/core": "^1.74.1",
|
|
25
|
+
"@principles/install-layout": "0.1.0",
|
|
25
26
|
"better-sqlite3": "^13.0.3",
|
|
26
27
|
"js-yaml": "^5.2.0"
|
|
27
28
|
},
|
|
28
29
|
"devDependencies": {
|
|
29
|
-
"@types/better-sqlite3": "^
|
|
30
|
+
"@types/better-sqlite3": "^9.6.0",
|
|
30
31
|
"@types/node": "^26.1.2",
|
|
31
32
|
"@types/js-yaml": "^4.0.9",
|
|
32
33
|
"typescript": "^7.0.2",
|
|
33
34
|
"vite": "^8.0.16",
|
|
34
35
|
"vitest": "^4.1.10"
|
|
35
36
|
},
|
|
37
|
+
"repository": {
|
|
38
|
+
"type": "git",
|
|
39
|
+
"url": "git+https://github.com/csuzngjh/principles.git"
|
|
40
|
+
},
|
|
36
41
|
"license": "MIT"
|
|
37
42
|
}
|