create-principles-disciple 1.145.17 → 1.145.19
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/README.md +15 -0
- package/_release/product-identity.json +1 -1
- package/codex-adapter/package.json +1 -1
- 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/shared/prompt-injection-contract.d.ts +1 -1
- package/console/dist/ui/i18n/en.json +4 -1
- package/console/dist/ui/i18n/zh-CN.json +4 -1
- package/console/dist/ui/pages/activation/ActivationPage.js +3 -1
- package/console/dist/ui/pages/control-center/ControlCenterPage.js +11 -1
- 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.js +16 -16
- 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 +2 -2
- package/core/dist/runtime-v2/index.d.ts.map +1 -1
- package/core/dist/runtime-v2/index.js +3 -1
- package/core/dist/runtime-v2/index.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 +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/installers/openclaw-host-installer.d.ts +4 -8
- package/dist/installers/openclaw-host-installer.d.ts.map +1 -1
- package/dist/installers/openclaw-host-installer.js +10 -84
- package/dist/installers/openclaw-host-installer.js.map +1 -1
- package/host-runtime/dist/index.js +17 -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/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/pd-cli/package.json +1 -1
- package/plugin/dist/bundle.js +417 -417
- package/plugin/dist/governance-audit.js +1 -1
- package/plugin/dist/openclaw.plugin.json +1 -1
- package/plugin/openclaw.plugin.json +1 -1
- package/plugin/package.json +1 -1
- package/release-manager/dist/index.d.ts.map +1 -1
- package/release-manager/dist/index.js +5 -1
- package/release-manager/dist/index.js.map +1 -1
- package/release-manager/dist/installers/openclaw-host-installer.d.ts +4 -8
- package/release-manager/dist/installers/openclaw-host-installer.d.ts.map +1 -1
- package/release-manager/dist/installers/openclaw-host-installer.js +10 -84
- package/release-manager/dist/installers/openclaw-host-installer.js.map +1 -1
- package/release-manager/package.json +2 -2
- package/workbuddy-adapter/package.json +1 -1
package/README.md
CHANGED
|
@@ -46,8 +46,23 @@ npx create-principles-disciple --yes --workspace "/path/to/workspace" --json
|
|
|
46
46
|
--non-interactive Skip prompts
|
|
47
47
|
--workspace <path> Workspace directory
|
|
48
48
|
--json Output result as JSON (implies non-interactive)
|
|
49
|
+
--provider <name> LLM provider for the pd.default runtime profile (openai/anthropic/deepseek)
|
|
50
|
+
--api-key-env <name> NAME of the env var holding your LLM API key. Requires --provider
|
|
51
|
+
--model <id> LLM model id (optional; the per-provider default applies when omitted)
|
|
52
|
+
--base-url <url> OpenAI-compatible custom endpoint (optional; env: PD_BASE_URL)
|
|
49
53
|
```
|
|
50
54
|
|
|
55
|
+
## LLM runtime profile — required before the internal agents can run
|
|
56
|
+
|
|
57
|
+
PD's internal agents (diagnostician, dreamer, scribe, artificer, signal collector) call the LLM
|
|
58
|
+
provider **you** configure. PD ships no keys, stores no key values, and `--api-key-env` names an
|
|
59
|
+
environment variable rather than carrying a secret.
|
|
60
|
+
|
|
61
|
+
`--yes` without `--provider` installs in evidence-only mode: pain signals are captured and kept,
|
|
62
|
+
but diagnosis does not run and no principle is proposed. The post-install summary says so, and at any
|
|
63
|
+
later time `pd config doctor --workspace "<path>"` names the missing field. Full operator walkthrough:
|
|
64
|
+
[`docs/runbooks/USER_GUIDE.md`](../../docs/runbooks/USER_GUIDE.md) — “Before You Start: Give PD an LLM”.
|
|
65
|
+
|
|
51
66
|
## Post-Install Verification
|
|
52
67
|
|
|
53
68
|
The installer automatically verifies the installation during setup:
|
|
@@ -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",
|
|
@@ -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 {
|
|
@@ -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
|
|
@@ -102,6 +102,7 @@
|
|
|
102
102
|
"promptCapacityListRoute": "list injection (billed on the selected lines)",
|
|
103
103
|
"promptCapacityPerHostEntry": "{{host}}: {{billing}} — {{used}}/{{budget}} chars{{full}}{{observed}}",
|
|
104
104
|
"promptCapacityPerHostFull": " (full)",
|
|
105
|
+
"promptCapacityPerHostDeclared": "(budget from the workspace config declaration)",
|
|
105
106
|
"promptCapacityPerHostObserved": " (budget from this host's most recent runtime observation at {{observedAt}})",
|
|
106
107
|
"promptCapacityViewAsHost": "View as {{host}}",
|
|
107
108
|
"promptCapacityClearHost": "Clear selection",
|
|
@@ -116,6 +117,8 @@
|
|
|
116
117
|
"promptBudgetFallbackObservedSuffix": "; the runtime's most recent observation was at {{observedAt}}",
|
|
117
118
|
"budgetCapacitySourceHostWindow": "host effective context window",
|
|
118
119
|
"budgetCapacitySourcePiCatalog": "exact model catalog match",
|
|
120
|
+
"budgetCapacitySourceOperatorDeclared": "workspace config declaration",
|
|
121
|
+
"budgetCapacitySourceOperatorDeclaredSuffix": ", source: workspace config declaration",
|
|
119
122
|
"budgetFallbackReason": {
|
|
120
123
|
"host_capacity_absent": "the host provided no context capacity fact",
|
|
121
124
|
"host_capacity_source_untrusted": "the host capacity source is untrusted",
|
|
@@ -1456,7 +1459,7 @@
|
|
|
1456
1459
|
"configDisabled": "All agents are disabled.",
|
|
1457
1460
|
"configErrors": "Configuration Errors",
|
|
1458
1461
|
"internalAgents": "Internal Agents",
|
|
1459
|
-
"internalAgentsDescription": "Each PD internal agent
|
|
1462
|
+
"internalAgentsDescription": "Each PD internal agent runs on the runtime profile you configure — provider, model, and the name of the environment variable holding your API key. Keys stay outside PD.",
|
|
1460
1463
|
"defaultRuntime": "Default Runtime",
|
|
1461
1464
|
"defaultRuntimeDescription": "The default runtime profile for agents without explicit overrides.",
|
|
1462
1465
|
"advancedDiagnostics": "Advanced Diagnostics",
|
|
@@ -102,6 +102,7 @@
|
|
|
102
102
|
"promptCapacityListRoute": "列表注入(按选中行计费)",
|
|
103
103
|
"promptCapacityPerHostEntry": "{{host}}:{{billing}} — {{used}}/{{budget}} 字符{{full}}{{observed}}",
|
|
104
104
|
"promptCapacityPerHostFull": "(已满)",
|
|
105
|
+
"promptCapacityPerHostDeclared": "(预算来自工作区配置声明)",
|
|
105
106
|
"promptCapacityPerHostObserved": "(预算来自该宿主最近一次运行时观测,观测于 {{observedAt}})",
|
|
106
107
|
"promptCapacityViewAsHost": "按 {{host}} 查看",
|
|
107
108
|
"promptCapacityClearHost": "清除选择",
|
|
@@ -116,6 +117,8 @@
|
|
|
116
117
|
"promptBudgetFallbackObservedSuffix": ";运行时最近一次观测于 {{observedAt}}",
|
|
117
118
|
"budgetCapacitySourceHostWindow": "宿主有效上下文窗口",
|
|
118
119
|
"budgetCapacitySourcePiCatalog": "模型目录精确匹配",
|
|
120
|
+
"budgetCapacitySourceOperatorDeclared": "工作区配置声明",
|
|
121
|
+
"budgetCapacitySourceOperatorDeclaredSuffix": ",来源: 工作区配置声明",
|
|
119
122
|
"budgetFallbackReason": {
|
|
120
123
|
"host_capacity_absent": "宿主未提供上下文容量事实",
|
|
121
124
|
"host_capacity_source_untrusted": "宿主容量来源不可信",
|
|
@@ -1456,7 +1459,7 @@
|
|
|
1456
1459
|
"configDisabled": "所有智能体已停用。",
|
|
1457
1460
|
"configErrors": "配置错误",
|
|
1458
1461
|
"internalAgents": "内部智能体",
|
|
1459
|
-
"internalAgentsDescription": "每个 PD
|
|
1462
|
+
"internalAgentsDescription": "每个 PD 内部智能体都运行在您配置的运行时配置上——provider、model,以及存放 API Key 的环境变量名。密钥本身留在 PD 之外。",
|
|
1460
1463
|
"defaultRuntime": "默认运行时",
|
|
1461
1464
|
"defaultRuntimeDescription": "未设置显式覆盖的智能体使用的默认运行时配置。",
|
|
1462
1465
|
"advancedDiagnostics": "高级诊断",
|
|
@@ -414,7 +414,9 @@ export function ActivationPage() {
|
|
|
414
414
|
defaultValue: "注入状态中的预算数字取自最近一次运行时观测(来源 {{source}},上下文 {{window}} tokens,观测于 {{observedAt}}),并非实时确认值。",
|
|
415
415
|
source: route.budgetCapacitySource === "pi_catalog_exact"
|
|
416
416
|
? t("pages.focus.budgetCapacitySourcePiCatalog", { defaultValue: "模型目录精确匹配" })
|
|
417
|
-
:
|
|
417
|
+
: route.budgetCapacitySource === "operator_declared"
|
|
418
|
+
? t("pages.focus.budgetCapacitySourceOperatorDeclared", { defaultValue: "工作区配置声明" })
|
|
419
|
+
: t("pages.focus.budgetCapacitySourceHostWindow", { defaultValue: "宿主有效上下文窗口" }),
|
|
418
420
|
window: route.budgetContextWindowTokens,
|
|
419
421
|
observedAt: route.budgetObservedAt,
|
|
420
422
|
}) }));
|
|
@@ -27,6 +27,14 @@ function validateSource(raw) {
|
|
|
27
27
|
function isRecord(value) {
|
|
28
28
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
29
29
|
}
|
|
30
|
+
// Overall readiness → the plain-language sentence shown under the internal-agents heading.
|
|
31
|
+
const CONFIG_READINESS_KEY = {
|
|
32
|
+
ready: "pages.controlCenter.configReady",
|
|
33
|
+
needs_setup: "pages.controlCenter.configNeedsSetup",
|
|
34
|
+
not_ready: "pages.controlCenter.configNotReady",
|
|
35
|
+
unknown: "pages.controlCenter.configUnknown",
|
|
36
|
+
disabled: "pages.controlCenter.configDisabled",
|
|
37
|
+
};
|
|
30
38
|
function validateReadinessStatus(raw) {
|
|
31
39
|
if (typeof raw !== "string")
|
|
32
40
|
return null;
|
|
@@ -486,7 +494,9 @@ export function ControlCenterPage() {
|
|
|
486
494
|
};
|
|
487
495
|
const overallReadiness = computeOverallReadiness(diagnostics);
|
|
488
496
|
const availableProfiles = catalogData?.profiles ?? configData.runtimeProfiles;
|
|
489
|
-
return (_jsx(PageShell, { children: _jsxs("div", { className: "animate-[pdFadeIn_400ms_ease-out]", children: [_jsx("div", { className: "font-mono text-[12px] tracking-[0.14em] text-ink-3 uppercase mb-3", children: t("pages.controlCenter.eyebrow") }), _jsx("h1", { className: "text-[29px] font-semibold tracking-tight text-ink mb-2", children: t("pages.controlCenter.title") }), _jsx("p", { className: "text-ink-3 text-[14px] max-w-[760px] leading-relaxed mb-7", children: t("pages.controlCenter.subtitle") }), _jsx(WorkflowDiagram, {}), _jsx(CompactStatusBar, { readiness: overallReadiness, agents: configData.agents }), _jsx(DesignGatePanel, {}), _jsxs("section", { className: "mt-8", "aria-labelledby": "section-agents", children: [_jsx(SectionTitle, { id: "section-agents", children: t("pages.controlCenter.internalAgents") }), _jsx("p", { className: "text-ink-3 text-[13px] leading-relaxed mb-3", children: t("pages.controlCenter.internalAgentsDescription") }), (
|
|
497
|
+
return (_jsx(PageShell, { children: _jsxs("div", { className: "animate-[pdFadeIn_400ms_ease-out]", children: [_jsx("div", { className: "font-mono text-[12px] tracking-[0.14em] text-ink-3 uppercase mb-3", children: t("pages.controlCenter.eyebrow") }), _jsx("h1", { className: "text-[29px] font-semibold tracking-tight text-ink mb-2", children: t("pages.controlCenter.title") }), _jsx("p", { className: "text-ink-3 text-[14px] max-w-[760px] leading-relaxed mb-7", children: t("pages.controlCenter.subtitle") }), _jsx(WorkflowDiagram, {}), _jsx(CompactStatusBar, { readiness: overallReadiness, agents: configData.agents }), _jsx(DesignGatePanel, {}), _jsxs("section", { className: "mt-8", "aria-labelledby": "section-agents", children: [_jsx(SectionTitle, { id: "section-agents", children: t("pages.controlCenter.internalAgents") }), _jsx("p", { className: "text-ink-3 text-[13px] leading-relaxed mb-3", children: t("pages.controlCenter.internalAgentsDescription") }), _jsx("p", { className: overallReadiness === "ready"
|
|
498
|
+
? "text-ink-4 text-[13px] leading-relaxed mb-3"
|
|
499
|
+
: "text-amber text-[13px] leading-relaxed mb-3", children: t(CONFIG_READINESS_KEY[overallReadiness]) }), (() => {
|
|
490
500
|
const { groups, unknown } = groupAgentsByDependency(configData.agents);
|
|
491
501
|
const locale = i18n.language.startsWith("en")
|
|
492
502
|
? "en"
|
|
@@ -441,15 +441,24 @@ function PendingReviewCard({ group, actionsLockedReason, onDecisionApplied, prom
|
|
|
441
441
|
// present a past observation as a live confirmation.
|
|
442
442
|
? t("pages.focus.promptBudgetObservedNote", {
|
|
443
443
|
defaultValue: "预算取自最近一次运行时观测(来源 {{source}},上下文 {{window}} tokens,观测于 {{observedAt}})",
|
|
444
|
+
// PRI-1020: three-way source label — the owner-declared
|
|
445
|
+
// basis reads as a declaration, never as a runtime fact.
|
|
444
446
|
source: promptInjection.budgetCapacitySource === "pi_catalog_exact"
|
|
445
447
|
? t("pages.focus.budgetCapacitySourcePiCatalog", { defaultValue: "模型目录精确匹配" })
|
|
446
|
-
:
|
|
448
|
+
: promptInjection.budgetCapacitySource === "operator_declared"
|
|
449
|
+
? t("pages.focus.budgetCapacitySourceOperatorDeclared", { defaultValue: "工作区配置声明" })
|
|
450
|
+
: t("pages.focus.budgetCapacitySourceHostWindow", { defaultValue: "宿主有效上下文窗口" }),
|
|
447
451
|
window: promptInjection.budgetContextWindowTokens,
|
|
448
452
|
observedAt: promptInjection.budgetObservedAt,
|
|
449
453
|
})
|
|
450
454
|
: t("pages.focus.promptBudgetModelAwareNote", {
|
|
451
|
-
defaultValue: "预算按已确认的模型上下文解析({{window}} tokens)",
|
|
455
|
+
defaultValue: "预算按已确认的模型上下文解析({{window}} tokens{{sourceSuffix}})",
|
|
452
456
|
window: promptInjection.budgetContextWindowTokens,
|
|
457
|
+
// PRI-1020: without an observation, a confirmed budget can
|
|
458
|
+
// only come from the Owner's declaration — say so.
|
|
459
|
+
sourceSuffix: promptInjection.budgetCapacitySource === "operator_declared"
|
|
460
|
+
? t("pages.focus.budgetCapacitySourceOperatorDeclaredSuffix", { defaultValue: ",来源: 工作区配置声明" })
|
|
461
|
+
: "",
|
|
453
462
|
})
|
|
454
463
|
: promptInjection.budgetObservedAt !== undefined
|
|
455
464
|
// PRI-1017: a fallback that still carries an observation
|
|
@@ -822,7 +831,14 @@ export function FocusPage({ featureFlags }) {
|
|
|
822
831
|
defaultValue: "(预算来自该宿主最近一次运行时观测,观测于 {{observedAt}})",
|
|
823
832
|
observedAt: entry.budgetObservedAt,
|
|
824
833
|
})
|
|
825
|
-
:
|
|
834
|
+
// PRI-1020: a declared basis is the Owner's own config
|
|
835
|
+
// fact — label it as a declaration, never as an
|
|
836
|
+
// observation.
|
|
837
|
+
: entry.budgetCapacitySource === "operator_declared"
|
|
838
|
+
? t("pages.focus.promptCapacityPerHostDeclared", {
|
|
839
|
+
defaultValue: "(预算来自工作区配置声明)",
|
|
840
|
+
})
|
|
841
|
+
: "",
|
|
826
842
|
}), entry.budgetFallbackReason !== undefined && (_jsxs("span", { "data-testid": `prompt-capacity-perhost-reason-${entry.hostKind}`, children: [" · ", t(`pages.focus.budgetFallbackReason.${entry.budgetFallbackReason}`, {
|
|
827
843
|
defaultValue: entry.budgetFallbackReason,
|
|
828
844
|
})] }))] }, entry.hostKind))) }), unconfirmed.nextAction !== undefined && (_jsx("p", { className: "mt-1 text-ink-2", children: unconfirmed.nextAction })), _jsxs("div", { className: "mt-2 flex gap-2", children: [["openclaw", "codex", "workbuddy"].map((host) => (_jsx("button", { type: "button", onClick: () => setPromptTargetHost(host), "data-testid": `prompt-capacity-pick-${host}`, className: `inline-flex items-center border rounded-[3px] px-[10px] py-[4px] transition-colors ${promptTargetHost === host ? "border-amber bg-amber/10" : "border-line hover:border-line-2"}`, children: t("pages.focus.promptCapacityViewAsHost", { host: host === "openclaw" ? "OpenClaw" : host === "workbuddy" ? "WorkBuddy" : "Codex" }) }, host))), promptTargetHost !== null && (_jsx("button", { type: "button", onClick: () => setPromptTargetHost(null), "data-testid": "prompt-capacity-pick-clear", className: "inline-flex items-center border border-line rounded-[3px] px-[10px] py-[4px] hover:border-line-2", children: t("pages.focus.promptCapacityClearHost", { defaultValue: "清除选择" }) }))] })] }));
|
|
@@ -85,7 +85,7 @@ function isPromptBudgetFallbackReason(value) {
|
|
|
85
85
|
return isString(value) && PROMPT_BUDGET_FALLBACK_REASONS.has(value);
|
|
86
86
|
}
|
|
87
87
|
function isPromptBudgetCapacitySource(value) {
|
|
88
|
-
return value === 'host_effective_window' || value === 'pi_catalog_exact' || value === 'legacy_fallback';
|
|
88
|
+
return value === 'operator_declared' || value === 'host_effective_window' || value === 'pi_catalog_exact' || value === 'legacy_fallback';
|
|
89
89
|
}
|
|
90
90
|
function isPromptBudgetCapacityStatus(value) {
|
|
91
91
|
return value === 'confirmed' || value === 'unknown';
|