create-principles-disciple 1.145.32 → 1.145.34
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/_release/product-identity.json +1 -1
- package/codex-adapter/dist/ingestion/ingestion.js +3 -1
- package/codex-adapter/package.json +1 -1
- package/console/dist/server/models/ActivationsConsoleModel.d.ts +19 -2
- package/console/dist/server/models/ActivationsConsoleModel.js +124 -10
- package/console/dist/server/models/OwnerDecisionConsoleModel.d.ts +3 -1
- package/console/dist/server/models/OwnerDecisionConsoleModel.js +6 -2
- package/console/dist/server/routes/activations.js +7 -2
- package/console/dist/server/routes/owner-decisions.js +1 -1
- package/core/dist/runtime-v2/activation/index.d.ts +6 -0
- package/core/dist/runtime-v2/activation/index.d.ts.map +1 -1
- package/core/dist/runtime-v2/activation/index.js +3 -0
- package/core/dist/runtime-v2/activation/index.js.map +1 -1
- package/core/dist/runtime-v2/activation/openclaw-promotion-checks.d.ts +75 -0
- package/core/dist/runtime-v2/activation/openclaw-promotion-checks.d.ts.map +1 -1
- package/core/dist/runtime-v2/activation/openclaw-promotion-checks.js +131 -37
- package/core/dist/runtime-v2/activation/openclaw-promotion-checks.js.map +1 -1
- package/core/dist/runtime-v2/activation/production-gate-deps.d.ts.map +1 -1
- package/core/dist/runtime-v2/activation/production-gate-deps.js +7 -3
- package/core/dist/runtime-v2/activation/production-gate-deps.js.map +1 -1
- package/core/dist/runtime-v2/activation/recovery-composition.d.ts +54 -0
- package/core/dist/runtime-v2/activation/recovery-composition.d.ts.map +1 -0
- package/core/dist/runtime-v2/activation/recovery-composition.js +129 -0
- package/core/dist/runtime-v2/activation/recovery-composition.js.map +1 -0
- package/core/dist/runtime-v2/activation/recovery-control-surfaces.d.ts +62 -0
- package/core/dist/runtime-v2/activation/recovery-control-surfaces.d.ts.map +1 -0
- package/core/dist/runtime-v2/activation/recovery-control-surfaces.js +84 -0
- package/core/dist/runtime-v2/activation/recovery-control-surfaces.js.map +1 -0
- package/core/dist/runtime-v2/activation/rulecode-shadow-summary.d.ts +13 -1
- package/core/dist/runtime-v2/activation/rulecode-shadow-summary.d.ts.map +1 -1
- package/core/dist/runtime-v2/activation/rulecode-shadow-summary.js +24 -1
- package/core/dist/runtime-v2/activation/rulecode-shadow-summary.js.map +1 -1
- package/core/dist/runtime-v2/index.d.ts +2 -2
- package/core/dist/runtime-v2/index.d.ts.map +1 -1
- package/core/dist/runtime-v2/index.js +1 -1
- package/core/dist/runtime-v2/index.js.map +1 -1
- package/core/dist/runtime-v2/trajectory-schema.d.ts.map +1 -1
- package/core/dist/runtime-v2/trajectory-schema.js +12 -1
- package/core/dist/runtime-v2/trajectory-schema.js.map +1 -1
- package/core/dist/runtime-v2/types/event-types.d.ts +10 -0
- package/core/dist/runtime-v2/types/event-types.d.ts.map +1 -1
- package/core/dist/runtime-v2/types/event-types.js +1 -0
- package/core/dist/runtime-v2/types/event-types.js.map +1 -1
- package/core/package.json +1 -1
- package/dist/installer.d.ts.map +1 -1
- package/dist/installer.js +111 -46
- package/dist/installer.js.map +1 -1
- package/host-runtime/dist/cli-recovery-probe.d.ts +30 -0
- package/host-runtime/dist/cli-recovery-probe.js +169 -0
- package/host-runtime/dist/governance-signal-admission.js +22 -5
- package/host-runtime/dist/host-liveness-contract.d.ts +51 -28
- package/host-runtime/dist/host-liveness-contract.js +143 -46
- package/host-runtime/dist/index.d.ts +2 -0
- package/host-runtime/dist/index.js +2 -0
- package/host-runtime/dist/production-pain-evidence.d.ts +2 -0
- package/host-runtime/dist/production-pain-evidence.js +46 -8
- package/host-runtime/dist/production-rulehost-gate.js +24 -6
- package/host-runtime/dist/workbuddy-rule-context-provider.d.ts +33 -0
- package/host-runtime/dist/workbuddy-rule-context-provider.js +126 -0
- package/host-runtime/dist/workspace-behavior-evidence.d.ts +22 -5
- package/host-runtime/dist/workspace-behavior-evidence.js +41 -11
- package/host-runtime/package.json +1 -1
- package/package.json +2 -2
- package/pd-cli/dist/commands/recovery-reachability-probe.d.ts +25 -0
- package/pd-cli/dist/commands/recovery-reachability-probe.d.ts.map +1 -0
- package/pd-cli/dist/commands/recovery-reachability-probe.js +50 -0
- package/pd-cli/dist/commands/recovery-reachability-probe.js.map +1 -0
- package/pd-cli/dist/commands/runtime-activation.d.ts +10 -1
- package/pd-cli/dist/commands/runtime-activation.d.ts.map +1 -1
- package/pd-cli/dist/commands/runtime-activation.js +81 -3
- package/pd-cli/dist/commands/runtime-activation.js.map +1 -1
- package/pd-cli/package.json +1 -1
- package/plugin/dist/bundle.js +385 -385
- package/plugin/dist/governance-audit.js +1 -1
- package/plugin/dist/openclaw.plugin.json +1 -1
- package/plugin/dist/rulehost-evidence.js +1 -1
- package/plugin/openclaw.plugin.json +1 -1
- package/plugin/package.json +1 -1
- package/release-manager/dist/installer.d.ts.map +1 -1
- package/release-manager/dist/installer.js +111 -46
- package/release-manager/dist/installer.js.map +1 -1
- package/release-manager/package.json +2 -2
- package/workbuddy-adapter/dist/codec/input-decoder.d.ts +14 -11
- package/workbuddy-adapter/dist/codec/input-decoder.js +28 -14
- package/workbuddy-adapter/dist/pd-hook.js +31 -12
- package/workbuddy-adapter/package.json +1 -1
|
@@ -314,6 +314,22 @@ function ensureToolCallsProjectDirColumn(db) {
|
|
|
314
314
|
// the prepared-statement readiness check below fails loud if absent.
|
|
315
315
|
}
|
|
316
316
|
}
|
|
317
|
+
/**
|
|
318
|
+
* SPEC-RULECODE-HOST-PROMOTION-001 R2: additive migration for producer host
|
|
319
|
+
* attribution. Legacy rows stay NULL — the WorkBuddy rule-context reader
|
|
320
|
+
* treats a NULL stamp as unprovable (never guessed), so no backfill exists.
|
|
321
|
+
*/
|
|
322
|
+
function ensureToolCallsHostKindColumn(db) {
|
|
323
|
+
const columns = db.prepare('PRAGMA table_info(tool_calls)').all();
|
|
324
|
+
if (columns.some((row) => pragmaField(row, 'name') === 'host_kind'))
|
|
325
|
+
return;
|
|
326
|
+
try {
|
|
327
|
+
db.exec('ALTER TABLE tool_calls ADD COLUMN host_kind TEXT');
|
|
328
|
+
}
|
|
329
|
+
catch {
|
|
330
|
+
// Same concurrent-writer contract as the sibling migrations above.
|
|
331
|
+
}
|
|
332
|
+
}
|
|
317
333
|
/**
|
|
318
334
|
* SPEC-CODEX-PAIN-CLOSURE-001 CR-01: upgrade the live-hook observation of a
|
|
319
335
|
* tool call with the host-verified final result (exit code) read through the
|
|
@@ -342,9 +358,18 @@ export function recordVerifiedToolOutcomes(args) {
|
|
|
342
358
|
if (!hasToolCalls)
|
|
343
359
|
applyTrajectorySchemaBase(db);
|
|
344
360
|
ensureToolCallsToolUseIdColumn(db);
|
|
345
|
-
|
|
361
|
+
ensureToolCallsHostKindColumn(db);
|
|
362
|
+
// Review R3/P2: a KNOWN host's call identity includes its attribution.
|
|
363
|
+
// The lookup matches ONLY rows of the same host — a colliding row from
|
|
364
|
+
// another host (or an unattributed legacy row) is a DIFFERENT record: the
|
|
365
|
+
// caller inserts its own row instead of swallowing or claiming it.
|
|
366
|
+
// Callers without a hostKind keep the historical match-any semantics
|
|
367
|
+
// (explicit compat contract, asserted by tests).
|
|
368
|
+
const findByToolUseId = args.hostKind !== undefined
|
|
369
|
+
? db.prepare('SELECT id, outcome FROM tool_calls WHERE session_id = ? AND tool_use_id = ? AND host_kind = ? ORDER BY id LIMIT 1')
|
|
370
|
+
: db.prepare('SELECT id, outcome FROM tool_calls WHERE session_id = ? AND tool_use_id = ? ORDER BY id LIMIT 1');
|
|
346
371
|
const upgradeUnknown = db.prepare("UPDATE tool_calls SET outcome = ?, exit_code = ?, result_preview = COALESCE(?, result_preview) WHERE id = ? AND outcome = 'unknown'");
|
|
347
|
-
const insertVerified = db.prepare('INSERT INTO tool_calls (session_id, tool_name, outcome, duration_ms, exit_code, error_type, error_message, gfi_before, gfi_after, params_json, result_preview, created_at, tool_use_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)');
|
|
372
|
+
const insertVerified = db.prepare('INSERT INTO tool_calls (session_id, tool_name, outcome, duration_ms, exit_code, error_type, error_message, gfi_before, gfi_after, params_json, result_preview, created_at, tool_use_id, host_kind) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)');
|
|
348
373
|
const upsertSession = db.prepare('INSERT INTO sessions (session_id, started_at, updated_at) VALUES (?, ?, ?) ON CONFLICT(session_id) DO UPDATE SET updated_at = excluded.updated_at');
|
|
349
374
|
const createdAt = new Date().toISOString();
|
|
350
375
|
db.transaction(() => {
|
|
@@ -352,7 +377,9 @@ export function recordVerifiedToolOutcomes(args) {
|
|
|
352
377
|
if (typeof input.exitCode !== 'number' || !Number.isInteger(input.exitCode))
|
|
353
378
|
continue;
|
|
354
379
|
const finalOutcome = input.exitCode === 0 ? 'success' : 'failure';
|
|
355
|
-
const existing =
|
|
380
|
+
const existing = (args.hostKind !== undefined
|
|
381
|
+
? findByToolUseId.get(args.sessionId, input.toolUseId, args.hostKind)
|
|
382
|
+
: findByToolUseId.get(args.sessionId, input.toolUseId));
|
|
356
383
|
const boundedPreview = typeof input.outputPreview === 'string' && input.outputPreview.length > 0
|
|
357
384
|
? input.outputPreview.slice(0, MAX_PREVIEW)
|
|
358
385
|
: null;
|
|
@@ -368,7 +395,7 @@ export function recordVerifiedToolOutcomes(args) {
|
|
|
368
395
|
}
|
|
369
396
|
upsertSession.run(args.sessionId, createdAt, createdAt);
|
|
370
397
|
const sanitizedParams = sanitizeToolParams(input.params ?? {}, args.workspaceDir);
|
|
371
|
-
const info = insertVerified.run(args.sessionId, input.toolName, finalOutcome, null, input.exitCode, null, null, null, null, stable(sanitizedParams), boundedPreview, createdAt, input.toolUseId);
|
|
398
|
+
const info = insertVerified.run(args.sessionId, input.toolName, finalOutcome, null, input.exitCode, null, null, null, null, stable(sanitizedParams), boundedPreview, createdAt, input.toolUseId, args.hostKind ?? null);
|
|
372
399
|
results.push({ status: 'inserted', id: Number(info.lastInsertRowid) });
|
|
373
400
|
}
|
|
374
401
|
})();
|
|
@@ -426,6 +453,7 @@ export function createProductionPainEvidenceHandler(options = {}) {
|
|
|
426
453
|
db.pragma('busy_timeout = 5000');
|
|
427
454
|
ensureToolCallsToolUseIdColumn(db);
|
|
428
455
|
ensureToolCallsProjectDirColumn(db);
|
|
456
|
+
ensureToolCallsHostKindColumn(db);
|
|
429
457
|
if (!hasCanonicalSchema(db)) {
|
|
430
458
|
db.close();
|
|
431
459
|
db = undefined;
|
|
@@ -520,20 +548,30 @@ export function createProductionPainEvidenceHandler(options = {}) {
|
|
|
520
548
|
// CR-01: the host tool-call id is the stable join key for the
|
|
521
549
|
// consent-gated transcript upgrade (recordVerifiedToolOutcomes);
|
|
522
550
|
// content-shape probing stays the fallback for hosts without ids.
|
|
551
|
+
// Review R3/P2: for a known host the identity is host-scoped — a
|
|
552
|
+
// colliding row from ANOTHER host (or an unattributed legacy row) is
|
|
553
|
+
// NOT this delivery's duplicate, so both hosts keep independent
|
|
554
|
+
// records instead of the second being swallowed.
|
|
523
555
|
if (event.context.toolCallId !== undefined
|
|
524
|
-
&&
|
|
556
|
+
&& (options.hostKind !== undefined
|
|
557
|
+
? db.prepare('SELECT 1 FROM tool_calls WHERE session_id = ? AND tool_use_id = ? AND host_kind = ?').get(event.context.sessionId, event.context.toolCallId, options.hostKind)
|
|
558
|
+
: db.prepare('SELECT 1 FROM tool_calls WHERE session_id = ? AND tool_use_id = ?').get(event.context.sessionId, event.context.toolCallId)) !== undefined) {
|
|
525
559
|
duplicate = true;
|
|
526
560
|
duplicateAdmitted = db.prepare('SELECT 1 FROM pain_events WHERE canonical_pain_id = ?').get(painId) !== undefined;
|
|
527
561
|
return;
|
|
528
562
|
}
|
|
529
|
-
|
|
563
|
+
// Review R3/P2: the content-shape fallback dedup is host-scoped the
|
|
564
|
+
// same way — identical content from two hosts is two records.
|
|
565
|
+
if ((options.hostKind !== undefined
|
|
566
|
+
? db.prepare('SELECT 1 FROM tool_calls WHERE session_id = ? AND tool_name = ? AND params_json = ? AND outcome = ? AND exit_code IS ? AND error_message IS ? AND result_preview IS ? AND host_kind = ?').get(event.context.sessionId, toolName, paramsJson, outcome.outcome, outcome.exitCode, outcome.error ?? null, resultPreview, options.hostKind)
|
|
567
|
+
: db.prepare('SELECT 1 FROM tool_calls WHERE session_id = ? AND tool_name = ? AND params_json = ? AND outcome = ? AND exit_code IS ? AND error_message IS ? AND result_preview IS ?').get(event.context.sessionId, toolName, paramsJson, outcome.outcome, outcome.exitCode, outcome.error ?? null, resultPreview)) !== undefined) {
|
|
530
568
|
duplicate = true;
|
|
531
569
|
duplicateAdmitted = db.prepare('SELECT 1 FROM pain_events WHERE canonical_pain_id = ?').get(painId) !== undefined;
|
|
532
570
|
return;
|
|
533
571
|
}
|
|
534
572
|
db.prepare(`INSERT INTO sessions (session_id, started_at, updated_at) VALUES (?, ?, ?) ON CONFLICT(session_id) DO UPDATE SET updated_at = excluded.updated_at`).run(event.context.sessionId, createdAt, createdAt);
|
|
535
|
-
db.prepare(`INSERT INTO tool_calls (session_id, tool_name, outcome, duration_ms, exit_code, error_type, error_message, gfi_before, gfi_after, params_json, result_preview, created_at, tool_use_id, project_dir) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
536
|
-
.run(event.context.sessionId, toolName, outcome.outcome, outcome.durationMs ?? null, outcome.exitCode, outcome.error ? outcome.error.split(/[\s:]/, 1)[0] : null, outcome.error ?? null, null, null, paramsJson, resultPreview, createdAt, event.context.toolCallId ?? null, path.resolve(options.projectDir ?? event.context.workspaceDir));
|
|
573
|
+
db.prepare(`INSERT INTO tool_calls (session_id, tool_name, outcome, duration_ms, exit_code, error_type, error_message, gfi_before, gfi_after, params_json, result_preview, created_at, tool_use_id, project_dir, host_kind) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
574
|
+
.run(event.context.sessionId, toolName, outcome.outcome, outcome.durationMs ?? null, outcome.exitCode, outcome.error ? outcome.error.split(/[\s:]/, 1)[0] : null, outcome.error ?? null, null, null, paramsJson, resultPreview, createdAt, event.context.toolCallId ?? null, path.resolve(options.projectDir ?? event.context.workspaceDir), options.hostKind ?? null);
|
|
537
575
|
if (admitted) {
|
|
538
576
|
// Raw observation only (Pain Diagnosis Persistence SPEC §8): the
|
|
539
577
|
// pain row must record WHAT happened, not WHY. Attribution
|
|
@@ -350,21 +350,26 @@ export function createProductionRuleHostGate(options = {}) {
|
|
|
350
350
|
// evaluator replay; merely wiring history must not revive old
|
|
351
351
|
// activations. Live execution additionally needs the existing
|
|
352
352
|
// promotion decision's binding to this exact artifact snapshot.
|
|
353
|
-
|
|
353
|
+
// SPEC-RULECODE-HOST-PROMOTION-001 §11.3: the SAME qualification
|
|
354
|
+
// gates every host with a V2 context path — WorkBuddy must not
|
|
355
|
+
// auto-execute historical V2 artifacts stamped for another host
|
|
356
|
+
// (the hostKinds binding below rejects them by the exact same
|
|
357
|
+
// includes() check Codex uses).
|
|
358
|
+
if (options.hostKind === 'codex' || options.hostKind === 'workbuddy') {
|
|
354
359
|
const contract = content.ruleHostInputContract;
|
|
355
360
|
const hosts = isRecord(contract) ? contract.hostKinds : undefined;
|
|
356
361
|
let contentBindingVerified = digestCheck.outcome === 'verified';
|
|
357
362
|
if (activationMode === 'shadow' && row.owner_approved === 1) {
|
|
358
363
|
// Old databases remain readable without writing a migration
|
|
359
364
|
// from this enforcement reader. A legacy approval without a
|
|
360
|
-
// content digest cannot grant
|
|
365
|
+
// content digest cannot grant V2 execution eligibility.
|
|
361
366
|
const approvalColumns = connection.getDb().prepare('PRAGMA table_info(approvals)').all();
|
|
362
367
|
if (approvalColumns.some((column) => isRecord(column) && column.name === 'artifact_digest')) {
|
|
363
368
|
const approval = connection.getDb().prepare(`
|
|
364
369
|
SELECT artifact_digest FROM approvals
|
|
365
370
|
WHERE artifact_id = ? AND channel = 'code_tool_hook' AND status = 'approved'
|
|
366
371
|
ORDER BY decided_at DESC LIMIT 1
|
|
367
|
-
|
|
372
|
+
`).get(artifactId);
|
|
368
373
|
const approvalDigest = isRecord(approval) && typeof approval.artifact_digest === 'string'
|
|
369
374
|
? approval.artifact_digest : null;
|
|
370
375
|
contentBindingVerified = verifyPiArtifactRowDigest(contentRow, contentJson, approvalDigest).outcome === 'verified';
|
|
@@ -375,9 +380,9 @@ export function createProductionRuleHostGate(options = {}) {
|
|
|
375
380
|
}
|
|
376
381
|
if (!isRecord(contract) || contract.version !== 1 || contract.contextVersion !== 2
|
|
377
382
|
|| !Array.isArray(hosts) || !hosts.every((host) => typeof host === 'string')
|
|
378
|
-
|| !hosts.includes(
|
|
383
|
+
|| !hosts.includes(options.hostKind) || row.owner_approved !== 1
|
|
379
384
|
|| !contentBindingVerified) {
|
|
380
|
-
addWarning(warnings,
|
|
385
|
+
addWarning(warnings, `${options.hostKind}_rule_context_v2_unqualified: activation=${activationId}`, `regenerate and replay this artifact for ${options.hostKind}, approve it for shadow observation, and use the existing Owner promotion flow for live execution`);
|
|
381
386
|
continue;
|
|
382
387
|
}
|
|
383
388
|
}
|
|
@@ -419,7 +424,18 @@ export function createProductionRuleHostGate(options = {}) {
|
|
|
419
424
|
: context === UNAVAILABLE_RULE_CONTEXT
|
|
420
425
|
? (contextFault ?? 'provider_invalid')
|
|
421
426
|
: 'history_unavailable';
|
|
422
|
-
|
|
427
|
+
// SPEC-RULECODE-HOST-PROMOTION-001 R2: a schema-valid
|
|
428
|
+
// unavailable context carries the provider's precise reason
|
|
429
|
+
// (e.g. workbuddy_history_attribution_conflict) — surface it
|
|
430
|
+
// in the warning instead of collapsing every legit
|
|
431
|
+
// unavailability into one opaque class (rc-9).
|
|
432
|
+
const preciseReason = context !== undefined
|
|
433
|
+
&& context !== UNAVAILABLE_RULE_CONTEXT
|
|
434
|
+
&& typeof context.history.unavailableReason === 'string'
|
|
435
|
+
&& context.history.unavailableReason.length > 0
|
|
436
|
+
? `:${context.history.unavailableReason}`
|
|
437
|
+
: '';
|
|
438
|
+
addWarning(warnings, `rule_context_v2_unavailable: ${fault}${preciseReason} (activation=${activationId})`, 'enable and wire the host rule context provider, or regenerate the rule without context dependence');
|
|
423
439
|
continue;
|
|
424
440
|
}
|
|
425
441
|
const inputContract = content.ruleHostInputContract;
|
|
@@ -547,6 +563,7 @@ export function createProductionRuleHostGate(options = {}) {
|
|
|
547
563
|
ruleId: candidate.ruleId,
|
|
548
564
|
activationId: candidate.implId,
|
|
549
565
|
activationMode: 'shadow',
|
|
566
|
+
...(options.hostKind !== undefined ? { hostKind: options.hostKind } : {}),
|
|
550
567
|
});
|
|
551
568
|
}
|
|
552
569
|
}
|
|
@@ -604,6 +621,7 @@ export function createProductionRuleHostGate(options = {}) {
|
|
|
604
621
|
...(result?.ruleId !== undefined ? { ruleId: result.ruleId } : {}),
|
|
605
622
|
...(liveActivationId !== undefined ? { activationId: liveActivationId } : {}),
|
|
606
623
|
activationMode: 'live',
|
|
624
|
+
...(options.hostKind !== undefined ? { hostKind: options.hostKind } : {}),
|
|
607
625
|
},
|
|
608
626
|
...shadowEvaluations,
|
|
609
627
|
];
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { type ToolSemanticRegistry } from '@principles/core/runtime-v2';
|
|
2
|
+
import type { RuleContextProvider } from './production-rulehost-gate.js';
|
|
3
|
+
export interface WorkbuddyRuleContextProviderOptions {
|
|
4
|
+
/** The WorkBuddy governance workspace whose trajectory database is authoritative. */
|
|
5
|
+
workspaceDir: string;
|
|
6
|
+
/** The host project cwd the hook observed (payload cwd); history rows must have this exact stored scope. Absent on channels that carry none. */
|
|
7
|
+
projectDir?: string;
|
|
8
|
+
/** The existing `rulecode_context_v2` gate. */
|
|
9
|
+
enabled: boolean;
|
|
10
|
+
/** Timestamp captured immediately after decoding this hook event. */
|
|
11
|
+
cutoffAt: Date;
|
|
12
|
+
/** Host-authoritative current WorkBuddy call_id, excluded even on timestamp ties. */
|
|
13
|
+
currentToolCallId: string;
|
|
14
|
+
toolSemantics: ToolSemanticRegistry;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* SPEC-RULECODE-HOST-PROMOTION-001 C: the WorkBuddy RuleContext provider.
|
|
18
|
+
*
|
|
19
|
+
* It reads the SAME canonical trajectory store the shared afterToolCall
|
|
20
|
+
* production path writes for WorkBuddy (`tool_calls` rows carrying the
|
|
21
|
+
* host's natural session/call ids and the observed project cwd) — genuinely
|
|
22
|
+
* observable WorkBuddy data, never borrowed Codex history. WorkBuddy has no
|
|
23
|
+
* design-gate declaration entry point (the Codex-native attestation source
|
|
24
|
+
* is Codex-only), so this provider deliberately supplies NO designGate
|
|
25
|
+
* fact: a rule whose required facts include design_approval stays suspended
|
|
26
|
+
* on this host with the precise `rule_required_fact_unavailable` warning
|
|
27
|
+
* instead of inheriting another host's attestation.
|
|
28
|
+
*
|
|
29
|
+
* Disabled, unscoped or unverifiable sources return explicit unavailable
|
|
30
|
+
* contexts — v2 rules then suspend through the existing shared-gate
|
|
31
|
+
* contract, which is the honest state until the missing input exists.
|
|
32
|
+
*/
|
|
33
|
+
export declare function createWorkbuddyRuleContextProvider(options: WorkbuddyRuleContextProviderOptions): RuleContextProvider;
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { computeBehaviorFacts, } from '@principles/core/runtime-v2';
|
|
3
|
+
import { assembleBehaviorHistory } from './behavior-history.js';
|
|
4
|
+
import { readWorkspaceRuleContextRowsBefore } from './workspace-behavior-evidence.js';
|
|
5
|
+
const HISTORY_LIMIT = 100;
|
|
6
|
+
const MAX_REASON_LENGTH = 240;
|
|
7
|
+
function isRecord(value) {
|
|
8
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
9
|
+
}
|
|
10
|
+
function unavailable(reason) {
|
|
11
|
+
const history = {
|
|
12
|
+
status: 'unavailable',
|
|
13
|
+
unavailableReason: reason.replace(/\s+/g, ' ').slice(0, MAX_REASON_LENGTH),
|
|
14
|
+
truncated: false,
|
|
15
|
+
calls: [],
|
|
16
|
+
};
|
|
17
|
+
return {
|
|
18
|
+
version: 2,
|
|
19
|
+
history,
|
|
20
|
+
facts: computeBehaviorFacts(history, null, null),
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* SPEC-RULECODE-HOST-PROMOTION-001 C: the WorkBuddy RuleContext provider.
|
|
25
|
+
*
|
|
26
|
+
* It reads the SAME canonical trajectory store the shared afterToolCall
|
|
27
|
+
* production path writes for WorkBuddy (`tool_calls` rows carrying the
|
|
28
|
+
* host's natural session/call ids and the observed project cwd) — genuinely
|
|
29
|
+
* observable WorkBuddy data, never borrowed Codex history. WorkBuddy has no
|
|
30
|
+
* design-gate declaration entry point (the Codex-native attestation source
|
|
31
|
+
* is Codex-only), so this provider deliberately supplies NO designGate
|
|
32
|
+
* fact: a rule whose required facts include design_approval stays suspended
|
|
33
|
+
* on this host with the precise `rule_required_fact_unavailable` warning
|
|
34
|
+
* instead of inheriting another host's attestation.
|
|
35
|
+
*
|
|
36
|
+
* Disabled, unscoped or unverifiable sources return explicit unavailable
|
|
37
|
+
* contexts — v2 rules then suspend through the existing shared-gate
|
|
38
|
+
* contract, which is the honest state until the missing input exists.
|
|
39
|
+
*/
|
|
40
|
+
export function createWorkbuddyRuleContextProvider(options) {
|
|
41
|
+
const workspaceDir = path.resolve(options.workspaceDir);
|
|
42
|
+
const projectDir = options.projectDir !== undefined ? path.resolve(options.projectDir) : undefined;
|
|
43
|
+
return (request) => {
|
|
44
|
+
if (typeof request.sessionId !== 'string' || request.sessionId.trim().length === 0) {
|
|
45
|
+
return unavailable('session_id_invalid');
|
|
46
|
+
}
|
|
47
|
+
if (!options.enabled)
|
|
48
|
+
return unavailable('workbuddy_rule_context_disabled');
|
|
49
|
+
if (path.resolve(request.workspaceDir) !== workspaceDir)
|
|
50
|
+
return unavailable('workspace_scope_mismatch');
|
|
51
|
+
if (projectDir === undefined || !path.isAbsolute(projectDir)) {
|
|
52
|
+
return unavailable('workbuddy_project_scope_unavailable');
|
|
53
|
+
}
|
|
54
|
+
const raw = request.rawPayload;
|
|
55
|
+
const toolInput = isRecord(raw) && isRecord(raw.toolInput) ? raw.toolInput : null;
|
|
56
|
+
if (toolInput === null
|
|
57
|
+
|| toolInput.toolName !== request.toolName
|
|
58
|
+
|| !isRecord(toolInput.params)
|
|
59
|
+
|| options.currentToolCallId.trim().length === 0) {
|
|
60
|
+
return unavailable('workbuddy_pre_tool_scope_mismatch');
|
|
61
|
+
}
|
|
62
|
+
const cutoff = options.cutoffAt;
|
|
63
|
+
if (!(cutoff instanceof Date) || !Number.isFinite(cutoff.getTime()))
|
|
64
|
+
return unavailable('history_cutoff_invalid');
|
|
65
|
+
try {
|
|
66
|
+
const historyRows = readWorkspaceRuleContextRowsBefore(workspaceDir, {
|
|
67
|
+
sessionId: request.sessionId,
|
|
68
|
+
projectDir,
|
|
69
|
+
beforeCreatedAt: cutoff.toISOString(),
|
|
70
|
+
excludeToolUseId: options.currentToolCallId,
|
|
71
|
+
limit: HISTORY_LIMIT,
|
|
72
|
+
// Review R2: consume ONLY rows PROVEN to be WorkBuddy's (stamped by
|
|
73
|
+
// this host's own writer). "Same workspace + same session id +
|
|
74
|
+
// same project" is NOT proof — a Codex session id colliding here
|
|
75
|
+
// must never lend its reads to a WorkBuddy read-before-write rule.
|
|
76
|
+
hostKind: 'workbuddy',
|
|
77
|
+
});
|
|
78
|
+
if (historyRows.unscopedPriorRows)
|
|
79
|
+
return unavailable('trajectory_project_scope_incomplete');
|
|
80
|
+
if ((historyRows.otherHostRows ?? 0) > 0) {
|
|
81
|
+
return unavailable('workbuddy_history_attribution_conflict');
|
|
82
|
+
}
|
|
83
|
+
if (historyRows.rows.length === 0) {
|
|
84
|
+
// Fail closed with the precise reason: legacy rows exist but cannot
|
|
85
|
+
// be PROVEN WorkBuddy's (never back-filled, never assumed).
|
|
86
|
+
if ((historyRows.unattributedRows ?? 0) > 0)
|
|
87
|
+
return unavailable('workbuddy_history_attribution_unprovable');
|
|
88
|
+
return unavailable('no_prior_session_history');
|
|
89
|
+
}
|
|
90
|
+
if ((historyRows.unattributedRows ?? 0) > 0) {
|
|
91
|
+
// Mixed window: consuming only the proven subset could UNDERCOUNT
|
|
92
|
+
// prior reads (a hidden foreign read would flip priorReadOfTarget),
|
|
93
|
+
// so the window is unprovable as a whole — suspend precisely.
|
|
94
|
+
return unavailable('workbuddy_history_attribution_unprovable');
|
|
95
|
+
}
|
|
96
|
+
const history = assembleBehaviorHistory(historyRows.rows, historyRows.truncated, {
|
|
97
|
+
projectDir,
|
|
98
|
+
toolSemantics: options.toolSemantics,
|
|
99
|
+
});
|
|
100
|
+
// WorkBuddy exposes its shell as the Bash tool, and MCP-style tools may
|
|
101
|
+
// resolve to 'other' absent from this host's semantic registry. Either
|
|
102
|
+
// may read or mutate files, so target-read absence and exact action
|
|
103
|
+
// counts cannot be asserted from this partial semantic view (same
|
|
104
|
+
// conservative rule as the Codex provider).
|
|
105
|
+
const factsIncomplete = history.truncated || history.calls.some((call) => call.canonicalKind === 'execute' || call.canonicalKind === 'other');
|
|
106
|
+
const computedFacts = computeBehaviorFacts(history, factsIncomplete ? null : request.targetPath, null);
|
|
107
|
+
const facts = factsIncomplete
|
|
108
|
+
? {
|
|
109
|
+
priorReadOfTarget: 'unknown',
|
|
110
|
+
readCount: null,
|
|
111
|
+
writeCount: null,
|
|
112
|
+
uniqueWritePathCount: null,
|
|
113
|
+
sameActionBlockCount: null,
|
|
114
|
+
}
|
|
115
|
+
: computedFacts;
|
|
116
|
+
return {
|
|
117
|
+
version: 2,
|
|
118
|
+
history,
|
|
119
|
+
facts,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
return unavailable(`trajectory_history_unavailable:${error instanceof Error ? error.message : String(error)}`);
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
}
|
|
@@ -7,18 +7,35 @@ export declare function createWorkspaceBehaviorEvidencePort(workspaceDir: string
|
|
|
7
7
|
* database. The timestamp is the caller's pre-event cutoff; rows at or after
|
|
8
8
|
* it are excluded so replayed/future calls cannot enter a live RuleContext.
|
|
9
9
|
* This is read-only and never creates or migrates trajectory state.
|
|
10
|
+
*
|
|
11
|
+
* Review R2 (SPEC-RULECODE-HOST-PROMOTION-001): when `hostKind` is supplied,
|
|
12
|
+
* the reader partitions the window by PROVEN producer attribution
|
|
13
|
+
* (`tool_calls.host_kind`, stamped by each host's writer) instead of handing
|
|
14
|
+
* back every row: `rows` carries only rows stamped with that host,
|
|
15
|
+
* `otherHostRows` counts rows stamped with a different host (a cross-host
|
|
16
|
+
* session-id collision), and `unattributedRows` counts legacy rows with no
|
|
17
|
+
* stamp (written before the column existed — attribution is unprovable, not
|
|
18
|
+
* assumed). A database whose tool_calls predates the column entirely counts
|
|
19
|
+
* every row in the unattributed bucket. The caller decides the failure
|
|
20
|
+
* policy; this reader never guesses an attribution.
|
|
10
21
|
*/
|
|
22
|
+
export interface WorkspaceRuleContextRowsResult {
|
|
23
|
+
rows: readonly RuleHostContextRow[];
|
|
24
|
+
truncated: boolean;
|
|
25
|
+
unscopedPriorRows: boolean;
|
|
26
|
+
/** Present only for attribution-aware reads: rows stamped with ANOTHER host (never zero-checked when hostKind is absent). */
|
|
27
|
+
otherHostRows?: number;
|
|
28
|
+
/** Present only for attribution-aware reads: legacy rows with no host stamp. */
|
|
29
|
+
unattributedRows?: number;
|
|
30
|
+
}
|
|
11
31
|
export declare function readWorkspaceRuleContextRowsBefore(workspaceDir: string, input: {
|
|
12
32
|
sessionId: string;
|
|
13
33
|
projectDir: string;
|
|
14
34
|
beforeCreatedAt: string;
|
|
15
35
|
excludeToolUseId: string;
|
|
16
36
|
limit: number;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
truncated: boolean;
|
|
20
|
-
unscopedPriorRows: boolean;
|
|
21
|
-
};
|
|
37
|
+
hostKind?: string;
|
|
38
|
+
}): WorkspaceRuleContextRowsResult;
|
|
22
39
|
/**
|
|
23
40
|
* List only Codex sessions proven by normalized host evidence and a matching
|
|
24
41
|
* project-scoped trajectory row. The trajectory schema has no host_kind on
|
|
@@ -74,12 +74,6 @@ export function createWorkspaceBehaviorEvidencePort(workspaceDir, toolSemantics)
|
|
|
74
74
|
},
|
|
75
75
|
};
|
|
76
76
|
}
|
|
77
|
-
/**
|
|
78
|
-
* Read one bounded, same-session history window from the canonical trajectory
|
|
79
|
-
* database. The timestamp is the caller's pre-event cutoff; rows at or after
|
|
80
|
-
* it are excluded so replayed/future calls cannot enter a live RuleContext.
|
|
81
|
-
* This is read-only and never creates or migrates trajectory state.
|
|
82
|
-
*/
|
|
83
77
|
export function readWorkspaceRuleContextRowsBefore(workspaceDir, input) {
|
|
84
78
|
const { sessionId, projectDir, beforeCreatedAt, excludeToolUseId, limit } = input;
|
|
85
79
|
if (sessionId.trim().length === 0)
|
|
@@ -95,9 +89,21 @@ export function readWorkspaceRuleContextRowsBefore(workspaceDir, input) {
|
|
|
95
89
|
const db = new Database(path.join(workspaceDir, '.state', 'trajectory.db'), { readonly: true, fileMustExist: true });
|
|
96
90
|
try {
|
|
97
91
|
db.pragma('busy_timeout = 100');
|
|
92
|
+
const attributionAware = input.hostKind !== undefined;
|
|
93
|
+
// Select host_kind ONLY for attribution-aware reads on schemas that carry
|
|
94
|
+
// the column. A plain read (or a legacy schema without the column) keeps
|
|
95
|
+
// the historical column list — never a failing query.
|
|
96
|
+
const includeHostKind = attributionAware && (() => {
|
|
97
|
+
const columns = db.prepare('PRAGMA table_info(tool_calls)').all();
|
|
98
|
+
return Array.isArray(columns)
|
|
99
|
+
&& columns.some((column) => record(column) && typeof column.name === 'string' && column.name === 'host_kind');
|
|
100
|
+
})();
|
|
98
101
|
return db.transaction(() => {
|
|
99
|
-
|
|
100
|
-
|
|
102
|
+
// Attribution-aware read: fetch one extra slot beyond the limit so the
|
|
103
|
+
// partition counts stay truthful about a truncated window's tail.
|
|
104
|
+
const selectColumns = includeHostKind ? 'id, tool_name, outcome, params_json, host_kind' : 'id, tool_name, outcome, params_json';
|
|
105
|
+
const fetched = db.prepare(`
|
|
106
|
+
SELECT ${selectColumns}
|
|
101
107
|
FROM tool_calls
|
|
102
108
|
WHERE session_id = ? AND project_dir = ? AND created_at < ? AND (tool_use_id IS NULL OR tool_use_id <> ?)
|
|
103
109
|
ORDER BY created_at DESC, id DESC
|
|
@@ -108,12 +114,36 @@ export function readWorkspaceRuleContextRowsBefore(workspaceDir, input) {
|
|
|
108
114
|
WHERE session_id = ? AND project_dir IS NULL AND created_at < ?
|
|
109
115
|
AND (tool_use_id IS NULL OR tool_use_id <> ?) LIMIT 1
|
|
110
116
|
`).get(sessionId, beforeCreatedAt, excludeToolUseId);
|
|
111
|
-
if (!Array.isArray(
|
|
117
|
+
if (!Array.isArray(fetched))
|
|
112
118
|
throw new Error('history_query_invalid');
|
|
119
|
+
if (!attributionAware) {
|
|
120
|
+
return {
|
|
121
|
+
rows: fetched.slice(0, limit).reverse().map(contextRow),
|
|
122
|
+
truncated: fetched.length > limit,
|
|
123
|
+
unscopedPriorRows: unscoped !== undefined,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
let otherHostRows = 0;
|
|
127
|
+
let unattributedRows = 0;
|
|
128
|
+
const matching = [];
|
|
129
|
+
for (const row of fetched) {
|
|
130
|
+
if (!record(row) || !Object.hasOwn(row, 'host_kind') || row.host_kind === null || row.host_kind === undefined) {
|
|
131
|
+
// No stamp (or no column): unprovable — never guessed into the host.
|
|
132
|
+
unattributedRows += 1;
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
if (row.host_kind !== input.hostKind) {
|
|
136
|
+
otherHostRows += 1;
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
matching.push(row);
|
|
140
|
+
}
|
|
113
141
|
return {
|
|
114
|
-
rows:
|
|
115
|
-
truncated:
|
|
142
|
+
rows: matching.slice(0, limit).reverse().map(contextRow),
|
|
143
|
+
truncated: fetched.length > limit,
|
|
116
144
|
unscopedPriorRows: unscoped !== undefined,
|
|
145
|
+
otherHostRows,
|
|
146
|
+
unattributedRows,
|
|
117
147
|
};
|
|
118
148
|
})();
|
|
119
149
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-principles-disciple",
|
|
3
|
-
"version": "1.145.
|
|
3
|
+
"version": "1.145.34",
|
|
4
4
|
"description": "Interactive CLI installer for Principles Disciple OpenClaw plugin",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -89,6 +89,6 @@
|
|
|
89
89
|
"directory": "packages/create-principles-disciple"
|
|
90
90
|
},
|
|
91
91
|
"pd": {
|
|
92
|
-
"bundledPluginVersion": "2.2.
|
|
92
|
+
"bundledPluginVersion": "2.2.7"
|
|
93
93
|
}
|
|
94
94
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { RecoveryCapabilityEvidence } from '@principles/core/runtime-v2';
|
|
2
|
+
/**
|
|
3
|
+
* SPEC-RULECODE-HOST-PROMOTION-001 R3/R4: CLI-channel recovery reachability
|
|
4
|
+
* for the pd-cli readiness path. Thin wrapper — the real subprocess probes
|
|
5
|
+
* live in host-runtime (`probeCliRecoveryCapabilities`) so the Console
|
|
6
|
+
* readiness assembly reuses the SAME implementation. This wrapper only
|
|
7
|
+
* resolves the built pd CLI entry for the CURRENT environment and fails
|
|
8
|
+
* closed (all capabilities not-verified) when it cannot.
|
|
9
|
+
*
|
|
10
|
+
* Evidence semantics (R4/P1): the CLI subprocess channel can prove
|
|
11
|
+
* `pd_status` and `rulecode_deactivate` (real `--dry-run` validation path —
|
|
12
|
+
* no audit write, no mutation); the console-channel capabilities are
|
|
13
|
+
* reported NOT-VERIFIED with the precise reason — never fabricated as ok.
|
|
14
|
+
*/
|
|
15
|
+
export { DEACTIVATE_DRY_RUN_PROBE_ACTIVATION_ID } from '@principles/host-runtime';
|
|
16
|
+
/**
|
|
17
|
+
* Probe the CLI-channel recovery capabilities against the target workspace.
|
|
18
|
+
* When `expectedActivationId` is supplied, pd_status additionally requires
|
|
19
|
+
* that activation to appear in the listing — proof the probe targeted the
|
|
20
|
+
* governed workspace, not merely some workspace.
|
|
21
|
+
*/
|
|
22
|
+
export declare function probeCliRecoveryReachability(workspaceDir: string, expectedActivationId?: string, options?: {
|
|
23
|
+
timeoutMs?: number;
|
|
24
|
+
}): Promise<RecoveryCapabilityEvidence[]>;
|
|
25
|
+
//# sourceMappingURL=recovery-reachability-probe.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recovery-reachability-probe.d.ts","sourceRoot":"","sources":["../../src/commands/recovery-reachability-probe.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AAE9E;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,sCAAsC,EAAE,MAAM,0BAA0B,CAAC;AAelF;;;;;GAKG;AACH,wBAAsB,4BAA4B,CAAC,YAAY,EAAE,MAAM,EAAE,oBAAoB,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,0BAA0B,EAAE,CAAC,CAW/K"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { probeCliRecoveryCapabilities } from '@principles/host-runtime';
|
|
5
|
+
/**
|
|
6
|
+
* SPEC-RULECODE-HOST-PROMOTION-001 R3/R4: CLI-channel recovery reachability
|
|
7
|
+
* for the pd-cli readiness path. Thin wrapper — the real subprocess probes
|
|
8
|
+
* live in host-runtime (`probeCliRecoveryCapabilities`) so the Console
|
|
9
|
+
* readiness assembly reuses the SAME implementation. This wrapper only
|
|
10
|
+
* resolves the built pd CLI entry for the CURRENT environment and fails
|
|
11
|
+
* closed (all capabilities not-verified) when it cannot.
|
|
12
|
+
*
|
|
13
|
+
* Evidence semantics (R4/P1): the CLI subprocess channel can prove
|
|
14
|
+
* `pd_status` and `rulecode_deactivate` (real `--dry-run` validation path —
|
|
15
|
+
* no audit write, no mutation); the console-channel capabilities are
|
|
16
|
+
* reported NOT-VERIFIED with the precise reason — never fabricated as ok.
|
|
17
|
+
*/
|
|
18
|
+
export { DEACTIVATE_DRY_RUN_PROBE_ACTIVATION_ID } from '@principles/host-runtime';
|
|
19
|
+
function resolveCliEntry() {
|
|
20
|
+
// Built layout: dist/commands/<this>.js with the entry at dist/index.js.
|
|
21
|
+
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
22
|
+
const candidates = [
|
|
23
|
+
path.resolve(here, '..', 'index.js'),
|
|
24
|
+
path.resolve(process.cwd(), 'dist', 'index.js'),
|
|
25
|
+
];
|
|
26
|
+
for (const candidate of candidates) {
|
|
27
|
+
if (existsSync(candidate))
|
|
28
|
+
return candidate;
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Probe the CLI-channel recovery capabilities against the target workspace.
|
|
34
|
+
* When `expectedActivationId` is supplied, pd_status additionally requires
|
|
35
|
+
* that activation to appear in the listing — proof the probe targeted the
|
|
36
|
+
* governed workspace, not merely some workspace.
|
|
37
|
+
*/
|
|
38
|
+
export async function probeCliRecoveryReachability(workspaceDir, expectedActivationId, options) {
|
|
39
|
+
const cliEntry = resolveCliEntry();
|
|
40
|
+
if (cliEntry === null) {
|
|
41
|
+
return [
|
|
42
|
+
{ capabilityId: 'pd_status', channel: 'cli', ok: false, workspaceMatched: false, detail: 'pd CLI entry not found (built entry missing in this environment)' },
|
|
43
|
+
{ capabilityId: 'rulecode_deactivate', channel: 'cli', ok: false, workspaceMatched: false, detail: 'pd CLI entry not found (built entry missing in this environment)' },
|
|
44
|
+
{ capabilityId: 'rulecode_global_pause', channel: 'console', ok: false, workspaceMatched: false, detail: 'console-channel control: verifying the HTTP-only recovery entry requires the Owner Console process; a CLI subprocess cannot produce this evidence' },
|
|
45
|
+
{ capabilityId: 'owner_review_access', channel: 'console', ok: false, workspaceMatched: false, detail: 'console-channel control: verifying the HTTP-only recovery entry requires the Owner Console process; a CLI subprocess cannot produce this evidence' },
|
|
46
|
+
];
|
|
47
|
+
}
|
|
48
|
+
return probeCliRecoveryCapabilities({ cliEntry, workspaceDir, ...(expectedActivationId !== undefined ? { expectedActivationId } : {}), ...(options?.timeoutMs !== undefined ? { timeoutMs: options.timeoutMs } : {}) });
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=recovery-reachability-probe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recovery-reachability-probe.js","sourceRoot":"","sources":["../../src/commands/recovery-reachability-probe.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,4BAA4B,EAAE,MAAM,0BAA0B,CAAC;AAGxE;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,sCAAsC,EAAE,MAAM,0BAA0B,CAAC;AAElF,SAAS,eAAe;IACtB,yEAAyE;IACzE,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1D,MAAM,UAAU,GAAG;QACjB,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,CAAC;QACpC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC;KAChD,CAAC;IACF,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,IAAI,UAAU,CAAC,SAAS,CAAC;YAAE,OAAO,SAAS,CAAC;IAC9C,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAAC,YAAoB,EAAE,oBAA6B,EAAE,OAAgC;IACtI,MAAM,QAAQ,GAAG,eAAe,EAAE,CAAC;IACnC,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;QACtB,OAAO;YACL,EAAE,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,EAAE,kEAAkE,EAAE;YAC7J,EAAE,YAAY,EAAE,qBAAqB,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,EAAE,kEAAkE,EAAE;YACvK,EAAE,YAAY,EAAE,uBAAuB,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,KAAK,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,EAAE,mJAAmJ,EAAE;YAC9P,EAAE,YAAY,EAAE,qBAAqB,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,KAAK,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,EAAE,mJAAmJ,EAAE;SAC7P,CAAC;IACJ,CAAC;IACD,OAAO,4BAA4B,CAAC,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,CAAC,oBAAoB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,oBAAoB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,OAAO,EAAE,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;AAC1N,CAAC"}
|
|
@@ -29,7 +29,7 @@ export interface CollectedRuleCodeEventEntries {
|
|
|
29
29
|
*/
|
|
30
30
|
export declare function collectRuleCodeEventEntries(workspaceDir: string): CollectedRuleCodeEventEntries;
|
|
31
31
|
/** Exported for PRI-577 regression tests and reuse by promote evidence assembly. */
|
|
32
|
-
export declare function readShadowSummaryForActivation(workspaceDir: string, activationId: string): PromotionEvidenceSnapshot['shadowSummary'];
|
|
32
|
+
export declare function readShadowSummaryForActivation(workspaceDir: string, activationId: string, targetHostKind?: string): PromotionEvidenceSnapshot['shadowSummary'];
|
|
33
33
|
interface ActivationDispatchOptions {
|
|
34
34
|
workspace?: string;
|
|
35
35
|
artifactId?: string;
|
|
@@ -44,6 +44,15 @@ interface ActivationDeactivateOptions {
|
|
|
44
44
|
activationId?: string;
|
|
45
45
|
reasonCode?: string;
|
|
46
46
|
json?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* SPEC-RULECODE-HOST-PROMOTION-001 R4/P1: non-destructive validation path
|
|
49
|
+
* for the recovery reachability probe. Runs the REAL entry through real
|
|
50
|
+
* parsing, workspace binding, and target-resolution preconditions, then
|
|
51
|
+
* returns BEFORE the governance audit write and BEFORE any store mutation.
|
|
52
|
+
* Mutually exclusive with an actual deactivation by construction: the
|
|
53
|
+
* dry-run branch never reaches the deactivate call.
|
|
54
|
+
*/
|
|
55
|
+
dryRun?: boolean;
|
|
47
56
|
}
|
|
48
57
|
export interface DeactivateResult {
|
|
49
58
|
ok: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime-activation.d.ts","sourceRoot":"","sources":["../../src/commands/runtime-activation.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAsEzC,OAAO,KAAK,EAA4C,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"runtime-activation.d.ts","sourceRoot":"","sources":["../../src/commands/runtime-activation.ts"],"names":[],"mappings":"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"}
|