@principles/pd-cli 1.82.0 → 1.84.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/dist/commands/diagnose.d.ts.map +1 -1
- package/dist/commands/diagnose.js +5 -0
- package/dist/commands/diagnose.js.map +1 -1
- package/dist/commands/pain-retry.d.ts.map +1 -1
- package/dist/commands/pain-retry.js +5 -0
- package/dist/commands/pain-retry.js.map +1 -1
- package/dist/commands/runtime-internalization-run-once.d.ts.map +1 -1
- package/dist/commands/runtime-internalization-run-once.js +5 -1
- package/dist/commands/runtime-internalization-run-once.js.map +1 -1
- package/dist/commands/runtime-uat.d.ts +1 -0
- package/dist/commands/runtime-uat.d.ts.map +1 -1
- package/dist/commands/runtime-uat.guard.test.d.ts +2 -0
- package/dist/commands/runtime-uat.guard.test.d.ts.map +1 -0
- package/dist/commands/runtime-uat.guard.test.js +155 -0
- package/dist/commands/runtime-uat.guard.test.js.map +1 -0
- package/dist/commands/runtime-uat.js +29 -3
- package/dist/commands/runtime-uat.js.map +1 -1
- package/dist/config-reader.d.ts +25 -0
- package/dist/config-reader.d.ts.map +1 -0
- package/dist/config-reader.js +109 -0
- package/dist/config-reader.js.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/utils/production-workspace-guard.d.ts +77 -0
- package/dist/utils/production-workspace-guard.d.ts.map +1 -0
- package/dist/utils/production-workspace-guard.js +170 -0
- package/dist/utils/production-workspace-guard.js.map +1 -0
- package/dist/utils/production-workspace-guard.test.d.ts +2 -0
- package/dist/utils/production-workspace-guard.test.d.ts.map +1 -0
- package/dist/utils/production-workspace-guard.test.js +95 -0
- package/dist/utils/production-workspace-guard.test.js.map +1 -0
- package/package.json +1 -1
- package/src/commands/diagnose.ts +8 -1
- package/src/commands/pain-retry.ts +8 -1
- package/src/commands/runtime-internalization-run-once.ts +6 -2
- package/src/commands/runtime-uat.guard.test.ts +177 -0
- package/src/commands/runtime-uat.ts +42 -4
- package/src/config-reader.ts +122 -0
- package/src/index.ts +2 -0
- package/src/utils/production-workspace-guard.test.ts +108 -0
- package/src/utils/production-workspace-guard.ts +219 -0
- package/tests/commands/candidate-audit-repair.test.ts +1 -0
- package/tests/commands/candidate-intake.test.ts +1 -0
- package/tests/commands/candidate-internalization-backfill.test.ts +1 -0
- package/tests/commands/candidate-internalize.test.ts +1 -0
- package/tests/commands/candidate-route.test.ts +1 -0
- package/tests/commands/diagnose.test.ts +5 -0
- package/tests/commands/health.test.ts +1 -0
- package/tests/commands/pain-record.test.ts +1 -0
- package/tests/commands/pain-retry.test.ts +5 -0
- package/tests/commands/runtime-activation.test.ts +1 -0
- package/tests/commands/runtime-canary.test.ts +1 -0
- package/tests/commands/runtime-diagnostics-export.test.ts +1 -0
- package/tests/commands/runtime-health-snapshot.test.ts +1 -0
- package/tests/commands/runtime-internalization-enqueue-successors.test.ts +1 -0
- package/tests/commands/runtime-internalization-integrity-repair.test.ts +1 -0
- package/tests/commands/runtime-internalization-integrity.test.ts +1 -0
- package/tests/commands/runtime-internalization-queue.test.ts +1 -0
- package/tests/commands/runtime-internalization-run-once.test.ts +5 -0
- package/tests/commands/runtime-internalization-wake-once.test.ts +1 -0
- package/tests/commands/runtime-pruning.test.ts +1 -0
- package/tests/commands/runtime-recovery.test.ts +1 -0
- package/tests/commands/runtime.test.ts +1 -0
- package/tests/commands/trace.test.ts +1 -0
- package/tests/config-reader.test.ts +142 -0
|
@@ -43,6 +43,7 @@ vi.mock('@principles/core/runtime-v2', () => ({
|
|
|
43
43
|
auditCandidateLedgerConsistency: mockAuditConsistency,
|
|
44
44
|
buildGfiWorkspaceSnapshot: mockBuildGfiSnapshot,
|
|
45
45
|
classifyGfiWorkspaceHealth: mockClassifyGfiHealth,
|
|
46
|
+
resolveOutputLanguage: vi.fn().mockReturnValue({ outputLanguage: 'zh-CN' }),
|
|
46
47
|
}));
|
|
47
48
|
|
|
48
49
|
vi.mock('../../src/services/feature-flag-loader.js', () => ({
|
|
@@ -36,6 +36,7 @@ vi.mock('@principles/core/runtime-v2', () => ({
|
|
|
36
36
|
}),
|
|
37
37
|
auditCandidateLedgerConsistency: mockAuditConsistency,
|
|
38
38
|
buildGfiWorkspaceSnapshot: mockBuildGfiSnapshot,
|
|
39
|
+
resolveOutputLanguage: vi.fn().mockReturnValue({ outputLanguage: 'zh-CN' }),
|
|
39
40
|
}));
|
|
40
41
|
|
|
41
42
|
vi.mock('../../src/commands/runtime-canary.js', () => ({
|
|
@@ -20,6 +20,7 @@ vi.mock('@principles/core/runtime-v2', () => ({
|
|
|
20
20
|
OperatorHealthReadModel: vi.fn().mockImplementation(function () {
|
|
21
21
|
return { getSnapshot: mockSnapshotFn, close: mockCloseFn };
|
|
22
22
|
}),
|
|
23
|
+
resolveOutputLanguage: vi.fn().mockReturnValue({ outputLanguage: 'zh-CN' }),
|
|
23
24
|
}));
|
|
24
25
|
|
|
25
26
|
import { handleRuntimeHealthSnapshot } from '../../src/commands/runtime-health-snapshot.js';
|
|
@@ -54,6 +54,7 @@ vi.mock('@principles/core/runtime-v2', () => ({
|
|
|
54
54
|
return null;
|
|
55
55
|
}
|
|
56
56
|
}),
|
|
57
|
+
resolveOutputLanguage: vi.fn().mockReturnValue({ outputLanguage: 'zh-CN' }),
|
|
57
58
|
}));
|
|
58
59
|
|
|
59
60
|
import { handleRuntimeInternalizationEnqueueSuccessors } from '../../src/commands/runtime-internalization-enqueue-successors.js';
|
|
@@ -10,6 +10,7 @@ vi.mock('@principles/core/runtime-v2', () => ({
|
|
|
10
10
|
InternalizationIntegrityRemediation: vi.fn().mockImplementation(function () {
|
|
11
11
|
return { repair: mockRepair };
|
|
12
12
|
}),
|
|
13
|
+
resolveOutputLanguage: vi.fn().mockReturnValue({ outputLanguage: 'zh-CN' }),
|
|
13
14
|
}));
|
|
14
15
|
|
|
15
16
|
import { Command } from 'commander';
|
|
@@ -10,6 +10,7 @@ vi.mock('@principles/core/runtime-v2', () => ({
|
|
|
10
10
|
InternalizationChainIntegrityReadModel: vi.fn().mockImplementation(function () {
|
|
11
11
|
return { check: mockCheck };
|
|
12
12
|
}),
|
|
13
|
+
resolveOutputLanguage: vi.fn().mockReturnValue({ outputLanguage: 'zh-CN' }),
|
|
13
14
|
}));
|
|
14
15
|
|
|
15
16
|
import { handleRuntimeInternalizationIntegrity } from '../../src/commands/runtime-internalization-integrity.js';
|
|
@@ -21,6 +21,7 @@ vi.mock('@principles/core/runtime-v2', () => ({
|
|
|
21
21
|
readModel: { getSnapshot: mockGetSnapshot, close: mockClose },
|
|
22
22
|
close: mockClose,
|
|
23
23
|
}),
|
|
24
|
+
resolveOutputLanguage: vi.fn().mockReturnValue({ outputLanguage: 'zh-CN' }),
|
|
24
25
|
}));
|
|
25
26
|
|
|
26
27
|
vi.mock('../../src/services/feature-flag-loader.js', () => ({
|
|
@@ -122,6 +122,11 @@ vi.mock('@principles/core/runtime-v2', () => ({
|
|
|
122
122
|
}),
|
|
123
123
|
isRuntimeConfigError: vi.fn().mockReturnValue(false),
|
|
124
124
|
validateRuntimeConfig: vi.fn(),
|
|
125
|
+
resolveOutputLanguage: vi.fn().mockReturnValue({ outputLanguage: 'zh-CN' }),
|
|
126
|
+
}));
|
|
127
|
+
|
|
128
|
+
vi.mock('../../src/config-reader.js', () => ({
|
|
129
|
+
readOutputLanguageFromWorkspace: vi.fn().mockReturnValue({ outputLanguage: 'zh-CN' }),
|
|
125
130
|
}));
|
|
126
131
|
|
|
127
132
|
import { handleRuntimeInternalizationRunOnce } from '../../src/commands/runtime-internalization-run-once.js';
|
|
@@ -21,6 +21,7 @@ vi.mock('@principles/core/runtime-v2', () => ({
|
|
|
21
21
|
InternalizationOrchestrator: vi.fn().mockImplementation(function () {
|
|
22
22
|
return { wakeOnce: mockWakeOnce };
|
|
23
23
|
}),
|
|
24
|
+
resolveOutputLanguage: vi.fn().mockReturnValue({ outputLanguage: 'zh-CN' }),
|
|
24
25
|
}));
|
|
25
26
|
|
|
26
27
|
import { handleRuntimeInternalizationWakeOnce } from '../../src/commands/runtime-internalization-wake-once.js';
|
|
@@ -87,6 +87,7 @@ vi.mock('@principles/core/runtime-v2', () => ({
|
|
|
87
87
|
listPruningReviews: mockListPruningReviews,
|
|
88
88
|
buildMaskedPrincipleSet: mockBuildMaskedPrincipleSet,
|
|
89
89
|
removeOrphanReferencesFromLedger: mockRemoveOrphanReferencesFromLedger,
|
|
90
|
+
resolveOutputLanguage: vi.fn().mockReturnValue({ outputLanguage: 'zh-CN' }),
|
|
90
91
|
}));
|
|
91
92
|
|
|
92
93
|
import { handlePruningReport, handlePruningExplain, handlePruningReview, handlePruningRollback, handlePruningOrphans } from '../../src/commands/runtime-pruning.js';
|
|
@@ -28,6 +28,7 @@ vi.mock('@principles/core/runtime-v2', () => ({
|
|
|
28
28
|
warnings: input.warnings ?? [],
|
|
29
29
|
})),
|
|
30
30
|
remediationAction: vi.fn((input) => input),
|
|
31
|
+
resolveOutputLanguage: vi.fn().mockReturnValue({ outputLanguage: 'zh-CN' }),
|
|
31
32
|
}));
|
|
32
33
|
|
|
33
34
|
import { handleRuntimeRecoverySweep } from '../../src/commands/runtime-recovery.js';
|
|
@@ -32,6 +32,7 @@ vi.mock('@principles/core/runtime-v2', () => ({
|
|
|
32
32
|
agentId: 'main',
|
|
33
33
|
}),
|
|
34
34
|
isRuntimeConfigError: vi.fn().mockReturnValue(false),
|
|
35
|
+
resolveOutputLanguage: vi.fn().mockReturnValue({ outputLanguage: 'zh-CN' }),
|
|
35
36
|
PDRuntimeError: class PDRuntimeError extends Error {
|
|
36
37
|
constructor(public category: string, message: string) {
|
|
37
38
|
super(message);
|
|
@@ -14,6 +14,7 @@ vi.mock('@principles/core/runtime-v2', () => ({
|
|
|
14
14
|
PainChainReadModel: vi.fn().mockImplementation(function () {
|
|
15
15
|
return { traceByPainId: mockTraceByPainId, close: mockPainChainClose };
|
|
16
16
|
}),
|
|
17
|
+
resolveOutputLanguage: vi.fn().mockReturnValue({ outputLanguage: 'zh-CN' }),
|
|
17
18
|
}));
|
|
18
19
|
|
|
19
20
|
vi.mock('../../src/resolve-workspace.js', () => ({
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for config-reader — readOutputLanguageFromWorkspace (PRI-336).
|
|
3
|
+
*
|
|
4
|
+
* Validates:
|
|
5
|
+
* - No config file → legitimate default, no warning
|
|
6
|
+
* - No principles section → legitimate default, no warning
|
|
7
|
+
* - No outputLanguage key → legitimate default, no warning
|
|
8
|
+
* - Read error → degraded with read_error reason + nextAction (ERR-002/009)
|
|
9
|
+
* - YAML parse error → degraded with yaml_parse_error reason + nextAction
|
|
10
|
+
* - Invalid config root → degraded with invalid_config_root reason + nextAction
|
|
11
|
+
* - Invalid principles structure → degraded with invalid_principles_structure reason + nextAction
|
|
12
|
+
* - Valid outputLanguage → resolved value
|
|
13
|
+
* - Invalid outputLanguage value → degraded with invalid value warning
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
17
|
+
import { readOutputLanguageFromWorkspace } from '../../src/config-reader.js';
|
|
18
|
+
|
|
19
|
+
// Mock fs and yaml
|
|
20
|
+
vi.mock('fs', () => ({
|
|
21
|
+
existsSync: vi.fn(),
|
|
22
|
+
readFileSync: vi.fn(),
|
|
23
|
+
}));
|
|
24
|
+
|
|
25
|
+
vi.mock('js-yaml', () => ({
|
|
26
|
+
default: {
|
|
27
|
+
load: vi.fn(),
|
|
28
|
+
JSON_SCHEMA: 'JSON_SCHEMA',
|
|
29
|
+
},
|
|
30
|
+
}));
|
|
31
|
+
|
|
32
|
+
import * as fs from 'fs';
|
|
33
|
+
import yaml from 'js-yaml';
|
|
34
|
+
|
|
35
|
+
const mockExistsSync = vi.mocked(fs.existsSync);
|
|
36
|
+
const mockReadFileSync = vi.mocked(fs.readFileSync);
|
|
37
|
+
const mockYamlLoad = vi.mocked(yaml.load);
|
|
38
|
+
|
|
39
|
+
beforeEach(() => {
|
|
40
|
+
vi.clearAllMocks();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
afterEach(() => {
|
|
44
|
+
vi.restoreAllMocks();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
describe('readOutputLanguageFromWorkspace', () => {
|
|
48
|
+
it('returns default with no warning when config file does not exist', () => {
|
|
49
|
+
mockExistsSync.mockReturnValue(false);
|
|
50
|
+
const result = readOutputLanguageFromWorkspace('/workspace');
|
|
51
|
+
expect(result.outputLanguage).toBe('zh-CN');
|
|
52
|
+
expect(result.degradationWarning).toBeUndefined();
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('returns default with no warning when principles section is missing', () => {
|
|
56
|
+
mockExistsSync.mockReturnValue(true);
|
|
57
|
+
mockReadFileSync.mockReturnValue('version: 1\n');
|
|
58
|
+
mockYamlLoad.mockReturnValue({ version: 1 });
|
|
59
|
+
const result = readOutputLanguageFromWorkspace('/workspace');
|
|
60
|
+
expect(result.outputLanguage).toBe('zh-CN');
|
|
61
|
+
expect(result.degradationWarning).toBeUndefined();
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('returns default with no warning when outputLanguage key is missing', () => {
|
|
65
|
+
mockExistsSync.mockReturnValue(true);
|
|
66
|
+
mockReadFileSync.mockReturnValue('version: 1\nprinciples: {}\n');
|
|
67
|
+
mockYamlLoad.mockReturnValue({ version: 1, principles: {} });
|
|
68
|
+
const result = readOutputLanguageFromWorkspace('/workspace');
|
|
69
|
+
expect(result.outputLanguage).toBe('zh-CN');
|
|
70
|
+
expect(result.degradationWarning).toBeUndefined();
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('returns valid outputLanguage when configured', () => {
|
|
74
|
+
mockExistsSync.mockReturnValue(true);
|
|
75
|
+
mockReadFileSync.mockReturnValue('version: 1\nprinciples:\n outputLanguage: en\n');
|
|
76
|
+
mockYamlLoad.mockReturnValue({ version: 1, principles: { outputLanguage: 'en' } });
|
|
77
|
+
const result = readOutputLanguageFromWorkspace('/workspace');
|
|
78
|
+
expect(result.outputLanguage).toBe('en');
|
|
79
|
+
expect(result.degradationWarning).toBeUndefined();
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('returns degraded with read_error when readFileSync throws', () => {
|
|
83
|
+
mockExistsSync.mockReturnValue(true);
|
|
84
|
+
mockReadFileSync.mockImplementation(() => { throw new Error('EACCES: permission denied'); });
|
|
85
|
+
const result = readOutputLanguageFromWorkspace('/workspace');
|
|
86
|
+
expect(result.outputLanguage).toBe('zh-CN');
|
|
87
|
+
expect(result.degradationWarning).toContain('Failed to read .pd/config.yaml');
|
|
88
|
+
expect(result.degradationWarning).toContain('nextAction');
|
|
89
|
+
expect(result.degradationWarning).toContain('Check file permissions');
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('returns degraded with yaml_parse_error when yaml.load throws', () => {
|
|
93
|
+
mockExistsSync.mockReturnValue(true);
|
|
94
|
+
mockReadFileSync.mockReturnValue('invalid: yaml: [broken');
|
|
95
|
+
mockYamlLoad.mockImplementation(() => { throw new Error('YAML syntax error'); });
|
|
96
|
+
const result = readOutputLanguageFromWorkspace('/workspace');
|
|
97
|
+
expect(result.outputLanguage).toBe('zh-CN');
|
|
98
|
+
expect(result.degradationWarning).toContain('Failed to parse .pd/config.yaml');
|
|
99
|
+
expect(result.degradationWarning).toContain('nextAction');
|
|
100
|
+
expect(result.degradationWarning).toContain('Fix YAML syntax');
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('returns degraded with invalid_config_root when parsed YAML is not an object', () => {
|
|
104
|
+
mockExistsSync.mockReturnValue(true);
|
|
105
|
+
mockReadFileSync.mockReturnValue('"just a string"');
|
|
106
|
+
mockYamlLoad.mockReturnValue('just a string');
|
|
107
|
+
const result = readOutputLanguageFromWorkspace('/workspace');
|
|
108
|
+
expect(result.outputLanguage).toBe('zh-CN');
|
|
109
|
+
expect(result.degradationWarning).toContain('root is not an object');
|
|
110
|
+
expect(result.degradationWarning).toContain('nextAction');
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it('returns degraded with invalid_config_root when parsed YAML is an array', () => {
|
|
114
|
+
mockExistsSync.mockReturnValue(true);
|
|
115
|
+
mockReadFileSync.mockReturnValue('- item1\n- item2\n');
|
|
116
|
+
mockYamlLoad.mockReturnValue(['item1', 'item2']);
|
|
117
|
+
const result = readOutputLanguageFromWorkspace('/workspace');
|
|
118
|
+
expect(result.outputLanguage).toBe('zh-CN');
|
|
119
|
+
expect(result.degradationWarning).toContain('root is not an object');
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it('returns degraded with invalid_principles_structure when principles is not an object', () => {
|
|
123
|
+
mockExistsSync.mockReturnValue(true);
|
|
124
|
+
mockReadFileSync.mockReturnValue('version: 1\nprinciples: "not an object"\n');
|
|
125
|
+
mockYamlLoad.mockReturnValue({ version: 1, principles: 'not an object' });
|
|
126
|
+
const result = readOutputLanguageFromWorkspace('/workspace');
|
|
127
|
+
expect(result.outputLanguage).toBe('zh-CN');
|
|
128
|
+
expect(result.degradationWarning).toContain('principles field is not an object');
|
|
129
|
+
expect(result.degradationWarning).toContain('nextAction');
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('returns degraded with invalid value warning when outputLanguage is invalid', () => {
|
|
133
|
+
mockExistsSync.mockReturnValue(true);
|
|
134
|
+
mockReadFileSync.mockReturnValue('version: 1\nprinciples:\n outputLanguage: fr\n');
|
|
135
|
+
mockYamlLoad.mockReturnValue({ version: 1, principles: { outputLanguage: 'fr' } });
|
|
136
|
+
const result = readOutputLanguageFromWorkspace('/workspace');
|
|
137
|
+
expect(result.outputLanguage).toBe('zh-CN');
|
|
138
|
+
expect(result.degradationWarning).toContain('invalid');
|
|
139
|
+
expect(result.degradationWarning).toContain('fr');
|
|
140
|
+
expect(result.degradationWarning).toContain('nextAction');
|
|
141
|
+
});
|
|
142
|
+
});
|