create-principles-disciple 1.145.16 → 1.145.18
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 +2 -2
- package/codex-adapter/dist/worker/workspace-worker.js +2 -1
- package/codex-adapter/package.json +1 -1
- package/console/dist/server/index.js +12 -0
- package/console/dist/server/models/ActivationsConsoleModel.js +20 -2
- package/console/dist/server/models/ApprovalsConsoleModel.js +28 -4
- package/console/dist/server/models/ApprovalsGroupedConsoleModel.js +29 -3
- package/console/dist/server/routes/design-gate.d.ts +11 -0
- package/console/dist/server/routes/design-gate.js +156 -0
- package/console/dist/shared/prompt-injection-contract.d.ts +1 -1
- package/console/dist/ui/api.d.ts +29 -1
- package/console/dist/ui/api.js +105 -1
- package/console/dist/ui/i18n/en.json +48 -0
- package/console/dist/ui/i18n/zh-CN.json +48 -0
- package/console/dist/ui/pages/activation/ActivationPage.js +3 -1
- package/console/dist/ui/pages/control-center/ControlCenterPage.js +2 -1
- package/console/dist/ui/pages/control-center/DesignGatePanel.d.ts +1 -0
- package/console/dist/ui/pages/control-center/DesignGatePanel.js +137 -0
- package/console/dist/ui/pages/focus/FocusPage.js +19 -3
- package/console/dist/ui/utils/validators.js +1 -1
- package/console/dist/web/assets/app.css +6 -0
- package/console/dist/web/assets/app.js +30 -30
- package/core/dist/runtime-v2/activation/prompt-budget-policy.d.ts +14 -2
- package/core/dist/runtime-v2/activation/prompt-budget-policy.d.ts.map +1 -1
- package/core/dist/runtime-v2/activation/prompt-budget-policy.js +24 -2
- package/core/dist/runtime-v2/activation/prompt-budget-policy.js.map +1 -1
- package/core/dist/runtime-v2/config/index.d.ts +3 -3
- package/core/dist/runtime-v2/config/index.d.ts.map +1 -1
- package/core/dist/runtime-v2/config/index.js +3 -1
- package/core/dist/runtime-v2/config/index.js.map +1 -1
- package/core/dist/runtime-v2/config/pd-config-effective.d.ts +8 -1
- package/core/dist/runtime-v2/config/pd-config-effective.d.ts.map +1 -1
- package/core/dist/runtime-v2/config/pd-config-effective.js +10 -0
- package/core/dist/runtime-v2/config/pd-config-effective.js.map +1 -1
- package/core/dist/runtime-v2/config/pd-config-redaction.d.ts.map +1 -1
- package/core/dist/runtime-v2/config/pd-config-redaction.js +2 -0
- package/core/dist/runtime-v2/config/pd-config-redaction.js.map +1 -1
- package/core/dist/runtime-v2/config/pd-config-types.d.ts +39 -0
- package/core/dist/runtime-v2/config/pd-config-types.d.ts.map +1 -1
- package/core/dist/runtime-v2/config/pd-config-types.js +7 -0
- package/core/dist/runtime-v2/config/pd-config-types.js.map +1 -1
- package/core/dist/runtime-v2/config/pd-config-validate.d.ts.map +1 -1
- package/core/dist/runtime-v2/config/pd-config-validate.js +67 -1
- package/core/dist/runtime-v2/config/pd-config-validate.js.map +1 -1
- package/core/dist/runtime-v2/index.d.ts +5 -2
- package/core/dist/runtime-v2/index.d.ts.map +1 -1
- package/core/dist/runtime-v2/index.js +6 -1
- package/core/dist/runtime-v2/index.js.map +1 -1
- package/core/dist/runtime-v2/internalization/artificer-intent-preflight.d.ts +12 -0
- package/core/dist/runtime-v2/internalization/artificer-intent-preflight.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/artificer-intent-preflight.js +23 -0
- package/core/dist/runtime-v2/internalization/artificer-intent-preflight.js.map +1 -1
- package/core/dist/runtime-v2/internalization/artificer-prompt-builder.d.ts +1 -1
- package/core/dist/runtime-v2/internalization/artificer-prompt-builder.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/artificer-prompt-builder.js +15 -5
- package/core/dist/runtime-v2/internalization/artificer-prompt-builder.js.map +1 -1
- package/core/dist/runtime-v2/internalization/design-gate-facts.d.ts +54 -0
- package/core/dist/runtime-v2/internalization/design-gate-facts.d.ts.map +1 -0
- package/core/dist/runtime-v2/internalization/design-gate-facts.js +172 -0
- package/core/dist/runtime-v2/internalization/design-gate-facts.js.map +1 -0
- package/core/dist/runtime-v2/internalization/evaluator-prompt-builder.d.ts +8 -1
- package/core/dist/runtime-v2/internalization/evaluator-prompt-builder.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/evaluator-prompt-builder.js +73 -3
- package/core/dist/runtime-v2/internalization/evaluator-prompt-builder.js.map +1 -1
- package/core/dist/runtime-v2/internalization/evaluator-runner.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/evaluator-runner.js +64 -2
- package/core/dist/runtime-v2/internalization/evaluator-runner.js.map +1 -1
- package/core/dist/runtime-v2/internalization/rule-context-v2.d.ts +3 -0
- package/core/dist/runtime-v2/internalization/rule-context-v2.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/rule-context-v2.js +4 -0
- package/core/dist/runtime-v2/internalization/rule-context-v2.js.map +1 -1
- package/core/dist/runtime-v2/store/design-gate/sqlite-design-gate-store.d.ts +49 -0
- package/core/dist/runtime-v2/store/design-gate/sqlite-design-gate-store.d.ts.map +1 -0
- package/core/dist/runtime-v2/store/design-gate/sqlite-design-gate-store.js +274 -0
- package/core/dist/runtime-v2/store/design-gate/sqlite-design-gate-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 +31 -0
- package/core/dist/runtime-v2/store/sqlite-connection.js.map +1 -1
- package/core/dist/runtime-v2/types/event-types.d.ts +3 -3
- 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 +5 -1
- package/host-runtime/dist/codex-artificer-trusted-facts.d.ts +7 -0
- package/host-runtime/dist/codex-artificer-trusted-facts.js +17 -0
- package/host-runtime/dist/codex-rule-context-provider.js +82 -13
- package/host-runtime/dist/design-gate-facts.d.ts +37 -0
- package/host-runtime/dist/design-gate-facts.js +249 -0
- package/host-runtime/dist/index.d.ts +3 -0
- package/host-runtime/dist/index.js +20 -1
- package/host-runtime/dist/production-rulehost-gate.js +37 -1
- package/host-runtime/dist/prompt-injection-budget-observation.d.ts +10 -1
- package/host-runtime/dist/prompt-injection-budget-observation.js +21 -2
- package/host-runtime/dist/workspace-behavior-evidence.d.ts +9 -0
- package/host-runtime/dist/workspace-behavior-evidence.js +85 -0
- package/host-runtime/package.json +1 -1
- package/package.json +2 -2
- package/pd-cli/dist/commands/config-doctor.d.ts.map +1 -1
- package/pd-cli/dist/commands/config-doctor.js +18 -0
- package/pd-cli/dist/commands/config-doctor.js.map +1 -1
- package/pd-cli/dist/services/config-doctor.d.ts +9 -0
- package/pd-cli/dist/services/config-doctor.d.ts.map +1 -1
- package/pd-cli/dist/services/config-doctor.js +6 -0
- package/pd-cli/dist/services/config-doctor.js.map +1 -1
- package/plugin/dist/bundle.js +462 -432
- package/plugin/dist/governance-audit.js +1 -1
- package/plugin/dist/openclaw.plugin.json +1 -1
- package/plugin/dist/rulehost-evidence.js +24 -24
- package/plugin/openclaw.plugin.json +1 -1
- package/plugin/package.json +1 -1
- package/release-manager/package.json +2 -2
- package/workbuddy-adapter/package.json +1 -1
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
import fs from 'node:fs';
|
|
29
29
|
import path from 'node:path';
|
|
30
30
|
import { computeFeatureFlagsFromConfig, createRuntimeStateHandle, createPainSignalBridge, isRetryWaitBackoffElapsed, PrincipleTreeLedgerAdapter, resolveDiagnosticianCapability, } from '@principles/core/runtime-v2';
|
|
31
|
-
import { createWorkspaceBehaviorEvidencePort, loadPdConfigForPlugin, loadFeatureFlagFromConfig, reconcileGovernanceContinuation, runInternalizationConsumerCycle, saveHostToolDeclaration, } from '@principles/host-runtime';
|
|
31
|
+
import { createWorkspaceBehaviorEvidencePort, createCodexArtificerTrustedFactsPort, loadPdConfigForPlugin, loadFeatureFlagFromConfig, reconcileGovernanceContinuation, runInternalizationConsumerCycle, saveHostToolDeclaration, } from '@principles/host-runtime';
|
|
32
32
|
import { catchUpCodexIngestion } from '../ingestion/catch-up.js';
|
|
33
33
|
import { CODEX_TOOL_SEMANTIC_MAPPINGS, CODEX_TOOL_SEMANTICS } from '../tool-semantics.js';
|
|
34
34
|
const WORKER_OWNER = 'companion-worker';
|
|
@@ -407,6 +407,7 @@ export async function runCodexWorkspaceWorkerCycle(options) {
|
|
|
407
407
|
logger,
|
|
408
408
|
emitEvent,
|
|
409
409
|
behaviorEvidence: createWorkspaceBehaviorEvidencePort(workspaceDir, CODEX_TOOL_SEMANTICS),
|
|
410
|
+
trustedFacts: createCodexArtificerTrustedFactsPort(),
|
|
410
411
|
toolSemantics: CODEX_TOOL_SEMANTICS,
|
|
411
412
|
// PRI-741: artificer generation gets the Codex host projection
|
|
412
413
|
// (Bash/apply_patch — evidence-bound, intentionally sparse).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@principles/codex-adapter",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.12",
|
|
4
4
|
"description": "Codex CLI host adapter for Principles Disciple — implements HostAdapter interface for OpenAI Codex CLI's stdin/stdout JSON hook model (ADR-0020).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -23,6 +23,7 @@ import { handleApprovalsGroupedRoute, disposeApprovalsGroupedModels } from './ro
|
|
|
23
23
|
import { handleGovernanceRoute, handleGovernanceExperienceRoute, resolveOwnerConfigSnapshot, disposeGovernanceModels } from './routes/governance.js';
|
|
24
24
|
import { handleOwnerDecisionsRoute } from './routes/owner-decisions.js';
|
|
25
25
|
import { handleEvidenceOutcomesRoute } from './routes/evidence-outcomes.js';
|
|
26
|
+
import { handleDesignGateRoute } from './routes/design-gate.js';
|
|
26
27
|
import { handleOwnerDecisionInboxRoute, handleOwnerDecisionViewRoute, handleOwnerDecisionLibraryRoute, parseOwnerDecisionViewSubPath } from './routes/owner-decision.js';
|
|
27
28
|
import { handleOwnerIdentityRoute } from './routes/owner-identity.js';
|
|
28
29
|
import { handleEvidenceChainRoute, disposeEvidenceChainModels } from './routes/evidence-chain.js';
|
|
@@ -502,6 +503,17 @@ function handleRequest(services) {
|
|
|
502
503
|
}))(req, res);
|
|
503
504
|
return;
|
|
504
505
|
}
|
|
506
|
+
if (urlPath.startsWith('/api/v1/governance/design-gate/')) {
|
|
507
|
+
const identity = resolveOwnerIdentity(process.env, defaultOwnerIdentityHomeDir());
|
|
508
|
+
const { ownerId, credentialId } = identity;
|
|
509
|
+
asyncHandler(() => handleDesignGateRoute(req, res, {
|
|
510
|
+
workspaceDir: services.workspaceDir,
|
|
511
|
+
subPath: urlPath.slice('/api/v1/governance/design-gate'.length),
|
|
512
|
+
ownerIdentity: services.authConfig.isEnabled() && ownerId !== null && credentialId !== null
|
|
513
|
+
? { ownerId, credentialId } : null,
|
|
514
|
+
}))(req, res);
|
|
515
|
+
return;
|
|
516
|
+
}
|
|
505
517
|
// PRI-466/477: GET/POST/PUT /api/v1/intent (+ /init, /content sub-paths)
|
|
506
518
|
if (urlPath === '/api/v1/intent' || urlPath.startsWith('/api/v1/intent/')) {
|
|
507
519
|
const subPath = urlPath === '/api/v1/intent' ? '' : urlPath.slice('/api/v1/intent'.length);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { SqliteConnection, SqliteActivationStateStore, SqlitePIArtifactStore, extractPrincipleId, extractEvidenceRefs, PromotionReadinessReader, RuleHostWriter, createProductionGateDeps, SqliteActivationSafetyStore, isFeatureEnabled, RuleCodeOwnerDecisionService, collectOpenClawPromotionChecks, summarizeRuleCodeShadowEvents, buildPromotionEvidenceSnapshot, } from '@principles/core/runtime-v2';
|
|
2
|
-
import { resolvePromotionHostLiveness, resolveWorkspaceHostToolSemantics, readPromptActivationInjectionStatuses, runtimeBudgetObservationToResolution, selectConsoleRuntimeBudgetFacts, RUNTIME_BUDGET_OBSERVATION_STALE_REASON, RUNTIME_V2_EVENT_LOG_CANDIDATE_DIRS } from '@principles/host-runtime';
|
|
2
|
+
import { resolvePromotionHostLiveness, resolveWorkspaceHostToolSemantics, readPromptActivationInjectionStatuses, operatorDeclaredBudgetResolution, runtimeBudgetObservationToResolution, selectConsoleRuntimeBudgetFacts, RUNTIME_BUDGET_OBSERVATION_STALE_REASON, RUNTIME_V2_EVENT_LOG_CANDIDATE_DIRS } from '@principles/host-runtime';
|
|
3
|
+
import { PROMPT_BUDGET_HOST_KINDS } from '@principles/core/runtime-v2';
|
|
3
4
|
import { loadPdConfig, computeFlagsFromLoadResult } from '../config/pd-config-store.js';
|
|
4
5
|
import * as fs from 'node:fs';
|
|
5
6
|
import * as path from 'node:path';
|
|
@@ -332,6 +333,21 @@ export class ActivationsConsoleModel {
|
|
|
332
333
|
...(targetHost !== undefined ? { targetHost } : {}),
|
|
333
334
|
});
|
|
334
335
|
const perHostBudget = new Map([...budgetFacts.perHost].map(([hostKind, observation]) => [hostKind, runtimeBudgetObservationToResolution(observation)]));
|
|
336
|
+
// PRI-1020: hosts with no fresh observation fall back to the Owner's
|
|
337
|
+
// declared basis (.pd/config.yaml promptBudget), same as the grouped
|
|
338
|
+
// surface — observation wins when present.
|
|
339
|
+
const configLoad = loadPdConfig(this.workspaceDir);
|
|
340
|
+
const declaredConfig = configLoad.ok ? configLoad.effective.config.promptBudget : undefined;
|
|
341
|
+
const declaredHosts = new Set();
|
|
342
|
+
for (const hostKind of PROMPT_BUDGET_HOST_KINDS) {
|
|
343
|
+
if (perHostBudget.has(hostKind))
|
|
344
|
+
continue;
|
|
345
|
+
const declared = operatorDeclaredBudgetResolution(declaredConfig, hostKind);
|
|
346
|
+
if (declared !== undefined) {
|
|
347
|
+
perHostBudget.set(hostKind, declared);
|
|
348
|
+
declaredHosts.add(hostKind);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
335
351
|
const report = await readPromptActivationInjectionStatuses({
|
|
336
352
|
workspaceDir: this.workspaceDir,
|
|
337
353
|
...(targetHost !== undefined ? { targetHost } : {}),
|
|
@@ -342,9 +358,11 @@ export class ActivationsConsoleModel {
|
|
|
342
358
|
});
|
|
343
359
|
// The status report resolved the route internally; bind the observation
|
|
344
360
|
// to THAT host only. A stale observation is never presented as current.
|
|
361
|
+
// PRI-1020: nor when a declared basis actually backed the route — the
|
|
362
|
+
// stale marker would contradict the declared source label.
|
|
345
363
|
const decidedHost = report.route.status === 'confirmed' ? report.route.hostKind : undefined;
|
|
346
364
|
const usedObservation = decidedHost !== undefined ? budgetFacts.perHost.get(decidedHost) : undefined;
|
|
347
|
-
const staleObservation = decidedHost !== undefined && usedObservation === undefined
|
|
365
|
+
const staleObservation = decidedHost !== undefined && usedObservation === undefined && !declaredHosts.has(decidedHost)
|
|
348
366
|
? budgetFacts.stalePerHost.get(decidedHost)
|
|
349
367
|
: undefined;
|
|
350
368
|
promptInjectionRoute = {
|
|
@@ -3,7 +3,8 @@ import * as path from 'node:path';
|
|
|
3
3
|
import { SqliteConnection, SqliteApprovalQueueStore, SqliteActivationStateStore, SqlitePIArtifactStore, ActivationDispatcher, PromptWriter, DeferArchiveWriter, RuleHostWriter, createProductionGateDeps, ApprovalCompletionService, ApprovalQueue, mapConfidenceToLabel, isArtifactRevisionOf, detectPromptReplacementTarget, buildOwnerRevisionArtifact, PrincipleTreeLedgerAdapter, MVP_CHANNELS, } from '@principles/core/runtime-v2';
|
|
4
4
|
import { resolveLedgerPrincipleId } from './principle-id-resolution.js';
|
|
5
5
|
import { loadPdConfig, computeFlagsFromLoadResult } from '../config/pd-config-store.js';
|
|
6
|
-
import { resolveWorkspaceHostToolSemantics, checkPromptArtifactDeliverabilityById, resolveLivePromptInjectionProjection, runtimeBudgetObservationToResolution, selectConsoleRuntimeBudgetFacts, } from '@principles/host-runtime';
|
|
6
|
+
import { resolveWorkspaceHostToolSemantics, checkPromptArtifactDeliverabilityById, operatorDeclaredBudgetResolution, resolveLivePromptInjectionProjection, runtimeBudgetObservationToResolution, selectConsoleRuntimeBudgetFacts, } from '@principles/host-runtime';
|
|
7
|
+
import { PROMPT_BUDGET_HOST_KINDS } from '@principles/core/runtime-v2';
|
|
7
8
|
const MVP_PROVEN_CHANNELS = new Set(MVP_CHANNELS);
|
|
8
9
|
const EMPTY_STATS = { pending: 0, approved: 0, rejected: 0, cancelled: 0 };
|
|
9
10
|
function isMissingTableError(err) {
|
|
@@ -21,7 +22,7 @@ function isActivationSuccess(activation) {
|
|
|
21
22
|
* without its own basis lets one host's observation look like another host's
|
|
22
23
|
* confirmation.
|
|
23
24
|
*/
|
|
24
|
-
function describeBudgetBasis(hostKind, facts) {
|
|
25
|
+
function describeBudgetBasis(hostKind, facts, declared) {
|
|
25
26
|
const used = facts.perHost.get(hostKind);
|
|
26
27
|
if (used !== undefined) {
|
|
27
28
|
return used.capacityStatus === 'confirmed'
|
|
@@ -31,6 +32,11 @@ function describeBudgetBasis(hostKind, facts) {
|
|
|
31
32
|
// budget, not a host window — say so.
|
|
32
33
|
: `budget basis=runtime_observation_fallback (${hostKind}, runtime reason=${used.fallbackReason ?? 'unknown'}, observed at ${used.observedAt})`;
|
|
33
34
|
}
|
|
35
|
+
// PRI-1020: the Owner's declared window backing this forecast — name it as
|
|
36
|
+
// a declaration, never as a runtime fact.
|
|
37
|
+
if (declared !== undefined) {
|
|
38
|
+
return `budget basis=operator_declared (${hostKind}, context window declared as ${declared.contextWindowTokens ?? 'unknown'} tokens in .pd/config.yaml)`;
|
|
39
|
+
}
|
|
34
40
|
const stale = facts.stalePerHost.get(hostKind);
|
|
35
41
|
if (stale !== undefined) {
|
|
36
42
|
return `budget basis=fixed_fallback (the runtime budget observation for ${hostKind} is stale — older than 24h and NOT used as the current budget)`;
|
|
@@ -327,6 +333,11 @@ export class ApprovalsConsoleModel {
|
|
|
327
333
|
async checkPromptInjectionBudget(activationId, targetHost) {
|
|
328
334
|
let resolution;
|
|
329
335
|
let budgetFacts;
|
|
336
|
+
// PRI-1020: declared bases per host (Owner's promptBudget config), used
|
|
337
|
+
// when a host has no fresh runtime observation. Scoped here so the basis
|
|
338
|
+
// descriptions at the call sites below see the same facts the projection
|
|
339
|
+
// ran under.
|
|
340
|
+
let declaredBudgetByHost = new Map();
|
|
330
341
|
// PRI-1017: the post-approval forecast runs under the workspace's most
|
|
331
342
|
// recent runtime budget OBSERVATION for the target host (per-host for
|
|
332
343
|
// unconfirmed routes), so the warning describes the budget the last real
|
|
@@ -339,6 +350,19 @@ export class ApprovalsConsoleModel {
|
|
|
339
350
|
...(targetHost !== undefined ? { targetHost } : {}),
|
|
340
351
|
});
|
|
341
352
|
const perHostBudget = new Map([...budgetFacts.perHost].map(([hostKind, observation]) => [hostKind, runtimeBudgetObservationToResolution(observation)]));
|
|
353
|
+
// PRI-1020: no fresh observation ⇒ the Owner's declared basis, same as
|
|
354
|
+
// the grouped/activations surfaces; a fresh observation still wins.
|
|
355
|
+
const configLoad = loadPdConfig(this.workspaceDir);
|
|
356
|
+
const declaredConfig = configLoad.ok ? configLoad.effective.config.promptBudget : undefined;
|
|
357
|
+
for (const hostKind of PROMPT_BUDGET_HOST_KINDS) {
|
|
358
|
+
if (perHostBudget.has(hostKind))
|
|
359
|
+
continue;
|
|
360
|
+
const declared = operatorDeclaredBudgetResolution(declaredConfig, hostKind);
|
|
361
|
+
if (declared !== undefined) {
|
|
362
|
+
perHostBudget.set(hostKind, declared);
|
|
363
|
+
declaredBudgetByHost.set(hostKind, declared);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
342
366
|
resolution = await resolveLivePromptInjectionProjection({
|
|
343
367
|
workspaceDir: this.workspaceDir,
|
|
344
368
|
...(targetHost !== undefined ? { targetHost } : {}),
|
|
@@ -358,7 +382,7 @@ export class ApprovalsConsoleModel {
|
|
|
358
382
|
// Each per-host forecast ran under ITS OWN budget basis (observation,
|
|
359
383
|
// runtime fallback, stale fallback, or no observation) — the headline
|
|
360
384
|
// numbers must never imply a single host's confirmation covers them all.
|
|
361
|
-
return `injection_capacity_unconfirmed: the activation is committed but this workspace's effective injection route cannot be confirmed (${resolution.decision.unconfirmedReason ?? 'unknown reason'}); per-host forecasts: ${resolution.perHost.map((entry) => `${entry.hostKind}=${entry.projection.route} (${entry.projection.usedChars}c/${entry.projection.budget}c${entry.projection.truncated ? ', truncated' : ''}) ${describeBudgetBasis(entry.hostKind, budgetFacts)}`).join('; ')}. nextAction=${resolution.decision.nextAction ?? 'pass an explicit target host (openclaw|codex|workbuddy)'}`;
|
|
385
|
+
return `injection_capacity_unconfirmed: the activation is committed but this workspace's effective injection route cannot be confirmed (${resolution.decision.unconfirmedReason ?? 'unknown reason'}); per-host forecasts: ${resolution.perHost.map((entry) => `${entry.hostKind}=${entry.projection.route} (${entry.projection.usedChars}c/${entry.projection.budget}c${entry.projection.truncated ? ', truncated' : ''}) ${describeBudgetBasis(entry.hostKind, budgetFacts, declaredBudgetByHost.get(entry.hostKind))}`).join('; ')}. nextAction=${resolution.decision.nextAction ?? 'pass an explicit target host (openclaw|codex|workbuddy)'}`;
|
|
362
386
|
}
|
|
363
387
|
const { projection } = resolution;
|
|
364
388
|
if (projection.injectedActivationIds.includes(activationId)) {
|
|
@@ -367,7 +391,7 @@ export class ApprovalsConsoleModel {
|
|
|
367
391
|
// Never let a stale observation masquerade as the current budget in the
|
|
368
392
|
// warning: name the basis the forecast actually ran under.
|
|
369
393
|
const decidedHost = resolution.decision.hostKind;
|
|
370
|
-
const budgetBasisNote = decidedHost === undefined ? '' : ` ${describeBudgetBasis(decidedHost, budgetFacts)}`;
|
|
394
|
+
const budgetBasisNote = decidedHost === undefined ? '' : ` ${describeBudgetBasis(decidedHost, budgetFacts, declaredBudgetByHost.get(decidedHost))}`;
|
|
371
395
|
const projectionDetail = projection.warnings.length > 0 ? ` projection warnings: ${projection.warnings.join(' | ')}` : '';
|
|
372
396
|
// AC-02/R-A3: oversized is independent of `truncated` — say WHY first.
|
|
373
397
|
if (projection.oversizedActivationIds.includes(activationId)) {
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { SqliteConnection, SqliteApprovalQueueStore, SqlitePIArtifactStore, ApprovalQueue, RUNTIME_V2_PRINCIPLE_BUDGET, detectPromptReplacementTarget, SqliteActivationStateStore, } from '@principles/core/runtime-v2';
|
|
2
|
-
import { checkPromptArtifactDeliverability, resolveLivePromptInjectionProjection, RUNTIME_BUDGET_OBSERVATION_STALE_REASON, runtimeBudgetObservationToResolution, selectConsoleRuntimeBudgetFacts, } from '@principles/host-runtime';
|
|
2
|
+
import { checkPromptArtifactDeliverability, operatorDeclaredBudgetResolution, resolveLivePromptInjectionProjection, RUNTIME_BUDGET_OBSERVATION_STALE_REASON, runtimeBudgetObservationToResolution, selectConsoleRuntimeBudgetFacts, } from '@principles/host-runtime';
|
|
3
|
+
import { PROMPT_BUDGET_HOST_KINDS } from '@principles/core/runtime-v2';
|
|
3
4
|
import { loadLedger } from '@principles/core/principle-tree-ledger';
|
|
5
|
+
import { loadPdConfig } from '../config/pd-config-store.js';
|
|
4
6
|
import { createArtifactPrincipleResolutionDeps, resolveArtifactPrincipleId, } from './artifact-principle-resolver.js';
|
|
5
7
|
import * as fs from 'node:fs';
|
|
6
8
|
import * as path from 'node:path';
|
|
@@ -391,6 +393,23 @@ export class ApprovalsGroupedConsoleModel {
|
|
|
391
393
|
...(targetHost !== undefined ? { targetHost } : {}),
|
|
392
394
|
});
|
|
393
395
|
const perHostBudget = new Map([...facts.perHost].map(([hostKind, observation]) => [hostKind, runtimeBudgetObservationToResolution(observation)]));
|
|
396
|
+
// PRI-1020: a host with NO fresh runtime observation falls back to the
|
|
397
|
+
// Owner's declared basis (.pd/config.yaml promptBudget) instead of the
|
|
398
|
+
// fixed 2000 — resolved through the same tier-0 policy branch the real
|
|
399
|
+
// injection uses, so forecast and injection can never disagree. A fresh
|
|
400
|
+
// observation still wins (it is what the runtime actually did last).
|
|
401
|
+
const configLoad = loadPdConfig(this.workspaceDir);
|
|
402
|
+
const declaredConfig = configLoad.ok ? configLoad.effective.config.promptBudget : undefined;
|
|
403
|
+
const declaredHosts = new Set();
|
|
404
|
+
for (const hostKind of PROMPT_BUDGET_HOST_KINDS) {
|
|
405
|
+
if (perHostBudget.has(hostKind))
|
|
406
|
+
continue;
|
|
407
|
+
const declared = operatorDeclaredBudgetResolution(declaredConfig, hostKind);
|
|
408
|
+
if (declared !== undefined) {
|
|
409
|
+
perHostBudget.set(hostKind, declared);
|
|
410
|
+
declaredHosts.add(hostKind);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
394
413
|
const resolution = await resolveLivePromptInjectionProjection({
|
|
395
414
|
workspaceDir: this.workspaceDir,
|
|
396
415
|
...(targetHost !== undefined ? { targetHost } : {}),
|
|
@@ -424,7 +443,13 @@ export class ApprovalsGroupedConsoleModel {
|
|
|
424
443
|
nextAction: resolution.decision.nextAction ?? 'pass an explicit target host (openclaw|codex|workbuddy)',
|
|
425
444
|
perHost: resolution.perHost.map((entry) => {
|
|
426
445
|
const observation = facts.perHost.get(entry.hostKind);
|
|
427
|
-
|
|
446
|
+
// PRI-1020: the stale marker explains a FALLBACK that ignored a
|
|
447
|
+
// too-old observation; it must not contradict a declared basis
|
|
448
|
+
// that was actually used.
|
|
449
|
+
const declaredUsed = observation === undefined && declaredHosts.has(entry.hostKind);
|
|
450
|
+
const stale = observation === undefined && !declaredUsed
|
|
451
|
+
? facts.stalePerHost.get(entry.hostKind)
|
|
452
|
+
: undefined;
|
|
428
453
|
return {
|
|
429
454
|
hostKind: entry.hostKind,
|
|
430
455
|
route: entry.projection.route,
|
|
@@ -450,7 +475,8 @@ export class ApprovalsGroupedConsoleModel {
|
|
|
450
475
|
// to whichever host happens to appear first.
|
|
451
476
|
const decidedHost = resolution.decision.hostKind;
|
|
452
477
|
const usedObservation = decidedHost !== undefined ? facts.perHost.get(decidedHost) : undefined;
|
|
453
|
-
const
|
|
478
|
+
const declaredHeadlineUsed = decidedHost !== undefined && usedObservation === undefined && declaredHosts.has(decidedHost);
|
|
479
|
+
const staleObservation = decidedHost !== undefined && usedObservation === undefined && !declaredHeadlineUsed
|
|
454
480
|
? facts.stalePerHost.get(decidedHost)
|
|
455
481
|
: undefined;
|
|
456
482
|
return {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
+
export interface DesignGateRouteContext {
|
|
3
|
+
workspaceDir: string;
|
|
4
|
+
subPath: string;
|
|
5
|
+
ownerIdentity: {
|
|
6
|
+
ownerId: string;
|
|
7
|
+
credentialId: string;
|
|
8
|
+
} | null;
|
|
9
|
+
}
|
|
10
|
+
/** Authenticated Owner attestations; never treats a principle approval as a design decision. */
|
|
11
|
+
export declare function handleDesignGateRoute(req: IncomingMessage, res: ServerResponse, ctx: DesignGateRouteContext): Promise<void>;
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { createRuntimeStateHandle, SqliteDesignGateStore, DesignGateStoreError } from '@principles/core/runtime-v2';
|
|
4
|
+
import { listObservedDesignGateSessions, readDesignGateSpecSnapshot } from '@principles/host-runtime';
|
|
5
|
+
import { readBody } from '../utils/request.js';
|
|
6
|
+
import { sendSuccess, sendError, sendBadRequest, sendMethodNotAllowed } from '../utils/response.js';
|
|
7
|
+
function record(value) {
|
|
8
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
9
|
+
}
|
|
10
|
+
function text(value) {
|
|
11
|
+
return typeof value === 'string' && value.trim().length > 0 && value.length <= 4096;
|
|
12
|
+
}
|
|
13
|
+
function decision(value) {
|
|
14
|
+
return value === 'approved' || value === 'not_approved' || value === 'not_required';
|
|
15
|
+
}
|
|
16
|
+
function scope(value) {
|
|
17
|
+
return record(value) && Object.keys(value).every(key => key === 'paths' || key === 'actions')
|
|
18
|
+
&& Array.isArray(value.paths) && value.paths.length > 0 && value.paths.length <= 100
|
|
19
|
+
&& value.paths.every(p => text(p) && !/[*?[\]]/.test(p) && !path.isAbsolute(p) && !p.split(/[\\/]/).includes('..'))
|
|
20
|
+
&& Array.isArray(value.actions) && value.actions.length > 0 && value.actions.length <= 3
|
|
21
|
+
&& value.actions.every(a => a === 'read' || a === 'write' || a === 'execute');
|
|
22
|
+
}
|
|
23
|
+
function closedBody(value, keys) {
|
|
24
|
+
return record(value) && Object.keys(value).every(key => keys.includes(key));
|
|
25
|
+
}
|
|
26
|
+
/** Authenticated Owner attestations; never treats a principle approval as a design decision. */
|
|
27
|
+
export async function handleDesignGateRoute(req, res, ctx) {
|
|
28
|
+
if (!ctx.ownerIdentity) {
|
|
29
|
+
sendError(res, 403, 'owner_authentication_required', 'A verified Owner identity is required to read or change design declarations.');
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const url = new URL(req.url ?? '/', 'http://localhost');
|
|
33
|
+
if (req.method === 'GET' && ctx.subPath === '/sessions') {
|
|
34
|
+
try {
|
|
35
|
+
sendSuccess(res, { sessions: listObservedDesignGateSessions(ctx.workspaceDir) });
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
sendError(res, 503, 'session_source_unavailable', 'Observed Codex session data is unavailable.', { nextAction: 'Run a Codex session with PD observation enabled, then refresh.' });
|
|
39
|
+
}
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
if (req.method === 'GET' && ctx.subPath === '/declaration') {
|
|
43
|
+
const project = url.searchParams.get('projectWorkspacePath');
|
|
44
|
+
const session = url.searchParams.get('hostSessionId');
|
|
45
|
+
if (!text(project) || !text(session)) {
|
|
46
|
+
sendBadRequest(res, 'Project and native session are required.');
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
let declaration;
|
|
50
|
+
try {
|
|
51
|
+
const handle = await createRuntimeStateHandle({ workspaceDir: ctx.workspaceDir, readonly: true, bootstrapIfMissing: false });
|
|
52
|
+
try {
|
|
53
|
+
declaration = new SqliteDesignGateStore(handle.stateManager.connection).getLatestDeclaration(project, session);
|
|
54
|
+
}
|
|
55
|
+
finally {
|
|
56
|
+
await handle.close();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
sendError(res, 503, 'declaration_source_unavailable', 'The design declaration source could not be read.', {
|
|
61
|
+
nextAction: 'Restore or initialize the governance workspace state database, then refresh the declaration.',
|
|
62
|
+
});
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
sendSuccess(res, { declaration });
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (req.method !== 'POST') {
|
|
69
|
+
sendMethodNotAllowed(res);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
let raw;
|
|
73
|
+
try {
|
|
74
|
+
raw = JSON.parse(await readBody(req));
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
sendBadRequest(res, 'Request body must be valid JSON.');
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const create = ctx.subPath === '/declarations';
|
|
81
|
+
const mutate = /^\/declarations\/([^/]+)\/(decision|revoke)$/.exec(ctx.subPath);
|
|
82
|
+
if (!create && !mutate) {
|
|
83
|
+
sendError(res, 404, 'not_found', 'Unknown design declaration operation.');
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (create) {
|
|
87
|
+
if (!closedBody(raw, ['projectWorkspacePath', 'hostSessionId', 'specPath', 'scope', 'decision'])
|
|
88
|
+
|| !text(raw.projectWorkspacePath) || !text(raw.hostSessionId) || !text(raw.specPath)
|
|
89
|
+
|| !scope(raw.scope) || !decision(raw.decision)) {
|
|
90
|
+
sendBadRequest(res, 'Expected an observed project/session, SPEC path, explicit paths/actions and decision; identity fields are not accepted.');
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
else if (!closedBody(raw, mutate?.[2] === 'decision' ? ['expectedRevision', 'decision'] : ['expectedRevision'])
|
|
95
|
+
|| typeof raw.expectedRevision !== 'number' || !Number.isSafeInteger(raw.expectedRevision) || raw.expectedRevision < 1
|
|
96
|
+
|| (mutate?.[2] === 'decision' && !decision(raw.decision))) {
|
|
97
|
+
sendBadRequest(res, 'Expected the current revision and a valid decision.');
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
// All request validation/source checks precede any write transaction.
|
|
101
|
+
if (!record(raw)) {
|
|
102
|
+
sendBadRequest(res, 'Invalid declaration.');
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
try {
|
|
106
|
+
let createInput = null;
|
|
107
|
+
if (create && text(raw.projectWorkspacePath) && text(raw.hostSessionId) && text(raw.specPath) && scope(raw.scope) && decision(raw.decision)) {
|
|
108
|
+
const chosen = listObservedDesignGateSessions(ctx.workspaceDir).find(entry => entry.projectWorkspacePath === raw.projectWorkspacePath && entry.hostSessionId === raw.hostSessionId);
|
|
109
|
+
if (!chosen) {
|
|
110
|
+
sendError(res, 409, 'native_scope_unverified', 'Select a Codex session already observed by this workspace.');
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const snapshot = readDesignGateSpecSnapshot(chosen.projectWorkspacePath, path.resolve(chosen.projectWorkspacePath, raw.specPath));
|
|
114
|
+
createInput = { project: chosen.projectWorkspacePath, session: chosen.hostSessionId, specPath: snapshot.realPath, specDigest: snapshot.digest, scope: raw.scope, decision: raw.decision };
|
|
115
|
+
}
|
|
116
|
+
const handle = await createRuntimeStateHandle({ workspaceDir: ctx.workspaceDir, bootstrapIfMissing: false });
|
|
117
|
+
try {
|
|
118
|
+
const store = new SqliteDesignGateStore(handle.stateManager.connection);
|
|
119
|
+
const actor = ctx.ownerIdentity;
|
|
120
|
+
const decidedAt = new Date().toISOString();
|
|
121
|
+
if (createInput) {
|
|
122
|
+
sendSuccess(res, { declaration: store.createDeclaration({ sourceRef: randomUUID(), governanceWorkspacePath: path.resolve(ctx.workspaceDir), projectWorkspacePath: createInput.project, hostSessionId: createInput.session, taskRef: `codex:${createInput.session}`, specPath: createInput.specPath, specDigest: createInput.specDigest, scope: createInput.scope, decision: createInput.decision, actor, decidedAt }) });
|
|
123
|
+
}
|
|
124
|
+
else if (mutate && typeof raw.expectedRevision === 'number') {
|
|
125
|
+
const sourceRef = decodeURIComponent(mutate[1] ?? '');
|
|
126
|
+
if (mutate[2] === 'revoke')
|
|
127
|
+
sendSuccess(res, { declaration: store.revoke({ sourceRef, expectedRevision: raw.expectedRevision, actor, decidedAt }) });
|
|
128
|
+
else if (decision(raw.decision)) {
|
|
129
|
+
const existing = store.getDeclaration(sourceRef);
|
|
130
|
+
if (existing) {
|
|
131
|
+
const currentSpec = readDesignGateSpecSnapshot(existing.projectWorkspacePath, existing.specPath);
|
|
132
|
+
if (currentSpec.digest !== existing.specDigest) {
|
|
133
|
+
sendError(res, 409, 'design_gate_spec_changed', 'The bound SPEC changed after this declaration was recorded.', {
|
|
134
|
+
nextAction: 'Review the current SPEC and create a new declaration before changing its decision.',
|
|
135
|
+
});
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
sendSuccess(res, { declaration: store.updateDecision({ sourceRef, expectedRevision: raw.expectedRevision, decision: raw.decision, actor, decidedAt }) });
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
finally {
|
|
144
|
+
await handle.close();
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
if (error instanceof DesignGateStoreError) {
|
|
149
|
+
const status = error.code === 'invalid_input' ? 400 : error.code === 'not_found' ? 404 : error.code === 'corrupt_data' ? 503 : 409;
|
|
150
|
+
sendError(res, status, `design_gate_${error.code}`, error.message, { nextAction: 'Refresh the declaration before retrying; no previous record was overwritten.' });
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
sendError(res, 503, 'design_gate_source_unavailable', 'The SPEC, observed session or declaration source could not be verified.', { nextAction: 'Check that the SPEC is a readable file inside the observed project and refresh the session list.' });
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
export type PromptInjectionTargetHostName = 'openclaw' | 'codex' | 'workbuddy';
|
|
16
16
|
export type PromptInjectionRouteName = 'legacy_trim' | 'shared_render';
|
|
17
17
|
export type PromptInjectionBudgetScopeName = 'selected_lines' | 'full_directive_context';
|
|
18
|
-
export type PromptBudgetCapacitySourceWire = 'host_effective_window' | 'pi_catalog_exact' | 'legacy_fallback';
|
|
18
|
+
export type PromptBudgetCapacitySourceWire = 'operator_declared' | 'host_effective_window' | 'pi_catalog_exact' | 'legacy_fallback';
|
|
19
19
|
export type PromptBudgetCapacityStatusWire = 'confirmed' | 'unknown';
|
|
20
20
|
/**
|
|
21
21
|
* Bounded machine-readable fallback reason. Closed set mirroring the core
|
package/console/dist/ui/api.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ApiResponse } from "../types.js";
|
|
2
2
|
import type { OwnerDecisionsData, OwnerResolutionResultData, OwnerDecisionInboxData, OwnerDecisionLibraryData } from "./utils/validators.js";
|
|
3
|
+
import type { DesignGateAction, DesignGateDecision, DesignGateDeclaration, DesignGateScope } from "@principles/core/runtime-v2/internalization/design-gate-facts";
|
|
3
4
|
import type { GovernanceExperienceSnapshot, OwnerGovernanceView, OwnerDecisionViewCore } from '@principles/core/runtime-v2';
|
|
4
5
|
import type { OwnerIdentityViewData, OwnerIdentityRegisterData, OwnerIdentityUnregisterData } from "./utils/validators.js";
|
|
5
6
|
import type { FeedbackReportData, FeedbackDraftSummaryData, FeedbackDraftEnvelopeData, FeedbackChannelsData, FeedbackSubmitResultData, DeleteEnvelopeData, WorkspaceEntryData, RemovedEnvelopeData, SyncResultData, ConfigSummaryData, ConfigCatalogData, AgentBindingUpdateData, DefaultRuntimeUpdateData, RuntimeProfileMutationData, ReadinessCheckData, FeatureFlagUpdateData, OutputLanguageData, GovernanceQueueData, RecoveryResultData, FailedTaskDetailData, ActivationsData, DisableActivationData, LifecycleMetricsData, UpdateStatusData, UpdateHistoryData, ApplyUpdateResultData, UpdateRecoveryData, UpdateTransactionData, ApprovalRecordData, PrinciplesListData, CorePrinciplesData, ApprovalsGroupedData, EvidenceChainData, TrajectoryData, IntentSummaryData, IntentDecisionRecordData, IntentDecisionResultData, IntentDecisionSummaryData, FollowUpResponseData, IntentInitResultData, IntentSaveResultData, IntentRawContentData, IntentVersionData, RuleCodeOwnerReviewData, RuleCodeMutationData } from "./utils/validators.js";
|
|
@@ -343,7 +344,34 @@ export interface FollowUpPayload {
|
|
|
343
344
|
candidateId?: string;
|
|
344
345
|
}
|
|
345
346
|
declare function dispatchFollowUp(decisionId: string, payload: FollowUpPayload): Promise<ApiResponse<FollowUpResponseData>>;
|
|
346
|
-
export
|
|
347
|
+
export interface DesignGateObservedSession {
|
|
348
|
+
projectWorkspacePath: string;
|
|
349
|
+
hostSessionId: string;
|
|
350
|
+
}
|
|
351
|
+
export interface DesignGateDeclarationInput {
|
|
352
|
+
projectWorkspacePath: string;
|
|
353
|
+
hostSessionId: string;
|
|
354
|
+
specPath: string;
|
|
355
|
+
scope: DesignGateScope;
|
|
356
|
+
decision: DesignGateDecision;
|
|
357
|
+
}
|
|
358
|
+
declare function fetchDesignGateSessions(): Promise<ApiResponse<{
|
|
359
|
+
sessions: DesignGateObservedSession[];
|
|
360
|
+
}>>;
|
|
361
|
+
declare function fetchDesignGateDeclaration(projectWorkspacePath: string, hostSessionId: string): Promise<ApiResponse<{
|
|
362
|
+
declaration: DesignGateDeclaration | null;
|
|
363
|
+
}>>;
|
|
364
|
+
declare function createDesignGateDeclaration(input: DesignGateDeclarationInput): Promise<ApiResponse<{
|
|
365
|
+
declaration: DesignGateDeclaration | null;
|
|
366
|
+
}>>;
|
|
367
|
+
declare function updateDesignGateDecision(sourceRef: string, expectedRevision: number, decision: DesignGateDecision): Promise<ApiResponse<{
|
|
368
|
+
declaration: DesignGateDeclaration | null;
|
|
369
|
+
}>>;
|
|
370
|
+
declare function revokeDesignGateDeclaration(sourceRef: string, expectedRevision: number): Promise<ApiResponse<{
|
|
371
|
+
declaration: DesignGateDeclaration | null;
|
|
372
|
+
}>>;
|
|
373
|
+
export { request, getToken, setToken, clearToken, checkAuth, approveApproval, rejectApproval, editApproval, fetchPrinciples, fetchCorePrinciples, fetchPrincipleDetail, fetchPrincipleGovernance, fetchOwnerDecisionView, fetchOwnerDecisionInbox, fetchOwnerDecisionLibrary, fetchPrincipleTrajectory, fetchPrincipleReceipts, fetchReceiptCounts, fetchEvidenceAudit, archivePrinciple, unarchivePrinciple, createFeedbackReport, listFeedbackReports, getFeedbackReport, deleteFeedbackReport, fetchFeedbackChannels, submitFeedbackReport, markFeedbackReportSent, fetchConfigSummary, fetchConfigCatalog, updateAgentBinding, updateDefaultRuntime, createRuntimeProfile, updateRuntimeProfile, deleteRuntimeProfile, fetchAgentReadiness, patchFeatureFlag, fetchOutputLanguage, updateOutputLanguage, fetchWorkspaces, addWorkspace, removeWorkspace, syncWorkspace, fetchGovernanceQueue, fetchGovernanceExperience, recoverFailedTask, fetchFailedTaskDetail, fetchOwnerDecisions, resolveOwnerDecision, fetchApprovalsGrouped, fetchAllActivations, disableActivation, proposePromptRevision, fetchRuleCodeOwnerReview, ruleCodeDecision, pauseAllRuleCode, releaseRuleCodePause, fetchLifecycleMetrics, fetchUpdateStatus, fetchUpdateHistory, applyFullUpdate, fetchUpdateRecovery, fetchUpdateTransaction, fetchEvidenceChain, fetchIntentSummary, fetchIntentContent, createIntentTemplate, saveIntentContent, fetchIntentVersions, recordIntentDecision, listIntentDecisionsByPainId, listIntentDecisionsByTaskId, fetchIntentDecisionSummary, dispatchFollowUp, fetchDesignGateSessions, fetchDesignGateDeclaration, createDesignGateDeclaration, updateDesignGateDecision, revokeDesignGateDeclaration, };
|
|
374
|
+
export type { DesignGateAction, DesignGateDecision, DesignGateDeclaration, DesignGateScope };
|
|
347
375
|
export type { FeedbackReportData, FeedbackDraftSummaryData, FeedbackDraftEnvelopeData, FeedbackChannelsData, FeedbackSubmitResultData, DeleteEnvelopeData, WorkspaceEntryData, RemovedEnvelopeData, SyncResultData, ConfigSummaryData, ConfigCatalogData, AgentBindingUpdateData, DefaultRuntimeUpdateData, RuntimeProfileMutationData, ReadinessCheckData, FeatureFlagUpdateData, OutputLanguageData, GovernanceQueueData, RecoveryResultData, ActivationsData, DisableActivationData, RuleCodeOwnerReviewData, RuleCodeMutationData, FailedTaskDetailData, LifecycleMetricsData, UpdateStatusData, UpdateHistoryData, ApplyUpdateResultData, UpdateRecoveryData, ApprovalRecordData, PrinciplesListData, CorePrinciplesData, CorePrincipleData, ApprovalsGroupedData, EvidenceChainData, EvidenceChainRecordData, EvidenceChainStateData, TrajectoryData, TrajectoryStageData, IntentSummaryData, IntentSectionsData, IntentDocWarningData, IntentDecisionRecordData, IntentDecisionResultData, IntentDecisionSummaryData, FollowUpResponseData, LinkCandidateFollowUpData, GuideRulehostFollowUpData, GeneratePatchProposalFollowUpData, IntentVersionEntry, IntentVersionData, } from "./utils/validators.js";
|
|
348
376
|
export type { ActivationRecordData as ActivationRecord } from "./utils/validators.js";
|
|
349
377
|
export type { OwnerDecisionInboxData, OwnerDecisionLibraryData } from "./utils/validators.js";
|
package/console/dist/ui/api.js
CHANGED
|
@@ -891,9 +891,113 @@ async function dispatchFollowUp(decisionId, payload) {
|
|
|
891
891
|
body: JSON.stringify(payload),
|
|
892
892
|
}, validateFollowUpResponse);
|
|
893
893
|
}
|
|
894
|
+
function isDesignGateRecord(value) {
|
|
895
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
896
|
+
}
|
|
897
|
+
function validateDesignGateSessions(value) {
|
|
898
|
+
if (!isDesignGateRecord(value) || !Array.isArray(value.sessions))
|
|
899
|
+
return null;
|
|
900
|
+
const sessions = [];
|
|
901
|
+
for (const entry of value.sessions) {
|
|
902
|
+
if (!isDesignGateRecord(entry)
|
|
903
|
+
|| typeof entry.projectWorkspacePath !== "string" || entry.projectWorkspacePath.trim() === ""
|
|
904
|
+
|| typeof entry.hostSessionId !== "string" || entry.hostSessionId.trim() === "")
|
|
905
|
+
return null;
|
|
906
|
+
sessions.push({ projectWorkspacePath: entry.projectWorkspacePath, hostSessionId: entry.hostSessionId });
|
|
907
|
+
}
|
|
908
|
+
return { sessions };
|
|
909
|
+
}
|
|
910
|
+
function isDesignGateAction(value) {
|
|
911
|
+
return value === "read" || value === "write" || value === "execute";
|
|
912
|
+
}
|
|
913
|
+
function isDesignGateDecisionValue(value) {
|
|
914
|
+
return value === "approved" || value === "not_approved" || value === "not_required";
|
|
915
|
+
}
|
|
916
|
+
function isNonEmptyDesignGateString(value) {
|
|
917
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
918
|
+
}
|
|
919
|
+
function isDesignGateStringArray(value) {
|
|
920
|
+
if (!Array.isArray(value))
|
|
921
|
+
return false;
|
|
922
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
923
|
+
if (!Object.hasOwn(value, index) || !isNonEmptyDesignGateString(value[index]))
|
|
924
|
+
return false;
|
|
925
|
+
}
|
|
926
|
+
return true;
|
|
927
|
+
}
|
|
928
|
+
/**
|
|
929
|
+
* Field-by-field mirror of the server declaration contract (rc-1 style) —
|
|
930
|
+
* the browser bundle never runtime-imports the Node-oriented core barrel, so
|
|
931
|
+
* the wire format is re-validated locally; the server remains the authority.
|
|
932
|
+
*/
|
|
933
|
+
function isDesignGateDeclarationValue(value) {
|
|
934
|
+
if (!isDesignGateRecord(value))
|
|
935
|
+
return false;
|
|
936
|
+
if (!Object.hasOwn(value, "sourceRef") || !isNonEmptyDesignGateString(value.sourceRef))
|
|
937
|
+
return false;
|
|
938
|
+
if (!isNonEmptyDesignGateString(value.governanceWorkspacePath))
|
|
939
|
+
return false;
|
|
940
|
+
if (!isNonEmptyDesignGateString(value.projectWorkspacePath))
|
|
941
|
+
return false;
|
|
942
|
+
if (!isNonEmptyDesignGateString(value.hostSessionId))
|
|
943
|
+
return false;
|
|
944
|
+
if (!isNonEmptyDesignGateString(value.taskRef))
|
|
945
|
+
return false;
|
|
946
|
+
if (!isNonEmptyDesignGateString(value.specPath) || !isNonEmptyDesignGateString(value.specDigest))
|
|
947
|
+
return false;
|
|
948
|
+
if (!isDesignGateRecord(value.scope))
|
|
949
|
+
return false;
|
|
950
|
+
if (!Object.hasOwn(value.scope, "paths") || !Object.hasOwn(value.scope, "actions"))
|
|
951
|
+
return false;
|
|
952
|
+
if (!isDesignGateStringArray(value.scope.paths) || value.scope.paths.length === 0)
|
|
953
|
+
return false;
|
|
954
|
+
if (!Array.isArray(value.scope.actions) || value.scope.actions.length === 0)
|
|
955
|
+
return false;
|
|
956
|
+
for (let index = 0; index < value.scope.actions.length; index += 1) {
|
|
957
|
+
if (!Object.hasOwn(value.scope.actions, index) || !isDesignGateAction(value.scope.actions[index]))
|
|
958
|
+
return false;
|
|
959
|
+
}
|
|
960
|
+
if (!isDesignGateDecisionValue(value.decision))
|
|
961
|
+
return false;
|
|
962
|
+
if (typeof value.revision !== "number" || !Number.isSafeInteger(value.revision) || value.revision < 1)
|
|
963
|
+
return false;
|
|
964
|
+
if (typeof value.revoked !== "boolean")
|
|
965
|
+
return false;
|
|
966
|
+
if (!isDesignGateRecord(value.actor)
|
|
967
|
+
|| !Object.hasOwn(value.actor, "ownerId") || !Object.hasOwn(value.actor, "credentialId")
|
|
968
|
+
|| !isNonEmptyDesignGateString(value.actor.ownerId) || !isNonEmptyDesignGateString(value.actor.credentialId))
|
|
969
|
+
return false;
|
|
970
|
+
if (!isNonEmptyDesignGateString(value.decidedAt))
|
|
971
|
+
return false;
|
|
972
|
+
return true;
|
|
973
|
+
}
|
|
974
|
+
function validateDesignGateDeclarationEnvelope(value) {
|
|
975
|
+
if (!isDesignGateRecord(value) || !Object.hasOwn(value, "declaration"))
|
|
976
|
+
return null;
|
|
977
|
+
if (value.declaration === null)
|
|
978
|
+
return { declaration: null };
|
|
979
|
+
return isDesignGateDeclarationValue(value.declaration) ? { declaration: value.declaration } : null;
|
|
980
|
+
}
|
|
981
|
+
const designGateBasePath = "/api/v1/governance/design-gate";
|
|
982
|
+
async function fetchDesignGateSessions() {
|
|
983
|
+
return request(`${designGateBasePath}/sessions`, undefined, validateDesignGateSessions);
|
|
984
|
+
}
|
|
985
|
+
async function fetchDesignGateDeclaration(projectWorkspacePath, hostSessionId) {
|
|
986
|
+
const query = new URLSearchParams({ projectWorkspacePath, hostSessionId });
|
|
987
|
+
return request(`${designGateBasePath}/declaration?${query.toString()}`, undefined, validateDesignGateDeclarationEnvelope);
|
|
988
|
+
}
|
|
989
|
+
async function createDesignGateDeclaration(input) {
|
|
990
|
+
return request(`${designGateBasePath}/declarations`, { method: "POST", body: JSON.stringify(input) }, validateDesignGateDeclarationEnvelope);
|
|
991
|
+
}
|
|
992
|
+
async function updateDesignGateDecision(sourceRef, expectedRevision, decision) {
|
|
993
|
+
return request(`${designGateBasePath}/declarations/${encodeURIComponent(sourceRef)}/decision`, { method: "POST", body: JSON.stringify({ expectedRevision, decision }) }, validateDesignGateDeclarationEnvelope);
|
|
994
|
+
}
|
|
995
|
+
async function revokeDesignGateDeclaration(sourceRef, expectedRevision) {
|
|
996
|
+
return request(`${designGateBasePath}/declarations/${encodeURIComponent(sourceRef)}/revoke`, { method: "POST", body: JSON.stringify({ expectedRevision }) }, validateDesignGateDeclarationEnvelope);
|
|
997
|
+
}
|
|
894
998
|
// ── Exports ───────────────────────────────────────────────────────────────────
|
|
895
999
|
export { request,
|
|
896
1000
|
// auth
|
|
897
1001
|
getToken, setToken, clearToken, checkAuth, approveApproval, rejectApproval, editApproval, fetchPrinciples, fetchCorePrinciples, fetchPrincipleDetail, fetchPrincipleGovernance, fetchOwnerDecisionView, fetchOwnerDecisionInbox, fetchOwnerDecisionLibrary, fetchPrincipleTrajectory, fetchPrincipleReceipts, fetchReceiptCounts, fetchEvidenceAudit, archivePrinciple, unarchivePrinciple, createFeedbackReport, listFeedbackReports, getFeedbackReport, deleteFeedbackReport,
|
|
898
1002
|
// Feedback submit ladder (Slice 3, spec §8)
|
|
899
|
-
fetchFeedbackChannels, submitFeedbackReport, markFeedbackReportSent, fetchConfigSummary, fetchConfigCatalog, updateAgentBinding, updateDefaultRuntime, createRuntimeProfile, updateRuntimeProfile, deleteRuntimeProfile, fetchAgentReadiness, patchFeatureFlag, fetchOutputLanguage, updateOutputLanguage, fetchWorkspaces, addWorkspace, removeWorkspace, syncWorkspace, fetchGovernanceQueue, fetchGovernanceExperience, recoverFailedTask, fetchFailedTaskDetail, fetchOwnerDecisions, resolveOwnerDecision, fetchApprovalsGrouped, fetchAllActivations, disableActivation, proposePromptRevision, fetchRuleCodeOwnerReview, ruleCodeDecision, pauseAllRuleCode, releaseRuleCodePause, fetchLifecycleMetrics, fetchUpdateStatus, fetchUpdateHistory, applyFullUpdate, fetchUpdateRecovery, fetchUpdateTransaction, fetchEvidenceChain, fetchIntentSummary, fetchIntentContent, createIntentTemplate, saveIntentContent, fetchIntentVersions, recordIntentDecision, listIntentDecisionsByPainId, listIntentDecisionsByTaskId, fetchIntentDecisionSummary, dispatchFollowUp, };
|
|
1003
|
+
fetchFeedbackChannels, submitFeedbackReport, markFeedbackReportSent, fetchConfigSummary, fetchConfigCatalog, updateAgentBinding, updateDefaultRuntime, createRuntimeProfile, updateRuntimeProfile, deleteRuntimeProfile, fetchAgentReadiness, patchFeatureFlag, fetchOutputLanguage, updateOutputLanguage, fetchWorkspaces, addWorkspace, removeWorkspace, syncWorkspace, fetchGovernanceQueue, fetchGovernanceExperience, recoverFailedTask, fetchFailedTaskDetail, fetchOwnerDecisions, resolveOwnerDecision, fetchApprovalsGrouped, fetchAllActivations, disableActivation, proposePromptRevision, fetchRuleCodeOwnerReview, ruleCodeDecision, pauseAllRuleCode, releaseRuleCodePause, fetchLifecycleMetrics, fetchUpdateStatus, fetchUpdateHistory, applyFullUpdate, fetchUpdateRecovery, fetchUpdateTransaction, fetchEvidenceChain, fetchIntentSummary, fetchIntentContent, createIntentTemplate, saveIntentContent, fetchIntentVersions, recordIntentDecision, listIntentDecisionsByPainId, listIntentDecisionsByTaskId, fetchIntentDecisionSummary, dispatchFollowUp, fetchDesignGateSessions, fetchDesignGateDeclaration, createDesignGateDeclaration, updateDesignGateDecision, revokeDesignGateDeclaration, };
|