create-principles-disciple 1.125.0 → 1.126.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/console/dist/server/config/pd-config-store.js +23 -11
- package/console/dist/server/index.js +8 -1
- package/console/dist/server/models/PrinciplesConsoleModel.d.ts +10 -0
- package/console/dist/server/models/PrinciplesConsoleModel.js +76 -29
- package/console/dist/server/routes/principles.d.ts +9 -0
- package/console/dist/server/routes/principles.js +46 -2
- package/console/dist/ui/App.js +2 -1
- package/console/dist/ui/api.d.ts +4 -3
- package/console/dist/ui/api.js +7 -2
- package/console/dist/ui/i18n/en.json +12 -0
- package/console/dist/ui/i18n/zh-CN.json +12 -0
- package/console/dist/ui/pages/principles/CorePrinciplesPage.d.ts +10 -0
- package/console/dist/ui/pages/principles/CorePrinciplesPage.js +59 -0
- package/console/dist/ui/pages/principles/PrinciplesPage.js +2 -1
- package/console/dist/ui/pages/principles/PrinciplesViewNav.d.ts +8 -0
- package/console/dist/ui/pages/principles/PrinciplesViewNav.js +15 -0
- package/console/dist/ui/utils/validators.d.ts +13 -0
- package/console/dist/ui/utils/validators.js +34 -0
- package/console/dist/web/assets/app.css +6 -0
- package/console/dist/web/assets/app.js +2148 -1962
- package/core/dist/runtime-v2/__tests__/adversarial-loop.test.js +14 -2
- package/core/dist/runtime-v2/__tests__/adversarial-loop.test.js.map +1 -1
- package/core/dist/runtime-v2/__tests__/artificer-runner-vslice.test.js +55 -1
- package/core/dist/runtime-v2/__tests__/artificer-runner-vslice.test.js.map +1 -1
- package/core/dist/runtime-v2/__tests__/evaluator-runner-vslice-v2.test.js +25 -7
- package/core/dist/runtime-v2/__tests__/evaluator-runner-vslice-v2.test.js.map +1 -1
- package/core/dist/runtime-v2/config/__tests__/pd-config-provenance.test.d.ts +24 -0
- package/core/dist/runtime-v2/config/__tests__/pd-config-provenance.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/config/__tests__/pd-config-provenance.test.js +208 -0
- package/core/dist/runtime-v2/config/__tests__/pd-config-provenance.test.js.map +1 -0
- package/core/dist/runtime-v2/config/index.d.ts +1 -1
- package/core/dist/runtime-v2/config/index.d.ts.map +1 -1
- package/core/dist/runtime-v2/config/index.js.map +1 -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 -2
- package/core/dist/runtime-v2/config/pd-config-effective.js.map +1 -1
- package/core/dist/runtime-v2/config/pd-config-feature-flags.d.ts +3 -1
- package/core/dist/runtime-v2/config/pd-config-feature-flags.d.ts.map +1 -1
- package/core/dist/runtime-v2/config/pd-config-feature-flags.js +2 -0
- package/core/dist/runtime-v2/config/pd-config-feature-flags.js.map +1 -1
- package/core/dist/runtime-v2/config/pd-config-types.d.ts +4 -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 +23 -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 +12 -1
- package/core/dist/runtime-v2/config/pd-config-validate.js.map +1 -1
- package/core/dist/runtime-v2/feature-flags/__tests__/installer-config-parity.test.js +4 -3
- package/core/dist/runtime-v2/feature-flags/__tests__/installer-config-parity.test.js.map +1 -1
- package/core/dist/runtime-v2/internalization/__tests__/evaluator-gate-authority.test.js +223 -1
- package/core/dist/runtime-v2/internalization/__tests__/evaluator-gate-authority.test.js.map +1 -1
- package/core/dist/runtime-v2/internalization/__tests__/owner-decision.test.js +41 -0
- package/core/dist/runtime-v2/internalization/__tests__/owner-decision.test.js.map +1 -1
- package/core/dist/runtime-v2/internalization/artificer-runner.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/artificer-runner.js +10 -0
- package/core/dist/runtime-v2/internalization/artificer-runner.js.map +1 -1
- package/core/dist/runtime-v2/internalization/evaluator-runner.d.ts +10 -0
- package/core/dist/runtime-v2/internalization/evaluator-runner.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/evaluator-runner.js +143 -23
- package/core/dist/runtime-v2/internalization/evaluator-runner.js.map +1 -1
- package/core/dist/runtime-v2/internalization/pitask-metadata.d.ts +12 -0
- package/core/dist/runtime-v2/internalization/pitask-metadata.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/pitask-metadata.js +15 -0
- package/core/dist/runtime-v2/internalization/pitask-metadata.js.map +1 -1
- package/core/dist/telemetry-event.d.ts +2 -2
- package/core/dist/telemetry-event.d.ts.map +1 -1
- package/core/dist/telemetry-event.js +6 -0
- package/core/dist/telemetry-event.js.map +1 -1
- package/dist/mvp-config.d.ts.map +1 -1
- package/dist/mvp-config.js +30 -20
- package/dist/mvp-config.js.map +1 -1
- package/package.json +1 -1
- package/pd-cli/dist/commands/runtime-init.d.ts.map +1 -1
- package/pd-cli/dist/commands/runtime-init.js +12 -1
- package/pd-cli/dist/commands/runtime-init.js.map +1 -1
- package/plugin/dist/bundle.js +390 -390
- package/plugin/dist/governance-audit.js +2 -2
- package/plugin/dist/rulehost-evidence.js +1 -1
|
@@ -312,11 +312,15 @@ export function updateAgentBinding(workspaceDir, agentName, payload) {
|
|
|
312
312
|
};
|
|
313
313
|
}
|
|
314
314
|
}
|
|
315
|
-
// Merge: start from raw config, overlay known sections, update internalAgents.agents
|
|
315
|
+
// Merge: start from raw config, overlay known sections, update internalAgents.agents.
|
|
316
|
+
// PRI-637: preserve the file's own `features:` section instead of re-writing
|
|
317
|
+
// the merged effective map. Defaults belong in the registry, not in config —
|
|
318
|
+
// snapshotting `effective.config.features` here would materialize every
|
|
319
|
+
// missing default flag into an immortal override on any agent-binding change.
|
|
316
320
|
const updatedConfig = {
|
|
317
321
|
...rawConfig,
|
|
318
322
|
version: effective.config.version,
|
|
319
|
-
features: { ...effective.config.features },
|
|
323
|
+
features: isRecord(rawConfig.features) ? rawConfig.features : { ...effective.config.features },
|
|
320
324
|
runtimeProfiles: { ...effective.config.runtimeProfiles },
|
|
321
325
|
internalAgents: {
|
|
322
326
|
defaultRuntime: effective.config.internalAgents.defaultRuntime,
|
|
@@ -434,11 +438,13 @@ export function updateDefaultRuntime(workspaceDir, payload) {
|
|
|
434
438
|
else {
|
|
435
439
|
// No agents in file — write nothing (all agents inherit default)
|
|
436
440
|
}
|
|
437
|
-
// Merge: update only defaultRuntime, preserve agent overrides
|
|
441
|
+
// Merge: update only defaultRuntime, preserve agent overrides.
|
|
442
|
+
// PRI-637: preserve the file's own `features:` section (same rationale as
|
|
443
|
+
// updateAgentBinding — never re-snapshot merged defaults into config).
|
|
438
444
|
const updatedConfig = {
|
|
439
445
|
...rawConfig,
|
|
440
446
|
version: effective.config.version,
|
|
441
|
-
features: { ...effective.config.features },
|
|
447
|
+
features: isRecord(rawConfig.features) ? rawConfig.features : { ...effective.config.features },
|
|
442
448
|
runtimeProfiles: { ...effective.config.runtimeProfiles },
|
|
443
449
|
internalAgents: {
|
|
444
450
|
defaultRuntime: defaultRuntimeRaw,
|
|
@@ -814,13 +820,14 @@ export function updateFeatureFlag(workspaceDir, featureName, enabled) {
|
|
|
814
820
|
// Use Object.hasOwn for untrusted key check (ERR-013).
|
|
815
821
|
let featuresSection;
|
|
816
822
|
if (!Object.hasOwn(rawConfig, 'features')) {
|
|
817
|
-
// Section absent —
|
|
818
|
-
//
|
|
819
|
-
//
|
|
823
|
+
// Section absent — create an EMPTY features map (PRI-637). Defaults belong
|
|
824
|
+
// in the registry, not in config: seeding the whole registered flag set here
|
|
825
|
+
// would materialize an immortal default snapshot on the first toggle of a
|
|
826
|
+
// fresh install. `features: {}` is fully valid — validatePdConfig only
|
|
827
|
+
// requires the key to be an object, and the effective config merges missing
|
|
828
|
+
// flags from DEFAULT_FEATURE_FLAGS at read time. Step 6 below then writes
|
|
829
|
+
// exactly one flag: the one the Owner toggled.
|
|
820
830
|
featuresSection = {};
|
|
821
|
-
for (const [flagId, flag] of Object.entries(_DEFAULT_FLAGS_RESULT.flags)) {
|
|
822
|
-
featuresSection[flagId] = { category: flag.category, enabled: flag.enabled };
|
|
823
|
-
}
|
|
824
831
|
rawConfig.features = featuresSection;
|
|
825
832
|
}
|
|
826
833
|
else if (isRecord(rawConfig.features)) {
|
|
@@ -865,7 +872,12 @@ export function updateFeatureFlag(workspaceDir, featureName, enabled) {
|
|
|
865
872
|
const category = (isRecord(existingEntry) && Object.hasOwn(existingEntry, 'category') && typeof existingEntry.category === 'string')
|
|
866
873
|
? existingEntry.category
|
|
867
874
|
: (DEFAULT_FLAG_CATEGORY.get(featureName) ?? 'quiet');
|
|
868
|
-
|
|
875
|
+
// PRI-637: the Console toggle is the canonical Owner action — an authenticated
|
|
876
|
+
// server writes this override under an explicit owner intent, so it records
|
|
877
|
+
// `source: 'owner'` (OWNER_PIN). This also upgrades a previously source-less
|
|
878
|
+
// LEGACY_UNKNOWN or system override: an explicit Owner action converts it to
|
|
879
|
+
// OWNER_PIN, which graduation must forever respect.
|
|
880
|
+
existingFeatures[featureName] = { category, enabled, source: 'owner' };
|
|
869
881
|
rawConfig.features = existingFeatures;
|
|
870
882
|
// 7. Validate the updated config before writing
|
|
871
883
|
const validation = validatePdConfig(rawConfig);
|
|
@@ -12,7 +12,7 @@ import { handleFeedbackReportsRoute, handleFeedbackChannelsRoute, disposeFeedbac
|
|
|
12
12
|
import { handleFailedTasksRoute, disposeFailedTasksModels } from './routes/failed-tasks.js';
|
|
13
13
|
import { handleApprovalsRoute, disposeApprovalsModels } from './routes/approvals.js';
|
|
14
14
|
import { handleHealthRoute, disposeHealthModels } from './routes/health.js';
|
|
15
|
-
import { handlePrinciplesRoute, disposePrinciplesModels } from './routes/principles.js';
|
|
15
|
+
import { handlePrinciplesRoute, handleCorePrinciplesRoute, disposePrinciplesModels } from './routes/principles.js';
|
|
16
16
|
import { handleLifecycleRoute, disposeLifecycleModels } from './routes/lifecycle.js';
|
|
17
17
|
import { handleActivationsRoute, disposeActivationsModels } from './routes/activations.js';
|
|
18
18
|
import { handleReceiptsRoute, disposeReceiptsModels } from './routes/receipts.js';
|
|
@@ -338,6 +338,13 @@ function handleRequest(services) {
|
|
|
338
338
|
asyncHandler(() => handleApprovalsRoute(req, res, services.workspaceDir, subPath))(req, res);
|
|
339
339
|
return;
|
|
340
340
|
}
|
|
341
|
+
// GET /api/principles/core — read-only PD Core Principles reference
|
|
342
|
+
// (MUST be before the /api/principles catch-all so "core" is not parsed
|
|
343
|
+
// as a principle id; the /api/v1/principles mount does not expose it.)
|
|
344
|
+
if (urlPath === '/api/principles/core') {
|
|
345
|
+
asyncHandler(() => handleCorePrinciplesRoute(req, res))(req, res);
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
341
348
|
// GET /api/principles, /api/principles/:id
|
|
342
349
|
if (urlPath === '/api/principles' || urlPath.startsWith('/api/principles/')) {
|
|
343
350
|
const subPath = urlPath.slice('/api/principles'.length);
|
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
import type { PrincipleStatus } from '@principles/core/runtime-v2';
|
|
2
2
|
export type { PrincipleStatus };
|
|
3
|
+
/** Core principle refused for a workspace governance mutation (archive/unarchive). */
|
|
4
|
+
export declare class ImmutableCorePrincipleError extends Error {
|
|
5
|
+
readonly principleId: string;
|
|
6
|
+
constructor(principleId: string);
|
|
7
|
+
}
|
|
8
|
+
/** Core principle refused from the ordinary Owner Principle detail flow. */
|
|
9
|
+
export declare class CorePrincipleNotGovernedError extends Error {
|
|
10
|
+
readonly principleId: string;
|
|
11
|
+
constructor(principleId: string);
|
|
12
|
+
}
|
|
3
13
|
export type PrinciplePriority = 'P0' | 'P1' | 'P2';
|
|
4
14
|
export type PrincipleScope = 'general' | 'domain';
|
|
5
15
|
export type PrincipleEvaluability = 'manual_only' | 'deterministic' | 'weak_heuristic';
|
|
@@ -2,6 +2,29 @@ import * as path from 'path';
|
|
|
2
2
|
import * as fs from 'fs';
|
|
3
3
|
import { classifyPrinciples, filterOwnerActionable } from './PrincipleClassifier.js';
|
|
4
4
|
import { updatePrinciple } from '@principles/core/principle-tree-ledger';
|
|
5
|
+
import { isCorePrincipleId } from '@principles/core/runtime-v2';
|
|
6
|
+
// ── PRI-641: Core principle boundary errors ─────────────────────────────────
|
|
7
|
+
// Core principles (registry T-01..T-10) are PD's built-in semantics, not
|
|
8
|
+
// workspace governance targets. Refusals must be distinguishable from storage
|
|
9
|
+
// failures (`false`), so they surface as typed errors at the model boundary.
|
|
10
|
+
/** Core principle refused for a workspace governance mutation (archive/unarchive). */
|
|
11
|
+
export class ImmutableCorePrincipleError extends Error {
|
|
12
|
+
principleId;
|
|
13
|
+
constructor(principleId) {
|
|
14
|
+
super(`Core principle "${principleId}" is built into Principles Disciple and cannot be modified through workspace governance.`);
|
|
15
|
+
this.name = 'ImmutableCorePrincipleError';
|
|
16
|
+
this.principleId = principleId;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/** Core principle refused from the ordinary Owner Principle detail flow. */
|
|
20
|
+
export class CorePrincipleNotGovernedError extends Error {
|
|
21
|
+
principleId;
|
|
22
|
+
constructor(principleId) {
|
|
23
|
+
super(`Core principle "${principleId}" is not owner-managed.`);
|
|
24
|
+
this.name = 'CorePrincipleNotGovernedError';
|
|
25
|
+
this.principleId = principleId;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
5
28
|
const VALID_STATUSES = ['candidate', 'active', 'archived', 'deprecated', 'probation'];
|
|
6
29
|
const VALID_PRIORITIES = ['P0', 'P1', 'P2'];
|
|
7
30
|
const VALID_SCOPES = ['general', 'domain'];
|
|
@@ -128,34 +151,9 @@ export class PrinciplesConsoleModel {
|
|
|
128
151
|
async listPrinciples(filter, decidedPrincipleIds, pendingApprovalPrincipleIds) {
|
|
129
152
|
const ledger = this.loadLedger();
|
|
130
153
|
const principles = Object.values(ledger.tree.principles);
|
|
131
|
-
const summary = {
|
|
132
|
-
candidate: 0,
|
|
133
|
-
probation: 0,
|
|
134
|
-
active: 0,
|
|
135
|
-
deprecated: 0,
|
|
136
|
-
archived: 0,
|
|
137
|
-
total: principles.length,
|
|
138
|
-
};
|
|
139
154
|
const items = [];
|
|
140
155
|
for (const p of principles) {
|
|
141
156
|
const status = safeCastEnum(p.status, VALID_STATUSES, 'candidate');
|
|
142
|
-
switch (status) {
|
|
143
|
-
case 'candidate':
|
|
144
|
-
summary.candidate++;
|
|
145
|
-
break;
|
|
146
|
-
case 'probation':
|
|
147
|
-
summary.probation++;
|
|
148
|
-
break;
|
|
149
|
-
case 'active':
|
|
150
|
-
summary.active++;
|
|
151
|
-
break;
|
|
152
|
-
case 'deprecated':
|
|
153
|
-
summary.deprecated++;
|
|
154
|
-
break;
|
|
155
|
-
case 'archived':
|
|
156
|
-
summary.archived++;
|
|
157
|
-
break;
|
|
158
|
-
}
|
|
159
157
|
const principleText = p.text ?? '';
|
|
160
158
|
const principleTrigger = p.triggerPattern ?? '';
|
|
161
159
|
items.push({
|
|
@@ -180,20 +178,61 @@ export class PrinciplesConsoleModel {
|
|
|
180
178
|
});
|
|
181
179
|
}
|
|
182
180
|
items.sort((a, b) => b.valueScore - a.valueScore);
|
|
183
|
-
// PRI-330: classify
|
|
181
|
+
// PRI-330 + PRI-641: classify first, then remove builtin from the corpus.
|
|
182
|
+
// The workspace projection is "workspace-governed principles only" —
|
|
183
|
+
// builtin axioms are PD's immutable semantics and never governance
|
|
184
|
+
// targets, so they must not reach lists, summary, or Debt consumers.
|
|
184
185
|
const classified = classifyPrinciples(items, decidedPrincipleIds, pendingApprovalPrincipleIds);
|
|
186
|
+
const workspaceClassified = classified.filter((c) => c.category !== 'builtin');
|
|
187
|
+
const workspaceItems = workspaceClassified.map((c) => c.principle);
|
|
188
|
+
// PRI-641: summary and categories are computed over the same workspace
|
|
189
|
+
// corpus the caller sees, so `principles[]` and `summary` can never
|
|
190
|
+
// disagree (no "list 3, total 13" projection).
|
|
191
|
+
const summary = {
|
|
192
|
+
candidate: 0,
|
|
193
|
+
probation: 0,
|
|
194
|
+
active: 0,
|
|
195
|
+
deprecated: 0,
|
|
196
|
+
archived: 0,
|
|
197
|
+
total: workspaceItems.length,
|
|
198
|
+
};
|
|
199
|
+
for (const p of workspaceItems) {
|
|
200
|
+
switch (p.status) {
|
|
201
|
+
case 'candidate':
|
|
202
|
+
summary.candidate++;
|
|
203
|
+
break;
|
|
204
|
+
case 'probation':
|
|
205
|
+
summary.probation++;
|
|
206
|
+
break;
|
|
207
|
+
case 'active':
|
|
208
|
+
summary.active++;
|
|
209
|
+
break;
|
|
210
|
+
case 'deprecated':
|
|
211
|
+
summary.deprecated++;
|
|
212
|
+
break;
|
|
213
|
+
case 'archived':
|
|
214
|
+
summary.archived++;
|
|
215
|
+
break;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
185
218
|
const categories = {};
|
|
186
|
-
for (const c of
|
|
219
|
+
for (const c of workspaceClassified) {
|
|
187
220
|
categories[c.category] = (categories[c.category] ?? 0) + 1;
|
|
188
221
|
}
|
|
189
|
-
let outputItems =
|
|
222
|
+
let outputItems = workspaceItems;
|
|
190
223
|
if (filter === 'actionable') {
|
|
191
|
-
const actionable = filterOwnerActionable(
|
|
224
|
+
const actionable = filterOwnerActionable(workspaceClassified);
|
|
192
225
|
outputItems = actionable.map((c) => c.principle);
|
|
193
226
|
}
|
|
194
227
|
return { principles: outputItems, summary, categories };
|
|
195
228
|
}
|
|
196
229
|
async getPrincipleDetail(principleId) {
|
|
230
|
+
// PRI-641: Core principles are not workspace-governed objects — they have
|
|
231
|
+
// no ordinary Owner detail (approvals/lifecycle/trajectory/receipts) and
|
|
232
|
+
// are viewed read-only via the Core Principles surface instead.
|
|
233
|
+
if (isCorePrincipleId(principleId)) {
|
|
234
|
+
throw new CorePrincipleNotGovernedError(principleId);
|
|
235
|
+
}
|
|
197
236
|
const ledger = this.loadLedger();
|
|
198
237
|
const p = ledger.tree.principles[principleId];
|
|
199
238
|
if (!p) {
|
|
@@ -247,6 +286,10 @@ export class PrinciplesConsoleModel {
|
|
|
247
286
|
return { principle };
|
|
248
287
|
}
|
|
249
288
|
async archivePrinciple(principleId) {
|
|
289
|
+
// PRI-641: refuse before any write — builtin axioms are immutable
|
|
290
|
+
if (isCorePrincipleId(principleId)) {
|
|
291
|
+
throw new ImmutableCorePrincipleError(principleId);
|
|
292
|
+
}
|
|
250
293
|
try {
|
|
251
294
|
const stateDir = path.join(this.workspaceDir, '.state');
|
|
252
295
|
updatePrinciple(stateDir, principleId, {
|
|
@@ -264,6 +307,10 @@ export class PrinciplesConsoleModel {
|
|
|
264
307
|
}
|
|
265
308
|
}
|
|
266
309
|
async unarchivePrinciple(principleId) {
|
|
310
|
+
// PRI-641: refuse before any write — builtin axioms are immutable
|
|
311
|
+
if (isCorePrincipleId(principleId)) {
|
|
312
|
+
throw new ImmutableCorePrincipleError(principleId);
|
|
313
|
+
}
|
|
267
314
|
try {
|
|
268
315
|
const stateDir = path.join(this.workspaceDir, '.state');
|
|
269
316
|
updatePrinciple(stateDir, principleId, {
|
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
+
/**
|
|
3
|
+
* GET /api/principles/core — read-only PD Core Principles reference (PRI-641).
|
|
4
|
+
*
|
|
5
|
+
* Served directly from the canonical `CORE_PRINCIPLES` registry (no ledger /
|
|
6
|
+
* DB read). Dispatched in server/index.ts BEFORE the `/api/principles`
|
|
7
|
+
* catch-all so `core` is never parsed as `/:id`; the `/api/v1/principles`
|
|
8
|
+
* mount intentionally does NOT expose this endpoint.
|
|
9
|
+
*/
|
|
10
|
+
export declare function handleCorePrinciplesRoute(req: IncomingMessage, res: ServerResponse): Promise<void>;
|
|
2
11
|
interface PrinciplesRouteParams {
|
|
3
12
|
req: IncomingMessage;
|
|
4
13
|
res: ServerResponse;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as path from 'path';
|
|
2
2
|
import * as fs from 'fs';
|
|
3
|
-
import { PrinciplesConsoleModel } from '../models/PrinciplesConsoleModel.js';
|
|
3
|
+
import { PrinciplesConsoleModel, ImmutableCorePrincipleError, CorePrincipleNotGovernedError, } from '../models/PrinciplesConsoleModel.js';
|
|
4
4
|
import { PrincipleTrajectoryModel } from '../models/PrincipleTrajectoryModel.js';
|
|
5
5
|
import { GovernanceProjectionCollector, GovernanceProjectionCollectionError } from '../models/GovernanceProjectionCollector.js';
|
|
6
|
-
import { OwnerGovernanceViewSchema, deriveOwnerGovernanceView } from '@principles/core/runtime-v2';
|
|
6
|
+
import { CORE_PRINCIPLES, OwnerGovernanceViewSchema, deriveOwnerGovernanceView } from '@principles/core/runtime-v2';
|
|
7
7
|
import { Value } from '@sinclair/typebox/value';
|
|
8
8
|
import { sendSuccess, sendError, sendNotFound } from '../utils/response.js';
|
|
9
9
|
const models = new Map();
|
|
@@ -16,6 +16,30 @@ function getModel(workspaceDir) {
|
|
|
16
16
|
}
|
|
17
17
|
return model;
|
|
18
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* GET /api/principles/core — read-only PD Core Principles reference (PRI-641).
|
|
21
|
+
*
|
|
22
|
+
* Served directly from the canonical `CORE_PRINCIPLES` registry (no ledger /
|
|
23
|
+
* DB read). Dispatched in server/index.ts BEFORE the `/api/principles`
|
|
24
|
+
* catch-all so `core` is never parsed as `/:id`; the `/api/v1/principles`
|
|
25
|
+
* mount intentionally does NOT expose this endpoint.
|
|
26
|
+
*/
|
|
27
|
+
export async function handleCorePrinciplesRoute(req, res) {
|
|
28
|
+
if (req.method !== 'GET') {
|
|
29
|
+
sendNotFound(res, `Route ${req.method} /api/principles/core not found`);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
sendSuccess(res, {
|
|
33
|
+
principles: CORE_PRINCIPLES.map((p) => ({
|
|
34
|
+
id: p.id,
|
|
35
|
+
layer: p.layer,
|
|
36
|
+
name: p.name,
|
|
37
|
+
nameZh: p.nameZh,
|
|
38
|
+
statement: p.statement,
|
|
39
|
+
statementZh: p.statementZh,
|
|
40
|
+
})),
|
|
41
|
+
});
|
|
42
|
+
}
|
|
19
43
|
/**
|
|
20
44
|
* Safely read an own string property from an unknown object.
|
|
21
45
|
* Returns the string value if the key exists and the value is a string,
|
|
@@ -153,6 +177,12 @@ export async function handlePrinciplesRoute({ req, res, workspaceDir, subPath, f
|
|
|
153
177
|
}
|
|
154
178
|
}
|
|
155
179
|
catch (err) {
|
|
180
|
+
if (err instanceof ImmutableCorePrincipleError) {
|
|
181
|
+
sendError(res, 403, 'immutable_core_principle', err.message, {
|
|
182
|
+
nextAction: 'View this principle under PD Core Principles.',
|
|
183
|
+
});
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
156
186
|
sendError(res, 500, 'archive_failed', err instanceof Error ? err.message : String(err));
|
|
157
187
|
}
|
|
158
188
|
return;
|
|
@@ -183,6 +213,12 @@ export async function handlePrinciplesRoute({ req, res, workspaceDir, subPath, f
|
|
|
183
213
|
}
|
|
184
214
|
}
|
|
185
215
|
catch (err) {
|
|
216
|
+
if (err instanceof ImmutableCorePrincipleError) {
|
|
217
|
+
sendError(res, 403, 'immutable_core_principle', err.message, {
|
|
218
|
+
nextAction: 'View this principle under PD Core Principles.',
|
|
219
|
+
});
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
186
222
|
sendError(res, 500, 'unarchive_failed', err instanceof Error ? err.message : String(err));
|
|
187
223
|
}
|
|
188
224
|
return;
|
|
@@ -264,6 +300,14 @@ export async function handlePrinciplesRoute({ req, res, workspaceDir, subPath, f
|
|
|
264
300
|
sendSuccess(res, result);
|
|
265
301
|
}
|
|
266
302
|
catch (err) {
|
|
303
|
+
if (err instanceof CorePrincipleNotGovernedError) {
|
|
304
|
+
// PRI-641: Core principles never enter the ordinary Owner detail flow
|
|
305
|
+
// (approvals/lifecycle/trajectory/receipts are workspace-governance data).
|
|
306
|
+
sendError(res, 404, 'core_principle_not_owner_managed', err.message, {
|
|
307
|
+
nextAction: 'View this principle under PD Core Principles.',
|
|
308
|
+
});
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
267
311
|
sendError(res, 500, 'principle_detail_error', err instanceof Error ? err.message : String(err));
|
|
268
312
|
}
|
|
269
313
|
return;
|
package/console/dist/ui/App.js
CHANGED
|
@@ -15,6 +15,7 @@ import { Toaster } from "./components/ui/sonner.js";
|
|
|
15
15
|
import { FocusPage } from "./pages/focus/FocusPage.js";
|
|
16
16
|
import { PainPage } from "./pages/pain/PainPage.js";
|
|
17
17
|
import { PrinciplesPage } from "./pages/principles/PrinciplesPage.js";
|
|
18
|
+
import { CorePrinciplesPage } from "./pages/principles/CorePrinciplesPage.js";
|
|
18
19
|
import { PrincipleDetailPage } from "./pages/principles/PrincipleDetailPage.js";
|
|
19
20
|
import { ActivationPage } from "./pages/activation/ActivationPage.js";
|
|
20
21
|
import { DebtPage } from "./pages/debt/DebtPage.js";
|
|
@@ -130,7 +131,7 @@ function AuthRoutes() {
|
|
|
130
131
|
}, []);
|
|
131
132
|
return (_jsxs(Routes, { children: [_jsx(Route, { path: "/splash", element: _jsx(SplashScreen, { onComplete: () => {
|
|
132
133
|
setShowSplash(false);
|
|
133
|
-
} }) }), _jsx(Route, { path: "/login", element: _jsx(LoginForm, { onAuthSuccess: handleAuthSuccess }) }), _jsx(Route, { path: "/*", element: authed === null ? (_jsx("div", { className: "min-h-screen bg-paper flex items-center justify-center", children: _jsxs("div", { className: "flex flex-col items-center gap-4", children: [_jsx("div", { className: "w-8 h-8 border-2 border-gov border-t-transparent rounded-full animate-spin" }), _jsx("span", { className: "text-[12px] font-mono tracking-wider text-ink-3 uppercase", children: "Verifying Session..." })] }) })) : authed ? (_jsx(NotificationProvider, { children: _jsxs("div", { className: "min-h-screen bg-paper text-ink", children: [_jsx("a", { href: "#main-content", className: "sr-only focus:not-sr-only focus:absolute focus:z-50 focus:p-4 focus:bg-paper focus:text-ink", children: "Skip to main content" }), _jsx(AppSidebar, { featureFlags: featureFlags ?? undefined }), _jsx("main", { id: "main-content", className: "ml-[256px] min-h-screen overflow-y-auto", children: _jsx(ErrorBoundary, { children: _jsxs(Routes, { children: [_jsx(Route, { path: "/", element: _jsx(Navigate, { to: "/focus", replace: true }) }), _jsx(Route, { path: "/welcome", element: _jsx(WelcomePage, { workspaceId: currentWorkspaceId }) }), _jsx(Route, { path: "/focus", element: _jsx(FocusPage, { featureFlags: featureFlags ?? undefined }) }), _jsx(Route, { path: "/pain", element: _jsx(PainPage, {}) }), _jsx(Route, { path: "/principles", element: _jsx(PrinciplesPage, {}) }), _jsx(Route, { path: "/principles/:id", element: _jsx(PrincipleDetailPage, {}) }), _jsx(Route, { path: "/activation", element: _jsx(ActivationPage, {}) }), _jsx(Route, { path: "/debt", element: _jsx(DebtPage, {}) }), _jsx(Route, { path: "/control-center", element: _jsx(ControlCenterPage, {}) }), _jsx(Route, { path: "/control-center/signal-keywords", element: _jsx(SignalKeywordsPage, {}) }), _jsx(Route, { path: "/settings", element: _jsx(SettingsPage, {}) }), _jsx(Route, { path: "/update", element: _jsx(UpdatePage, {}) }), _jsx(Route, { path: "/report-problem", element: _jsx(ReportProblemPage, {}) }), _jsx(Route, { path: "/failed-tasks", element: _jsx(FailedTasksPage, {}) }), _jsx(Route, { path: "/intent", element: _jsx(IntentPage, {}) }), IS_DEV && (_jsx(Route, { path: "/design-system", element: _jsx(DesignSystemPage, {}) })), !IS_DEV && (_jsx(Route, { path: "/design-system", element: _jsx(Navigate, { to: "/focus", replace: true }) }))] }) }) })] }) })) : (_jsx(Navigate, { to: "/login", replace: true })) })] }));
|
|
134
|
+
} }) }), _jsx(Route, { path: "/login", element: _jsx(LoginForm, { onAuthSuccess: handleAuthSuccess }) }), _jsx(Route, { path: "/*", element: authed === null ? (_jsx("div", { className: "min-h-screen bg-paper flex items-center justify-center", children: _jsxs("div", { className: "flex flex-col items-center gap-4", children: [_jsx("div", { className: "w-8 h-8 border-2 border-gov border-t-transparent rounded-full animate-spin" }), _jsx("span", { className: "text-[12px] font-mono tracking-wider text-ink-3 uppercase", children: "Verifying Session..." })] }) })) : authed ? (_jsx(NotificationProvider, { children: _jsxs("div", { className: "min-h-screen bg-paper text-ink", children: [_jsx("a", { href: "#main-content", className: "sr-only focus:not-sr-only focus:absolute focus:z-50 focus:p-4 focus:bg-paper focus:text-ink", children: "Skip to main content" }), _jsx(AppSidebar, { featureFlags: featureFlags ?? undefined }), _jsx("main", { id: "main-content", className: "ml-[256px] min-h-screen overflow-y-auto", children: _jsx(ErrorBoundary, { children: _jsxs(Routes, { children: [_jsx(Route, { path: "/", element: _jsx(Navigate, { to: "/focus", replace: true }) }), _jsx(Route, { path: "/welcome", element: _jsx(WelcomePage, { workspaceId: currentWorkspaceId }) }), _jsx(Route, { path: "/focus", element: _jsx(FocusPage, { featureFlags: featureFlags ?? undefined }) }), _jsx(Route, { path: "/pain", element: _jsx(PainPage, {}) }), _jsx(Route, { path: "/principles", element: _jsx(PrinciplesPage, {}) }), _jsx(Route, { path: "/principles/core", element: _jsx(CorePrinciplesPage, {}) }), _jsx(Route, { path: "/principles/:id", element: _jsx(PrincipleDetailPage, {}) }), _jsx(Route, { path: "/activation", element: _jsx(ActivationPage, {}) }), _jsx(Route, { path: "/debt", element: _jsx(DebtPage, {}) }), _jsx(Route, { path: "/control-center", element: _jsx(ControlCenterPage, {}) }), _jsx(Route, { path: "/control-center/signal-keywords", element: _jsx(SignalKeywordsPage, {}) }), _jsx(Route, { path: "/settings", element: _jsx(SettingsPage, {}) }), _jsx(Route, { path: "/update", element: _jsx(UpdatePage, {}) }), _jsx(Route, { path: "/report-problem", element: _jsx(ReportProblemPage, {}) }), _jsx(Route, { path: "/failed-tasks", element: _jsx(FailedTasksPage, {}) }), _jsx(Route, { path: "/intent", element: _jsx(IntentPage, {}) }), IS_DEV && (_jsx(Route, { path: "/design-system", element: _jsx(DesignSystemPage, {}) })), !IS_DEV && (_jsx(Route, { path: "/design-system", element: _jsx(Navigate, { to: "/focus", replace: true }) }))] }) }) })] }) })) : (_jsx(Navigate, { to: "/login", replace: true })) })] }));
|
|
134
135
|
}
|
|
135
136
|
export function App() {
|
|
136
137
|
return (_jsx(ThemeProvider, { children: _jsxs(I18nextProvider, { i18n: i18n, children: [_jsx(HashRouter, { children: _jsx(AuthRoutes, {}) }), _jsx(Toaster, {})] }) }));
|
package/console/dist/ui/api.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { OwnerDecisionsData, OwnerResolutionResultData } from "./utils/vali
|
|
|
3
3
|
import { listActiveSignalKeywords, listPendingSignalTerms, fetchKeywordStore, fetchPendingTerms, updateKeywordStore, admitPendingTerm, rejectPendingTerm } from "./utils/signal-keywords-api.js";
|
|
4
4
|
import type { GovernanceExperienceSnapshot, OwnerGovernanceView } from '@principles/core/runtime-v2';
|
|
5
5
|
import type { OwnerIdentityViewData, OwnerIdentityRegisterData, OwnerIdentityUnregisterData } from "./utils/validators.js";
|
|
6
|
-
import type { FeedbackReportData, FeedbackDraftSummaryData, FeedbackDraftEnvelopeData, FeedbackChannelsData, FeedbackSubmitResultData, DeleteEnvelopeData, WorkspaceEntryData, RemovedEnvelopeData, SyncResultData, ConfigSummaryData, ConfigCatalogData, AgentBindingUpdateData, DefaultRuntimeUpdateData, RuntimeProfileMutationData, ReadinessCheckData, FeatureFlagUpdateData, OutputLanguageData, GovernanceQueueData, RecoveryResultData, ActivationsData, DisableActivationData, LifecycleMetricsData, UpdateStatusData, UpdateHistoryData, ApplyUpdateResultData, RollbackResultData, ApprovalRecordData, PrinciplesListData, ApprovalsGroupedData, EvidenceChainData, TrajectoryData, IntentSummaryData, IntentDecisionRecordData, IntentDecisionResultData, IntentDecisionSummaryData, FollowUpResponseData, IntentInitResultData, IntentSaveResultData, IntentRawContentData, IntentVersionData, RuleCodeOwnerReviewData, RuleCodeMutationData } from "./utils/validators.js";
|
|
6
|
+
import type { FeedbackReportData, FeedbackDraftSummaryData, FeedbackDraftEnvelopeData, FeedbackChannelsData, FeedbackSubmitResultData, DeleteEnvelopeData, WorkspaceEntryData, RemovedEnvelopeData, SyncResultData, ConfigSummaryData, ConfigCatalogData, AgentBindingUpdateData, DefaultRuntimeUpdateData, RuntimeProfileMutationData, ReadinessCheckData, FeatureFlagUpdateData, OutputLanguageData, GovernanceQueueData, RecoveryResultData, ActivationsData, DisableActivationData, LifecycleMetricsData, UpdateStatusData, UpdateHistoryData, ApplyUpdateResultData, RollbackResultData, ApprovalRecordData, PrinciplesListData, CorePrinciplesData, ApprovalsGroupedData, EvidenceChainData, TrajectoryData, IntentSummaryData, IntentDecisionRecordData, IntentDecisionResultData, IntentDecisionSummaryData, FollowUpResponseData, IntentInitResultData, IntentSaveResultData, IntentRawContentData, IntentVersionData, RuleCodeOwnerReviewData, RuleCodeMutationData } from "./utils/validators.js";
|
|
7
7
|
declare function getToken(): string | null;
|
|
8
8
|
declare function setToken(token: string): void;
|
|
9
9
|
declare function clearToken(): void;
|
|
@@ -27,6 +27,7 @@ declare function addWorkspace(name: string, path: string): Promise<ApiResponse<W
|
|
|
27
27
|
declare function removeWorkspace(name: string): Promise<ApiResponse<RemovedEnvelopeData>>;
|
|
28
28
|
declare function syncWorkspace(name: string): Promise<ApiResponse<SyncResultData>>;
|
|
29
29
|
declare function fetchPrinciples(filter?: 'all' | 'actionable'): Promise<ApiResponse<PrinciplesListData>>;
|
|
30
|
+
declare function fetchCorePrinciples(): Promise<ApiResponse<CorePrinciplesData>>;
|
|
30
31
|
declare function fetchPrincipleDetail(principleId: string): Promise<ApiResponse<unknown>>;
|
|
31
32
|
declare function fetchPrincipleGovernance(principleId: string): Promise<ApiResponse<OwnerGovernanceView>>;
|
|
32
33
|
declare function archivePrinciple(principleId: string): Promise<ApiResponse<unknown>>;
|
|
@@ -230,8 +231,8 @@ export interface FollowUpPayload {
|
|
|
230
231
|
candidateId?: string;
|
|
231
232
|
}
|
|
232
233
|
declare function dispatchFollowUp(decisionId: string, payload: FollowUpPayload): Promise<ApiResponse<FollowUpResponseData>>;
|
|
233
|
-
export { request, listActiveSignalKeywords, listPendingSignalTerms, fetchKeywordStore, fetchPendingTerms, updateKeywordStore, admitPendingTerm, rejectPendingTerm, getToken, setToken, clearToken, checkAuth, approveApproval, rejectApproval, editApproval, fetchPrinciples, fetchPrincipleDetail, fetchPrincipleGovernance, fetchPrincipleTrajectory, fetchPrincipleReceipts, fetchReceiptCounts, 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, fetchOwnerDecisions, resolveOwnerDecision, fetchApprovalsGrouped, fetchAllActivations, disableActivation, fetchRuleCodeOwnerReview, ruleCodeDecision, pauseAllRuleCode, releaseRuleCodePause, fetchLifecycleMetrics, fetchUpdateStatus, fetchUpdateHistory, applyUpdate, applyFullUpdate, rollbackUpdate, fetchEvidenceChain, fetchIntentSummary, fetchIntentContent, createIntentTemplate, saveIntentContent, fetchIntentVersions, recordIntentDecision, listIntentDecisionsByPainId, listIntentDecisionsByTaskId, fetchIntentDecisionSummary, dispatchFollowUp, };
|
|
234
|
-
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, LifecycleMetricsData, UpdateStatusData, UpdateHistoryData, ApplyUpdateResultData, RollbackResultData, ApprovalRecordData, PrinciplesListData, ApprovalsGroupedData, EvidenceChainData, EvidenceChainRecordData, EvidenceChainStateData, TrajectoryData, TrajectoryStageData, IntentSummaryData, IntentSectionsData, IntentDocWarningData, IntentDecisionRecordData, IntentDecisionResultData, IntentDecisionSummaryData, FollowUpResponseData, LinkCandidateFollowUpData, GuideRulehostFollowUpData, GeneratePatchProposalFollowUpData, IntentVersionEntry, IntentVersionData, } from "./utils/validators.js";
|
|
234
|
+
export { request, listActiveSignalKeywords, listPendingSignalTerms, fetchKeywordStore, fetchPendingTerms, updateKeywordStore, admitPendingTerm, rejectPendingTerm, getToken, setToken, clearToken, checkAuth, approveApproval, rejectApproval, editApproval, fetchPrinciples, fetchCorePrinciples, fetchPrincipleDetail, fetchPrincipleGovernance, fetchPrincipleTrajectory, fetchPrincipleReceipts, fetchReceiptCounts, 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, fetchOwnerDecisions, resolveOwnerDecision, fetchApprovalsGrouped, fetchAllActivations, disableActivation, fetchRuleCodeOwnerReview, ruleCodeDecision, pauseAllRuleCode, releaseRuleCodePause, fetchLifecycleMetrics, fetchUpdateStatus, fetchUpdateHistory, applyUpdate, applyFullUpdate, rollbackUpdate, fetchEvidenceChain, fetchIntentSummary, fetchIntentContent, createIntentTemplate, saveIntentContent, fetchIntentVersions, recordIntentDecision, listIntentDecisionsByPainId, listIntentDecisionsByTaskId, fetchIntentDecisionSummary, dispatchFollowUp, };
|
|
235
|
+
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, LifecycleMetricsData, UpdateStatusData, UpdateHistoryData, ApplyUpdateResultData, RollbackResultData, 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";
|
|
235
236
|
export type { SignalKeyword, PendingSignalTerm } from "./utils/signal-keywords-types.js";
|
|
236
237
|
export type { ActivationRecordData as ActivationRecord } from "./utils/validators.js";
|
|
237
238
|
export type { ApprovalRecordData as ApprovalRecord } from "./utils/validators.js";
|
package/console/dist/ui/api.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { listActiveSignalKeywords, listPendingSignalTerms, fetchKeywordStore, fetchPendingTerms, updateKeywordStore, admitPendingTerm, rejectPendingTerm, } from "./utils/signal-keywords-api.js";
|
|
2
|
-
import { validateErrorResponse, validateHeaders, validateFeedbackReport, validateFeedbackDraftsList, validateFeedbackDraftEnvelope, validateFeedbackChannels, validateFeedbackSubmitResult, validateDeleteEnvelope, validateWorkspaceEntry, validateWorkspaceList, validateRemovedEnvelope, validateSyncResult, validateConfigSummary, validateConfigCatalog, validateAgentBindingUpdate, validateDefaultRuntimeUpdate, validateRuntimeProfileMutation, validateReadinessCheck, validateFeatureFlagUpdate, validateOutputLanguage, validateGovernanceQueue, validateRecoveryResult, validateOwnerDecisionsData, validateOwnerResolutionResult, validateActivations, validateDisableActivation, validateLifecycleMetrics, validateUpdateStatus, validateUpdateHistory, validateApplyUpdateResult, validateRollbackResult, validateApprovalRecordDirect, validatePrinciplesList, validateApprovalsGrouped, validateEvidenceChain, validateTrajectoryData, validateIntentSummary, validateIntentDecisionList, validateIntentDecisionResult, validateIntentDecisionSummary, validateFollowUpResponse, validateIntentInitResult, validateIntentSaveResult, validateIntentRawContent, validateIntentVersions, validateOwnerGovernanceView, validateGovernanceExperienceSnapshot, validateRuleCodeOwnerReview, validateRuleCodeMutation, validateOwnerIdentityView, validateOwnerIdentityRegister, validateOwnerIdentityUnregister, } from "./utils/validators.js";
|
|
2
|
+
import { validateErrorResponse, validateHeaders, validateFeedbackReport, validateFeedbackDraftsList, validateFeedbackDraftEnvelope, validateFeedbackChannels, validateFeedbackSubmitResult, validateDeleteEnvelope, validateWorkspaceEntry, validateWorkspaceList, validateRemovedEnvelope, validateSyncResult, validateConfigSummary, validateConfigCatalog, validateAgentBindingUpdate, validateDefaultRuntimeUpdate, validateRuntimeProfileMutation, validateReadinessCheck, validateFeatureFlagUpdate, validateOutputLanguage, validateGovernanceQueue, validateRecoveryResult, validateOwnerDecisionsData, validateOwnerResolutionResult, validateActivations, validateDisableActivation, validateLifecycleMetrics, validateUpdateStatus, validateUpdateHistory, validateApplyUpdateResult, validateRollbackResult, validateApprovalRecordDirect, validatePrinciplesList, validateCorePrinciples, validateApprovalsGrouped, validateEvidenceChain, validateTrajectoryData, validateIntentSummary, validateIntentDecisionList, validateIntentDecisionResult, validateIntentDecisionSummary, validateFollowUpResponse, validateIntentInitResult, validateIntentSaveResult, validateIntentRawContent, validateIntentVersions, validateOwnerGovernanceView, validateGovernanceExperienceSnapshot, validateRuleCodeOwnerReview, validateRuleCodeMutation, validateOwnerIdentityView, validateOwnerIdentityRegister, validateOwnerIdentityUnregister, } from "./utils/validators.js";
|
|
3
3
|
// ── Auth ──────────────────────────────────────────────────────────────────────
|
|
4
4
|
function getToken() {
|
|
5
5
|
return sessionStorage.getItem("pd_token");
|
|
@@ -113,6 +113,11 @@ async function fetchPrinciples(filter) {
|
|
|
113
113
|
const query = filter === undefined ? '' : `?filter=${filter}`;
|
|
114
114
|
return request(`/api/principles${query}`, undefined, validatePrinciplesList);
|
|
115
115
|
}
|
|
116
|
+
// PRI-641: read-only PD Core Principles reference. Served from the canonical
|
|
117
|
+
// registry by the server; validated here for network shape only.
|
|
118
|
+
async function fetchCorePrinciples() {
|
|
119
|
+
return request("/api/principles/core", undefined, validateCorePrinciples);
|
|
120
|
+
}
|
|
116
121
|
// Principle detail is deeply nested; for now we accept unvalidated until a
|
|
117
122
|
// dedicated validator is added (the page already handles missing fields gracefully).
|
|
118
123
|
// This endpoint is marked legacy/deferred for full validation.
|
|
@@ -575,6 +580,6 @@ export { request,
|
|
|
575
580
|
// signal-keywords (UI stubs, see signal-keywords-api.ts)
|
|
576
581
|
listActiveSignalKeywords, listPendingSignalTerms, fetchKeywordStore, fetchPendingTerms, updateKeywordStore, admitPendingTerm, rejectPendingTerm,
|
|
577
582
|
// auth
|
|
578
|
-
getToken, setToken, clearToken, checkAuth, approveApproval, rejectApproval, editApproval, fetchPrinciples, fetchPrincipleDetail, fetchPrincipleGovernance, fetchPrincipleTrajectory, fetchPrincipleReceipts, fetchReceiptCounts, archivePrinciple, unarchivePrinciple, createFeedbackReport, listFeedbackReports, getFeedbackReport, deleteFeedbackReport,
|
|
583
|
+
getToken, setToken, clearToken, checkAuth, approveApproval, rejectApproval, editApproval, fetchPrinciples, fetchCorePrinciples, fetchPrincipleDetail, fetchPrincipleGovernance, fetchPrincipleTrajectory, fetchPrincipleReceipts, fetchReceiptCounts, archivePrinciple, unarchivePrinciple, createFeedbackReport, listFeedbackReports, getFeedbackReport, deleteFeedbackReport,
|
|
579
584
|
// Feedback submit ladder (Slice 3, spec §8)
|
|
580
585
|
fetchFeedbackChannels, submitFeedbackReport, markFeedbackReportSent, fetchConfigSummary, fetchConfigCatalog, updateAgentBinding, updateDefaultRuntime, createRuntimeProfile, updateRuntimeProfile, deleteRuntimeProfile, fetchAgentReadiness, patchFeatureFlag, fetchOutputLanguage, updateOutputLanguage, fetchWorkspaces, addWorkspace, removeWorkspace, syncWorkspace, fetchGovernanceQueue, fetchGovernanceExperience, recoverFailedTask, fetchOwnerDecisions, resolveOwnerDecision, fetchApprovalsGrouped, fetchAllActivations, disableActivation, fetchRuleCodeOwnerReview, ruleCodeDecision, pauseAllRuleCode, releaseRuleCodePause, fetchLifecycleMetrics, fetchUpdateStatus, fetchUpdateHistory, applyUpdate, applyFullUpdate, rollbackUpdate, fetchEvidenceChain, fetchIntentSummary, fetchIntentContent, createIntentTemplate, saveIntentContent, fetchIntentVersions, recordIntentDecision, listIntentDecisionsByPainId, listIntentDecisionsByTaskId, fetchIntentDecisionSummary, dispatchFollowUp, };
|
|
@@ -506,6 +506,18 @@
|
|
|
506
506
|
"reviewTitle": "Principle Review",
|
|
507
507
|
"reviewSubtitle": "Review the principles distilled from observed behavior.",
|
|
508
508
|
"reviewDescription": "These are not cold rules — they are behavioral principles your Agent has distilled from real use.",
|
|
509
|
+
"viewNavLabel": "Principles views",
|
|
510
|
+
"tabWorkspace": "Workspace Principles",
|
|
511
|
+
"tabCore": "PD Core Principles",
|
|
512
|
+
"coreSectionTitle": "PRINCIPLES",
|
|
513
|
+
"coreTitle": "PD Core Principles",
|
|
514
|
+
"coreDescription": "These are the built-in principles PD uses to guide how an agent understands problems, makes judgments, and learns from experience. They are provided by the PD Runtime and are not workspace-learned principles.",
|
|
515
|
+
"coreReadOnly": "Read-only",
|
|
516
|
+
"coreLayerFoundational": "Foundational Axioms",
|
|
517
|
+
"coreLayerOperating": "Operating Principles",
|
|
518
|
+
"coreLoading": "Loading…",
|
|
519
|
+
"coreLoadFailed": "Unable to load PD Core Principles",
|
|
520
|
+
"coreRetry": "Retry",
|
|
509
521
|
"metricDeposited": "Deposited Principles",
|
|
510
522
|
"metricActive": "Active Principles",
|
|
511
523
|
"metricLatest": "Last Updated",
|
|
@@ -506,6 +506,18 @@
|
|
|
506
506
|
"reviewTitle": "原则审查",
|
|
507
507
|
"reviewSubtitle": "审阅从真实行为中沉淀出的原则。",
|
|
508
508
|
"reviewDescription": "这些不是冰冷的规则,而是智能体在真实使用过程中沉淀下来的行为准则。",
|
|
509
|
+
"viewNavLabel": "原则视图",
|
|
510
|
+
"tabWorkspace": "工作区原则",
|
|
511
|
+
"tabCore": "PD 核心原则",
|
|
512
|
+
"coreSectionTitle": "原则",
|
|
513
|
+
"coreTitle": "PD 核心原则",
|
|
514
|
+
"coreDescription": "这些是 PD 内置的基本原则,用来指导智能体如何理解问题、作出判断,以及从经验中学习。它们由 PD Runtime 提供,不属于工作区的学习原则。",
|
|
515
|
+
"coreReadOnly": "只读",
|
|
516
|
+
"coreLayerFoundational": "基础公理",
|
|
517
|
+
"coreLayerOperating": "操作原则",
|
|
518
|
+
"coreLoading": "加载中…",
|
|
519
|
+
"coreLoadFailed": "无法加载 PD 核心原则",
|
|
520
|
+
"coreRetry": "重试",
|
|
509
521
|
"metricDeposited": "沉淀原则",
|
|
510
522
|
"metricActive": "已生效原则",
|
|
511
523
|
"metricLatest": "最近更新",
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PD Core Principles — read-only reference surface (PRI-641).
|
|
3
|
+
*
|
|
4
|
+
* The 10 builtin axioms (T-01..T-10) are PD's own semantics, served from the
|
|
5
|
+
* canonical registry via GET /api/principles/core. They are not workspace
|
|
6
|
+
* governance targets: no lifecycle, no approvals, no archive, no edit. This
|
|
7
|
+
* page renders exactly id / name / statement / layer, localized with the
|
|
8
|
+
* registry's own bilingual fields.
|
|
9
|
+
*/
|
|
10
|
+
export declare function CorePrinciplesPage(): import("react").JSX.Element;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useEffect, useCallback } from "react";
|
|
3
|
+
import { useTranslation } from "react-i18next";
|
|
4
|
+
import { PageShell } from "../../components/layout/page-shell.js";
|
|
5
|
+
import { SectionTitle } from "../../components/layout/section-title.js";
|
|
6
|
+
import { Button } from "../../components/ui/button.js";
|
|
7
|
+
import { Skeleton } from "../../components/ui/skeleton.js";
|
|
8
|
+
import { fetchCorePrinciples } from "../../api.js";
|
|
9
|
+
import { PrinciplesViewNav } from "./PrinciplesViewNav.js";
|
|
10
|
+
/**
|
|
11
|
+
* PD Core Principles — read-only reference surface (PRI-641).
|
|
12
|
+
*
|
|
13
|
+
* The 10 builtin axioms (T-01..T-10) are PD's own semantics, served from the
|
|
14
|
+
* canonical registry via GET /api/principles/core. They are not workspace
|
|
15
|
+
* governance targets: no lifecycle, no approvals, no archive, no edit. This
|
|
16
|
+
* page renders exactly id / name / statement / layer, localized with the
|
|
17
|
+
* registry's own bilingual fields.
|
|
18
|
+
*/
|
|
19
|
+
export function CorePrinciplesPage() {
|
|
20
|
+
const { t, i18n } = useTranslation("pages");
|
|
21
|
+
const [principles, setPrinciples] = useState([]);
|
|
22
|
+
const [loading, setLoading] = useState(true);
|
|
23
|
+
const [error, setError] = useState(null);
|
|
24
|
+
const loadCore = useCallback(async () => {
|
|
25
|
+
setLoading(true);
|
|
26
|
+
setError(null);
|
|
27
|
+
try {
|
|
28
|
+
// Response shape is runtime-validated in fetchCorePrinciples
|
|
29
|
+
// (validateCorePrinciples); no fallback to hardcoded principles on error.
|
|
30
|
+
const result = await fetchCorePrinciples();
|
|
31
|
+
if (!result.success) {
|
|
32
|
+
setError(result.error ?? t("principles.coreLoadFailed"));
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
setPrinciples(result.data.principles);
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
setError(err instanceof Error ? err.message : t("principles.coreLoadFailed"));
|
|
39
|
+
}
|
|
40
|
+
finally {
|
|
41
|
+
setLoading(false);
|
|
42
|
+
}
|
|
43
|
+
}, [t]);
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
loadCore();
|
|
46
|
+
}, [loadCore]);
|
|
47
|
+
const isZh = (i18n.language ?? "").startsWith("zh");
|
|
48
|
+
const foundational = principles.filter((p) => p.layer === "foundational");
|
|
49
|
+
const operating = principles.filter((p) => p.layer === "operating");
|
|
50
|
+
return (_jsxs(PageShell, { children: [_jsx(SectionTitle, { children: t("principles.coreSectionTitle") }), _jsx("h1", { className: "text-[29px] font-semibold tracking-tight text-ink mb-2", children: t("principles.coreTitle") }), _jsx("p", { className: "text-ink-3 text-[14px] leading-relaxed mb-1", children: t("principles.coreDescription") }), _jsxs("p", { className: "text-ink-4 text-[12px] font-mono mb-6", children: ["\uD83D\uDD12 ", t("principles.coreReadOnly")] }), _jsx(PrinciplesViewNav, { view: "core" }), loading && (_jsx("div", { className: "grid gap-3", role: "status", "aria-live": "polite", "aria-label": t("principles.coreLoading"), children: Array.from({ length: 4 }).map((_, i) => (_jsxs("div", { className: "bg-panel border border-line rounded-[var(--radius-md)] p-4", children: [_jsx(Skeleton, { className: "h-5 w-[40%] rounded-sm mb-3" }), _jsx(Skeleton, { className: "h-4 w-full rounded-sm mb-2" }), _jsx(Skeleton, { className: "h-4 w-[70%] rounded-sm" })] }, i))) })), error && (_jsxs("div", { className: "border border-danger/30 rounded-[var(--radius-md)] p-4 mb-4", children: [_jsx("p", { className: "text-danger text-sm", children: t("principles.coreLoadFailed") }), _jsx("p", { className: "text-ink-4 text-[12px] mt-1 font-mono break-all", children: error }), _jsx(Button, { variant: "outline", size: "sm", onClick: loadCore, className: "mt-2", children: t("principles.coreRetry") })] })), !loading && !error && (_jsxs(_Fragment, { children: [_jsx(CoreLayerGroup, { label: t("principles.coreLayerFoundational"), principles: foundational, isZh: isZh }), _jsx(CoreLayerGroup, { label: t("principles.coreLayerOperating"), principles: operating, isZh: isZh })] }))] }));
|
|
51
|
+
}
|
|
52
|
+
function CoreLayerGroup({ label, principles, isZh, }) {
|
|
53
|
+
const { t } = useTranslation("pages");
|
|
54
|
+
return (_jsxs("section", { className: "mb-8", "aria-label": label, children: [_jsxs("h2", { className: "font-mono text-[11px] uppercase tracking-[0.02em] text-ink-3 border-b border-line pb-2 mb-4", children: [label, " \u00B7 ", principles.length] }), _jsx("div", { className: "grid gap-3 animate-[pdFadeIn_400ms_ease-out]", children: principles.map((p) => {
|
|
55
|
+
const name = isZh ? p.nameZh : p.name;
|
|
56
|
+
const statement = isZh ? p.statementZh : p.statement;
|
|
57
|
+
return (_jsxs("article", { id: p.id, className: "bg-panel border border-line rounded-[var(--radius-md)] p-4", children: [_jsxs("div", { className: "flex items-center gap-2 mb-2", children: [_jsx("span", { className: "font-mono text-[11px] tracking-[0.02em] border border-line rounded-[2px] px-2 py-0.5 text-ink-3", children: p.id }), _jsx("span", { className: "font-mono text-[11px] tracking-[0.02em] text-ink-4", children: t("principles.coreLayer" + (p.layer === "foundational" ? "Foundational" : "Operating")) })] }), _jsx("h3", { className: "font-semibold text-ink mb-1", children: name }), _jsx("p", { className: "text-ink-3 text-[13px] leading-relaxed", children: statement })] }, p.id));
|
|
58
|
+
}) })] }));
|
|
59
|
+
}
|
|
@@ -10,6 +10,7 @@ import { ShinyText } from "../../components/ui/shiny-text.js";
|
|
|
10
10
|
import { fetchPrinciples, fetchApprovalsGrouped, } from "../../api.js";
|
|
11
11
|
import { enumLabel } from "../../utils/enum-labels.js";
|
|
12
12
|
import { formatDate } from "../../utils/format-date.js";
|
|
13
|
+
import { PrinciplesViewNav } from "./PrinciplesViewNav.js";
|
|
13
14
|
// ── Map principle status to review status ───────────────────────────────────
|
|
14
15
|
function toReviewStatus(principleStatus, approvalStatus) {
|
|
15
16
|
if (approvalStatus === "approved")
|
|
@@ -259,7 +260,7 @@ export function PrinciplesPage() {
|
|
|
259
260
|
];
|
|
260
261
|
// PRI-558: most recent update across loaded principles (drives "Last Updated" metric)
|
|
261
262
|
const latestUpdatedAt = principles.reduce((max, p) => (new Date(p.updatedAt).getTime() > new Date(max).getTime() ? p.updatedAt : max), principles[0]?.updatedAt ?? "");
|
|
262
|
-
return (_jsxs(PageShell, { children: [_jsx(SectionTitle, { children: t("principles.reviewTitle") }), _jsx(ShinyText, { as: "h1", className: "text-[29px] font-semibold tracking-tight text-ink mb-2", duration: 4.5, brightness: 0.5, disabled: !(filterMode === 'actionable' && (categories?.owner_actionable ?? 0) > 0), children: t("principles.reviewSubtitle") }), _jsx("p", { className: "text-ink-3 text-[14px] leading-relaxed mb-6", children: t("principles.reviewDescription") }), _jsxs("div", { className: "flex flex-wrap items-center gap-3 mb-6", children: [_jsxs("div", { className: "flex gap-1", role: "group", "aria-label": "Filter mode", children: [_jsxs("button", { onClick: () => setFilterMode('actionable'), className: "font-mono text-[11px] uppercase tracking-[0.02em] border rounded-[2px] px-2 py-1 transition-colors focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gov " +
|
|
263
|
+
return (_jsxs(PageShell, { children: [_jsx(SectionTitle, { children: t("principles.reviewTitle") }), _jsx(ShinyText, { as: "h1", className: "text-[29px] font-semibold tracking-tight text-ink mb-2", duration: 4.5, brightness: 0.5, disabled: !(filterMode === 'actionable' && (categories?.owner_actionable ?? 0) > 0), children: t("principles.reviewSubtitle") }), _jsx("p", { className: "text-ink-3 text-[14px] leading-relaxed mb-6", children: t("principles.reviewDescription") }), _jsx(PrinciplesViewNav, { view: "workspace" }), _jsxs("div", { className: "flex flex-wrap items-center gap-3 mb-6", children: [_jsxs("div", { className: "flex gap-1", role: "group", "aria-label": "Filter mode", children: [_jsxs("button", { onClick: () => setFilterMode('actionable'), className: "font-mono text-[11px] uppercase tracking-[0.02em] border rounded-[2px] px-2 py-1 transition-colors focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gov " +
|
|
263
264
|
(filterMode === 'actionable'
|
|
264
265
|
? "bg-gov text-paper border-gov"
|
|
265
266
|
: "bg-surface text-ink-3 border-line hover:border-line-2"), children: [t("principles.filterActionable", { defaultValue: "Actionable" }), categories?.owner_actionable ? ` (${categories.owner_actionable})` : ''] }), _jsxs("button", { onClick: () => setFilterMode('all'), className: "font-mono text-[11px] uppercase tracking-[0.02em] border rounded-[2px] px-2 py-1 transition-colors focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gov " +
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PRI-641: internal navigation inside the Principles section — Workspace
|
|
3
|
+
* Principles vs the read-only PD Core Principles reference surface. The
|
|
4
|
+
* sidebar keeps a single "Principles" entry; this is the only extra nav.
|
|
5
|
+
*/
|
|
6
|
+
export declare function PrinciplesViewNav({ view }: {
|
|
7
|
+
view: "workspace" | "core";
|
|
8
|
+
}): import("react").JSX.Element;
|