@principles/pd-cli 1.152.12 → 1.152.14
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/candidate.d.ts.map +1 -1
- package/dist/commands/candidate.js +34 -7
- package/dist/commands/candidate.js.map +1 -1
- package/dist/commands/diagnose.d.ts.map +1 -1
- package/dist/commands/diagnose.js +23 -7
- package/dist/commands/diagnose.js.map +1 -1
- package/dist/commands/pain-retry.d.ts.map +1 -1
- package/dist/commands/pain-retry.js +21 -7
- package/dist/commands/pain-retry.js.map +1 -1
- package/package.json +13 -7
- package/CHANGELOG.md +0 -23
- package/dist/commands/__tests__/intent-flag-wiring.test.d.ts +0 -9
- package/dist/commands/__tests__/intent-flag-wiring.test.d.ts.map +0 -1
- package/dist/commands/__tests__/intent-flag-wiring.test.js +0 -237
- package/dist/commands/__tests__/intent-flag-wiring.test.js.map +0 -1
- package/dist/commands/__tests__/legacy-cleanup.test.d.ts +0 -18
- package/dist/commands/__tests__/legacy-cleanup.test.d.ts.map +0 -1
- package/dist/commands/__tests__/legacy-cleanup.test.js +0 -467
- package/dist/commands/__tests__/legacy-cleanup.test.js.map +0 -1
- package/dist/commands/__tests__/mvp-smoke.test.d.ts +0 -15
- package/dist/commands/__tests__/mvp-smoke.test.d.ts.map +0 -1
- package/dist/commands/__tests__/mvp-smoke.test.js +0 -262
- package/dist/commands/__tests__/mvp-smoke.test.js.map +0 -1
- package/dist/commands/__tests__/pain-retry-maxTokens-flag.test.d.ts +0 -2
- package/dist/commands/__tests__/pain-retry-maxTokens-flag.test.d.ts.map +0 -1
- package/dist/commands/__tests__/pain-retry-maxTokens-flag.test.js +0 -60
- package/dist/commands/__tests__/pain-retry-maxTokens-flag.test.js.map +0 -1
- package/dist/commands/__tests__/rulecode-flag-wiring.test.d.ts +0 -21
- package/dist/commands/__tests__/rulecode-flag-wiring.test.d.ts.map +0 -1
- package/dist/commands/__tests__/rulecode-flag-wiring.test.js +0 -186
- package/dist/commands/__tests__/rulecode-flag-wiring.test.js.map +0 -1
- package/dist/commands/__tests__/rulecode-handler.test.d.ts +0 -16
- package/dist/commands/__tests__/rulecode-handler.test.d.ts.map +0 -1
- package/dist/commands/__tests__/rulecode-handler.test.js +0 -285
- package/dist/commands/__tests__/rulecode-handler.test.js.map +0 -1
- package/dist/commands/__tests__/run-rulehost-flag-wiring.test.d.ts +0 -24
- package/dist/commands/__tests__/run-rulehost-flag-wiring.test.d.ts.map +0 -1
- package/dist/commands/__tests__/run-rulehost-flag-wiring.test.js +0 -232
- package/dist/commands/__tests__/run-rulehost-flag-wiring.test.js.map +0 -1
- package/dist/commands/__tests__/runtime-activation-nextaction.test.d.ts +0 -15
- package/dist/commands/__tests__/runtime-activation-nextaction.test.d.ts.map +0 -1
- package/dist/commands/__tests__/runtime-activation-nextaction.test.js +0 -73
- package/dist/commands/__tests__/runtime-activation-nextaction.test.js.map +0 -1
- package/dist/commands/__tests__/runtime-probe-config.test.d.ts +0 -20
- package/dist/commands/__tests__/runtime-probe-config.test.d.ts.map +0 -1
- package/dist/commands/__tests__/runtime-probe-config.test.js +0 -389
- package/dist/commands/__tests__/runtime-probe-config.test.js.map +0 -1
- package/dist/commands/__tests__/telemetry-flag-wiring.test.d.ts +0 -9
- package/dist/commands/__tests__/telemetry-flag-wiring.test.d.ts.map +0 -1
- package/dist/commands/__tests__/telemetry-flag-wiring.test.js +0 -76
- package/dist/commands/__tests__/telemetry-flag-wiring.test.js.map +0 -1
- package/dist/commands/__tests__/version.test.d.ts +0 -2
- package/dist/commands/__tests__/version.test.d.ts.map +0 -1
- package/dist/commands/__tests__/version.test.js +0 -238
- package/dist/commands/__tests__/version.test.js.map +0 -1
- package/dist/commands/runtime-uat.guard.test.d.ts +0 -2
- package/dist/commands/runtime-uat.guard.test.d.ts.map +0 -1
- package/dist/commands/runtime-uat.guard.test.js +0 -153
- package/dist/commands/runtime-uat.guard.test.js.map +0 -1
- package/dist/services/__tests__/cli-output.test.d.ts +0 -18
- package/dist/services/__tests__/cli-output.test.d.ts.map +0 -1
- package/dist/services/__tests__/cli-output.test.js +0 -103
- package/dist/services/__tests__/cli-output.test.js.map +0 -1
- package/dist/services/__tests__/evaluator-runner-deps.test.d.ts +0 -2
- package/dist/services/__tests__/evaluator-runner-deps.test.d.ts.map +0 -1
- package/dist/services/__tests__/evaluator-runner-deps.test.js +0 -343
- package/dist/services/__tests__/evaluator-runner-deps.test.js.map +0 -1
- package/dist/services/__tests__/rulehost-readiness.test.d.ts +0 -2
- package/dist/services/__tests__/rulehost-readiness.test.d.ts.map +0 -1
- package/dist/services/__tests__/rulehost-readiness.test.js +0 -311
- package/dist/services/__tests__/rulehost-readiness.test.js.map +0 -1
- package/dist/services/__tests__/runtime-adapter-resolver.test.d.ts +0 -18
- package/dist/services/__tests__/runtime-adapter-resolver.test.d.ts.map +0 -1
- package/dist/services/__tests__/runtime-adapter-resolver.test.js +0 -673
- package/dist/services/__tests__/runtime-adapter-resolver.test.js.map +0 -1
- package/dist/utils/production-workspace-guard.test.d.ts +0 -2
- package/dist/utils/production-workspace-guard.test.d.ts.map +0 -1
- package/dist/utils/production-workspace-guard.test.js +0 -137
- package/dist/utils/production-workspace-guard.test.js.map +0 -1
- package/scripts/llm-dogfood.ts +0 -456
- package/scripts/migrate-illegal-expected-decision.ts +0 -252
- package/src/commands/__tests__/intent-flag-wiring.test.ts +0 -282
- package/src/commands/__tests__/legacy-cleanup.test.ts +0 -602
- package/src/commands/__tests__/mvp-smoke.test.ts +0 -300
- package/src/commands/__tests__/pain-retry-maxTokens-flag.test.ts +0 -73
- package/src/commands/__tests__/rulecode-flag-wiring.test.ts +0 -237
- package/src/commands/__tests__/rulecode-handler.test.ts +0 -369
- package/src/commands/__tests__/run-rulehost-flag-wiring.test.ts +0 -292
- package/src/commands/__tests__/runtime-activation-nextaction.test.ts +0 -81
- package/src/commands/__tests__/runtime-probe-config.test.ts +0 -432
- package/src/commands/__tests__/telemetry-flag-wiring.test.ts +0 -84
- package/src/commands/__tests__/version.test.ts +0 -251
- package/src/commands/admission-gate.ts +0 -30
- package/src/commands/artifact.ts +0 -82
- package/src/commands/build-trajectory-evidence.ts +0 -298
- package/src/commands/candidate.ts +0 -1250
- package/src/commands/codex-ingest-catchup.ts +0 -114
- package/src/commands/codex-ingest-quarantine.ts +0 -127
- package/src/commands/codex-reconcile.ts +0 -84
- package/src/commands/codex-setup.ts +0 -476
- package/src/commands/codex-worker.ts +0 -185
- package/src/commands/command-helpers.ts +0 -24
- package/src/commands/config-doctor.ts +0 -193
- package/src/commands/console.ts +0 -797
- package/src/commands/context.ts +0 -72
- package/src/commands/demo-story-a.ts +0 -241
- package/src/commands/diagnose.ts +0 -756
- package/src/commands/errors-list.ts +0 -441
- package/src/commands/evolution-tasks-list.ts +0 -48
- package/src/commands/evolution-tasks-show.ts +0 -62
- package/src/commands/flow.ts +0 -60
- package/src/commands/health-codex.ts +0 -576
- package/src/commands/health.ts +0 -315
- package/src/commands/history.ts +0 -63
- package/src/commands/intent.ts +0 -457
- package/src/commands/legacy-cleanup.ts +0 -531
- package/src/commands/legacy-import.ts +0 -104
- package/src/commands/mvp-smoke.ts +0 -160
- package/src/commands/pain-evidence.ts +0 -226
- package/src/commands/pain-list.ts +0 -239
- package/src/commands/pain-record.ts +0 -612
- package/src/commands/pain-retry.ts +0 -916
- package/src/commands/principles-stats.ts +0 -700
- package/src/commands/proven-channel-baseline.ts +0 -115
- package/src/commands/quality-scorecard.ts +0 -272
- package/src/commands/remediation-output.ts +0 -66
- package/src/commands/rulecode.ts +0 -465
- package/src/commands/run.ts +0 -89
- package/src/commands/runtime-activation.ts +0 -1629
- package/src/commands/runtime-artifact-repair.ts +0 -524
- package/src/commands/runtime-canary.ts +0 -395
- package/src/commands/runtime-compatibility-scan.ts +0 -105
- package/src/commands/runtime-diagnostics-export.ts +0 -229
- package/src/commands/runtime-features.ts +0 -153
- package/src/commands/runtime-gfi-snapshot.ts +0 -135
- package/src/commands/runtime-health-snapshot.ts +0 -108
- package/src/commands/runtime-init.ts +0 -429
- package/src/commands/runtime-internalization-enqueue-successors.ts +0 -530
- package/src/commands/runtime-internalization-integrity-repair.ts +0 -79
- package/src/commands/runtime-internalization-integrity.ts +0 -107
- package/src/commands/runtime-internalization-queue.ts +0 -135
- package/src/commands/runtime-internalization-retry.ts +0 -191
- package/src/commands/runtime-internalization-run-once.ts +0 -791
- package/src/commands/runtime-internalization-run-rulehost.ts +0 -749
- package/src/commands/runtime-internalization-wake-once.ts +0 -87
- package/src/commands/runtime-pain-flood-simulation.ts +0 -121
- package/src/commands/runtime-pruning.ts +0 -438
- package/src/commands/runtime-recovery-failed-tasks.ts +0 -258
- package/src/commands/runtime-recovery.ts +0 -109
- package/src/commands/runtime-synthetic-baseline.ts +0 -70
- package/src/commands/runtime-uat.guard.test.ts +0 -175
- package/src/commands/runtime-uat.ts +0 -380
- package/src/commands/runtime.ts +0 -473
- package/src/commands/samples-list.ts +0 -39
- package/src/commands/samples-review.ts +0 -36
- package/src/commands/task.ts +0 -271
- package/src/commands/telemetry.ts +0 -349
- package/src/commands/trace.ts +0 -174
- package/src/commands/trajectory-db-unavailable.ts +0 -19
- package/src/commands/trajectory.ts +0 -64
- package/src/commands/version.ts +0 -49
- package/src/config-reader.ts +0 -122
- package/src/index.ts +0 -1276
- package/src/legacy/legacy-import.ts +0 -179
- package/src/legacy/session-history-import.ts +0 -203
- package/src/resolve-workspace.ts +0 -106
- package/src/services/__tests__/cli-output.test.ts +0 -130
- package/src/services/__tests__/evaluator-runner-deps.test.ts +0 -382
- package/src/services/__tests__/rulehost-readiness.test.ts +0 -363
- package/src/services/__tests__/runtime-adapter-resolver.test.ts +0 -793
- package/src/services/cli-output.ts +0 -95
- package/src/services/config-doctor.ts +0 -697
- package/src/services/console-launcher.ts +0 -537
- package/src/services/demo-rule-compiler.ts +0 -40
- package/src/services/demo-story-a-runner.ts +0 -471
- package/src/services/mainline-snapshot-assembler.ts +0 -579
- package/src/services/pain-flood-simulation-runner.ts +0 -462
- package/src/services/pd-config-loader.ts +0 -433
- package/src/services/proven-channel-baseline-runner.ts +0 -157
- package/src/services/quality-scorecard/data-extractor.ts +0 -150
- package/src/services/quality-scorecard/local-evaluator.ts +0 -142
- package/src/services/quality-scorecard/strong-model-gate.ts +0 -202
- package/src/services/resolve-runtime-from-pd-config.ts +0 -230
- package/src/services/rulehost-pipeline-runner.ts +0 -1214
- package/src/services/rulehost-readiness.ts +0 -326
- package/src/services/runtime-adapter-resolver.ts +0 -364
- package/src/services/synthetic-baseline-runner.ts +0 -400
- package/src/services/version-report.ts +0 -253
- package/src/services/workspace-tool-semantics.ts +0 -26
- package/src/utils/path-security.ts +0 -96
- package/src/utils/production-workspace-guard.test.ts +0 -157
- package/src/utils/production-workspace-guard.ts +0 -210
- package/tests/bdd/cli-contract.steps.ts +0 -346
- package/tests/bdd/principles-stats.steps.ts +0 -211
- package/tests/bdd/support/gherkin-loader.ts +0 -147
- package/tests/bdd/support/repo-root.ts +0 -62
- package/tests/bdd/support/vitest-bdd.ts +0 -179
- package/tests/commands/admission-gate-coverage.test.ts +0 -79
- package/tests/commands/build-trajectory-evidence.test.ts +0 -508
- package/tests/commands/candidate-audit-repair.test.ts +0 -421
- package/tests/commands/candidate-intake.test.ts +0 -732
- package/tests/commands/candidate-internalization-backfill.test.ts +0 -548
- package/tests/commands/candidate-internalize-lineage.test.ts +0 -628
- package/tests/commands/candidate-internalize.test.ts +0 -299
- package/tests/commands/candidate-route.test.ts +0 -329
- package/tests/commands/candidate-show.test.ts +0 -95
- package/tests/commands/cli-command-tree.test.ts +0 -144
- package/tests/commands/cli-help-snapshot.test.ts +0 -155
- package/tests/commands/cli-skill-contract.test.ts +0 -121
- package/tests/commands/codex-consent-reversibility.steps.test.ts +0 -299
- package/tests/commands/codex-ingest-quarantine.test.ts +0 -136
- package/tests/commands/codex-setup.test.ts +0 -297
- package/tests/commands/codex-worker-daemon.test.ts +0 -95
- package/tests/commands/codex-worker-registration.test.ts +0 -207
- package/tests/commands/config-doctor.test.ts +0 -336
- package/tests/commands/console-launcher-edge-cases.test.ts +0 -388
- package/tests/commands/console-open.test.ts +0 -1381
- package/tests/commands/context.test.ts +0 -114
- package/tests/commands/demo-story-a.test.ts +0 -318
- package/tests/commands/diagnose.test.ts +0 -1803
- package/tests/commands/errors-list.test.ts +0 -679
- package/tests/commands/evolution-tasks-list.test.ts +0 -41
- package/tests/commands/evolution-tasks-show.test.ts +0 -46
- package/tests/commands/health-codex.test.ts +0 -349
- package/tests/commands/health-host-wiring.test.ts +0 -76
- package/tests/commands/health-reliability.test.ts +0 -99
- package/tests/commands/health.test.ts +0 -413
- package/tests/commands/intent.test.ts +0 -321
- package/tests/commands/legacy-cleanup.test.ts +0 -148
- package/tests/commands/pain-evidence.test.ts +0 -518
- package/tests/commands/pain-list.test.ts +0 -219
- package/tests/commands/pain-record-async.test.ts +0 -335
- package/tests/commands/pain-record-session-parser.test.ts +0 -228
- package/tests/commands/pain-record.test.ts +0 -851
- package/tests/commands/pain-retry.test.ts +0 -1121
- package/tests/commands/plugin-config-resolution-cutover.test.ts +0 -229
- package/tests/commands/pri-393-runtime-config-unification.test.ts +0 -443
- package/tests/commands/principles-stats-wiring.test.ts +0 -135
- package/tests/commands/principles-stats.test.ts +0 -274
- package/tests/commands/product-path-regression.test.ts +0 -86
- package/tests/commands/proven-channel-baseline.test.ts +0 -441
- package/tests/commands/rulecode.test.ts +0 -177
- package/tests/commands/run-rulehost-handler.test.ts +0 -908
- package/tests/commands/runtime-activation-approve-flag-wiring.test.ts +0 -227
- package/tests/commands/runtime-activation-deactivate-flag-wiring.test.ts +0 -167
- package/tests/commands/runtime-activation-dispatch-flag-wiring.test.ts +0 -262
- package/tests/commands/runtime-activation-governance-audit.test.ts +0 -95
- package/tests/commands/runtime-activation-list-flag-wiring.test.ts +0 -193
- package/tests/commands/runtime-activation-promote-flag-wiring.test.ts +0 -248
- package/tests/commands/runtime-activation-shadow-telemetry.test.ts +0 -130
- package/tests/commands/runtime-activation.test.ts +0 -2052
- package/tests/commands/runtime-artifact-repair-registration.test.ts +0 -74
- package/tests/commands/runtime-artifact-repair.test.ts +0 -404
- package/tests/commands/runtime-canary.test.ts +0 -430
- package/tests/commands/runtime-compatibility-scan.test.ts +0 -146
- package/tests/commands/runtime-diagnostics-export.test.ts +0 -175
- package/tests/commands/runtime-features.test.ts +0 -249
- package/tests/commands/runtime-health-snapshot.test.ts +0 -358
- package/tests/commands/runtime-init-empty-workspace.test.ts +0 -252
- package/tests/commands/runtime-init.test.ts +0 -420
- package/tests/commands/runtime-internalization-enqueue-successors.test.ts +0 -782
- package/tests/commands/runtime-internalization-integrity-repair.test.ts +0 -239
- package/tests/commands/runtime-internalization-integrity.test.ts +0 -140
- package/tests/commands/runtime-internalization-queue.test.ts +0 -380
- package/tests/commands/runtime-internalization-retry-owner-authority.test.ts +0 -431
- package/tests/commands/runtime-internalization-run-once-evaluator-parity.test.ts +0 -269
- package/tests/commands/runtime-internalization-run-once-language.test.ts +0 -303
- package/tests/commands/runtime-internalization-run-once-real-config.test.ts +0 -237
- package/tests/commands/runtime-internalization-run-once-rollout-parity.test.ts +0 -706
- package/tests/commands/runtime-internalization-run-once.test.ts +0 -1791
- package/tests/commands/runtime-internalization-wake-once.test.ts +0 -171
- package/tests/commands/runtime-internalization.test.ts +0 -53
- package/tests/commands/runtime-pain-flood-simulation.test.ts +0 -418
- package/tests/commands/runtime-pruning.test.ts +0 -694
- package/tests/commands/runtime-recovery-failed-tasks.test.ts +0 -328
- package/tests/commands/runtime-recovery.test.ts +0 -120
- package/tests/commands/runtime-synthetic-baseline.test.ts +0 -249
- package/tests/commands/runtime-uat.test.ts +0 -397
- package/tests/commands/runtime.test.ts +0 -392
- package/tests/commands/samples-list.test.ts +0 -43
- package/tests/commands/samples-review.test.ts +0 -41
- package/tests/commands/task.test.ts +0 -153
- package/tests/commands/telemetry.test.ts +0 -190
- package/tests/commands/trace.test.ts +0 -316
- package/tests/config-reader.test.ts +0 -143
- package/tests/e2e/candidate-intake-e2e.test.ts +0 -338
- package/tests/e2e/cli-full-flow.test.ts +0 -233
- package/tests/e2e/cross-package-acceptance.test.ts +0 -635
- package/tests/helpers/pd-cli-path.ts +0 -5
- package/tests/pd-cli-smoke.test.ts +0 -13
- package/tests/resolve-workspace.test.ts +0 -196
- package/tests/services/config-doctor-signal-health.test.ts +0 -109
- package/tests/services/console-launcher.test.ts +0 -114
- package/tests/services/demo-rule-compiler.test.ts +0 -242
- package/tests/services/mainline-snapshot-assembler.test.ts +0 -572
- package/tests/services/pd-config-loader.test.ts +0 -505
- package/tests/services/proven-channel-baseline-runner.test.ts +0 -30
- package/tests/services/quality-scorecard/strong-model-gate.test.ts +0 -133
- package/tests/services/resolve-runtime-from-pd-config.test.ts +0 -485
- package/tests/services/rulehost-pipeline-e2e.test.ts +0 -538
- package/tests/services/rulehost-pipeline-runner.test.ts +0 -1242
- package/tests/services/workspace-tool-semantics.test.ts +0 -76
- package/tests/utils/path-security.test.ts +0 -180
- package/tsconfig.json +0 -26
- package/vitest.config.ts +0 -10
|
@@ -1,433 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* PD Config Loader — PRI-305
|
|
3
|
-
*
|
|
4
|
-
* I/O boundary: reads `.pd/config.yaml`, validates via core, computes effective config.
|
|
5
|
-
* This replaces the old `feature-flag-loader.ts` and `workflows.yaml` reading
|
|
6
|
-
* for CLI production paths.
|
|
7
|
-
*
|
|
8
|
-
* ADR-0016: PD owns exactly one user config file.
|
|
9
|
-
* - Missing config → defaults with nextAction
|
|
10
|
-
* - Malformed config → fail loud with errors and nextAction
|
|
11
|
-
* - No secrets in output
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
import * as fs from 'fs';
|
|
15
|
-
import * as path from 'path';
|
|
16
|
-
import * as os from 'os';
|
|
17
|
-
import * as yaml from 'js-yaml';
|
|
18
|
-
import { canonicalPath, isPathInside } from '../utils/path-security.js';
|
|
19
|
-
import {
|
|
20
|
-
validatePdConfig,
|
|
21
|
-
computeEffectivePdConfig,
|
|
22
|
-
computeFeatureFlagsFromConfig,
|
|
23
|
-
isFeatureEnabled,
|
|
24
|
-
redactPdConfig,
|
|
25
|
-
} from '@principles/core/runtime-v2';
|
|
26
|
-
import type {
|
|
27
|
-
EffectivePdConfig,
|
|
28
|
-
PdConfigValidationResult,
|
|
29
|
-
RedactedPdConfigSummary,
|
|
30
|
-
FeatureFlagsResult,
|
|
31
|
-
} from '@principles/core/runtime-v2';
|
|
32
|
-
|
|
33
|
-
// ── Constants ────────────────────────────────────────────────────────────────
|
|
34
|
-
|
|
35
|
-
export const PD_CONFIG_DIR = '.pd';
|
|
36
|
-
export const PD_CONFIG_FILENAME = 'config.yaml';
|
|
37
|
-
|
|
38
|
-
// ── Types ────────────────────────────────────────────────────────────────────
|
|
39
|
-
|
|
40
|
-
export type ConfigSource = 'defaults' | 'user_config' | 'malformed';
|
|
41
|
-
|
|
42
|
-
export interface PdConfigLoadResultOk {
|
|
43
|
-
ok: true;
|
|
44
|
-
effective: EffectivePdConfig;
|
|
45
|
-
source: ConfigSource;
|
|
46
|
-
configPath: string;
|
|
47
|
-
/** Warnings from config resolution (not errors) */
|
|
48
|
-
warnings: string[];
|
|
49
|
-
/** If legacy files were detected */
|
|
50
|
-
legacyFilesDetected: string[];
|
|
51
|
-
/** PRI-404: Next actions for removing legacy files (empty if none detected) */
|
|
52
|
-
legacyFileNextActions: string[];
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export interface PdConfigLoadResultErr {
|
|
56
|
-
ok: false;
|
|
57
|
-
source: 'malformed';
|
|
58
|
-
configPath: string;
|
|
59
|
-
errors: { path: string; reason: string; nextAction: string }[];
|
|
60
|
-
/** Fallback defaults are still available */
|
|
61
|
-
defaults: EffectivePdConfig;
|
|
62
|
-
/** Warnings from config resolution */
|
|
63
|
-
warnings: string[];
|
|
64
|
-
legacyFilesDetected: string[];
|
|
65
|
-
/** PRI-404: Next actions for removing legacy files (empty if none detected) */
|
|
66
|
-
legacyFileNextActions: string[];
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export type PdConfigLoadResult = PdConfigLoadResultOk | PdConfigLoadResultErr;
|
|
70
|
-
|
|
71
|
-
// ── Config Path ──────────────────────────────────────────────────────────────
|
|
72
|
-
|
|
73
|
-
export function getPdConfigPath(workspaceDir: string): string {
|
|
74
|
-
return path.join(workspaceDir, PD_CONFIG_DIR, PD_CONFIG_FILENAME);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// ── Legacy File Detection ────────────────────────────────────────────────────
|
|
78
|
-
|
|
79
|
-
function detectLegacyFiles(workspaceDir: string): string[] {
|
|
80
|
-
const detected: string[] = [];
|
|
81
|
-
const legacyPaths = [
|
|
82
|
-
path.join(workspaceDir, PD_CONFIG_DIR, 'feature-flags.yaml'),
|
|
83
|
-
path.join(workspaceDir, '.state', 'workflows.yaml'),
|
|
84
|
-
];
|
|
85
|
-
for (const p of legacyPaths) {
|
|
86
|
-
if (fs.existsSync(p)) {
|
|
87
|
-
detected.push(p);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
return detected;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/** PRI-404: Generate nextAction suggestions for removing legacy files. */
|
|
94
|
-
function buildLegacyFileNextActions(legacyFiles: string[]): string[] {
|
|
95
|
-
return legacyFiles.map(f => {
|
|
96
|
-
return `Run 'rm ${f}' to remove legacy config`;
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// ── Load PD Config ───────────────────────────────────────────────────────────
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Load and validate `.pd/config.yaml` from the workspace.
|
|
104
|
-
*
|
|
105
|
-
* - Missing file → returns defaults with source='defaults'
|
|
106
|
-
* - Malformed file → returns error result with defaults fallback
|
|
107
|
-
* - Valid file → returns effective config with source='user_config'
|
|
108
|
-
*
|
|
109
|
-
* Never throws on malformed input. Always provides a usable fallback.
|
|
110
|
-
*/
|
|
111
|
-
export function loadPdConfig(workspaceDir: string): PdConfigLoadResult {
|
|
112
|
-
const configPath = getPdConfigPath(workspaceDir);
|
|
113
|
-
const legacyFilesDetected = detectLegacyFiles(workspaceDir);
|
|
114
|
-
const legacyFileNextActions = buildLegacyFileNextActions(legacyFilesDetected);
|
|
115
|
-
|
|
116
|
-
// 1) Config file missing → use defaults
|
|
117
|
-
if (!fs.existsSync(configPath)) {
|
|
118
|
-
const effective = computeEffectivePdConfig(null);
|
|
119
|
-
return {
|
|
120
|
-
ok: true,
|
|
121
|
-
effective,
|
|
122
|
-
source: 'defaults',
|
|
123
|
-
configPath,
|
|
124
|
-
warnings: [
|
|
125
|
-
...effective.warnings,
|
|
126
|
-
...(legacyFilesDetected.length > 0
|
|
127
|
-
? [`Legacy config files detected (${legacyFilesDetected.length}): ${legacyFilesDetected.join(', ')}. PD now uses .pd/config.yaml.`]
|
|
128
|
-
: []),
|
|
129
|
-
],
|
|
130
|
-
legacyFilesDetected,
|
|
131
|
-
legacyFileNextActions,
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// 2) Read the file
|
|
136
|
-
let raw: string;
|
|
137
|
-
try {
|
|
138
|
-
raw = fs.readFileSync(configPath, 'utf8');
|
|
139
|
-
} catch (err) {
|
|
140
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
141
|
-
const effective = computeEffectivePdConfig(null);
|
|
142
|
-
return {
|
|
143
|
-
ok: false,
|
|
144
|
-
source: 'malformed',
|
|
145
|
-
configPath,
|
|
146
|
-
errors: [{ path: '', reason: `Failed to read .pd/config.yaml: ${message}`, nextAction: 'Check file permissions for .pd/config.yaml' }],
|
|
147
|
-
warnings: [],
|
|
148
|
-
defaults: effective,
|
|
149
|
-
legacyFilesDetected,
|
|
150
|
-
legacyFileNextActions,
|
|
151
|
-
};
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
// 3) Parse YAML — treat as unknown (ERR-001)
|
|
155
|
-
let parsed: unknown;
|
|
156
|
-
try {
|
|
157
|
-
parsed = yaml.load(raw, { schema: yaml.JSON_SCHEMA });
|
|
158
|
-
} catch (err) {
|
|
159
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
160
|
-
const effective = computeEffectivePdConfig(null);
|
|
161
|
-
return {
|
|
162
|
-
ok: false,
|
|
163
|
-
source: 'malformed',
|
|
164
|
-
configPath,
|
|
165
|
-
errors: [{ path: '', reason: `YAML parse error in .pd/config.yaml: ${message}`, nextAction: 'Fix YAML syntax in .pd/config.yaml' }],
|
|
166
|
-
warnings: [],
|
|
167
|
-
defaults: effective,
|
|
168
|
-
legacyFilesDetected,
|
|
169
|
-
legacyFileNextActions,
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
// 4) Validate via core (ERR-001, ERR-005: no `as` bypasses)
|
|
174
|
-
const validationResult: PdConfigValidationResult = validatePdConfig(parsed);
|
|
175
|
-
|
|
176
|
-
if (!validationResult.ok) {
|
|
177
|
-
const effective = computeEffectivePdConfig(null);
|
|
178
|
-
return {
|
|
179
|
-
ok: false,
|
|
180
|
-
source: 'malformed',
|
|
181
|
-
configPath,
|
|
182
|
-
errors: validationResult.errors.map(e => ({
|
|
183
|
-
path: e.path,
|
|
184
|
-
reason: e.reason,
|
|
185
|
-
nextAction: e.nextAction,
|
|
186
|
-
})),
|
|
187
|
-
warnings: [],
|
|
188
|
-
defaults: effective,
|
|
189
|
-
legacyFilesDetected,
|
|
190
|
-
legacyFileNextActions,
|
|
191
|
-
};
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
// 5) Compute effective config
|
|
195
|
-
const effective = computeEffectivePdConfig(validationResult.value);
|
|
196
|
-
|
|
197
|
-
return {
|
|
198
|
-
ok: true,
|
|
199
|
-
effective,
|
|
200
|
-
source: 'user_config',
|
|
201
|
-
configPath,
|
|
202
|
-
warnings: [
|
|
203
|
-
...effective.warnings,
|
|
204
|
-
...validationResult.warnings,
|
|
205
|
-
...(legacyFilesDetected.length > 0
|
|
206
|
-
? [`Legacy config files detected (${legacyFilesDetected.length}): ${legacyFilesDetected.join(', ')}. PD now uses .pd/config.yaml.`]
|
|
207
|
-
: []),
|
|
208
|
-
],
|
|
209
|
-
legacyFilesDetected,
|
|
210
|
-
legacyFileNextActions,
|
|
211
|
-
};
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
// ── Feature Flags from Config ────────────────────────────────────────────────
|
|
215
|
-
|
|
216
|
-
/**
|
|
217
|
-
* Flags whose production gate FAILS CLOSED when the workspace config cannot
|
|
218
|
-
* be loaded: the gate cannot know the flag state, so the gated capability is
|
|
219
|
-
* suspended (OpenClaw `buildRuleContextIfEnabled` returns undefined context on
|
|
220
|
-
* config failure → v2 rules skip). Status derivation must mirror that posture
|
|
221
|
-
* or the CLI would display "active" for rules that are actually not
|
|
222
|
-
* enforcing (PRI-780 review B3).
|
|
223
|
-
*/
|
|
224
|
-
const CONFIG_FAILURE_FAIL_CLOSED_FLAGS: ReadonlySet<string> = new Set(['rulecode_context_v2']);
|
|
225
|
-
|
|
226
|
-
/**
|
|
227
|
-
* Compute feature flags from the loaded PD config.
|
|
228
|
-
* Works with both ok and error results (uses defaults for errors).
|
|
229
|
-
*
|
|
230
|
-
* On a failed load, flags whose gate fail-closes on config errors are forced
|
|
231
|
-
* disabled with an observable warning — the registry default (ON for a
|
|
232
|
-
* graduated flag) must never be displayed as enforcing when the workspace
|
|
233
|
-
* config is unreadable.
|
|
234
|
-
*/
|
|
235
|
-
export function computeFlagsFromLoadResult(result: PdConfigLoadResult): FeatureFlagsResult {
|
|
236
|
-
const effective = result.ok ? result.effective : result.defaults;
|
|
237
|
-
const flags = computeFeatureFlagsFromConfig(effective);
|
|
238
|
-
if (!result.ok) {
|
|
239
|
-
for (const flagId of CONFIG_FAILURE_FAIL_CLOSED_FLAGS) {
|
|
240
|
-
const flag = flags.flags[flagId];
|
|
241
|
-
if (flag?.enabled) {
|
|
242
|
-
flags.flags[flagId] = { ...flag, enabled: false };
|
|
243
|
-
flags.warnings.push(`${flagId}: config load failed — flag treated as disabled (fail-closed, matches the gate's config-failure suspension)`);
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
return flags;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
/**
|
|
251
|
-
* PRI-720: resolve the seed-time full-chain override for prompt/defer_archive
|
|
252
|
-
* internalization chains from the `prompt_full_pipeline` feature flag
|
|
253
|
-
* (Owner switch: Console settings toggle or `.pd/config.yaml` features).
|
|
254
|
-
* Returns undefined (= standard channel-aware topology) when the flag is off
|
|
255
|
-
* or the config is unreadable — absence is the legacy-compatible default.
|
|
256
|
-
* Resolve ONCE per command invocation and pass the value to every seed call.
|
|
257
|
-
*/
|
|
258
|
-
export function resolvePromptFullPipelineSeedMode(workspaceDir: string): 'full_chain' | undefined {
|
|
259
|
-
const flags = computeFlagsFromLoadResult(loadPdConfig(workspaceDir));
|
|
260
|
-
return isFeatureEnabled(flags, 'prompt_full_pipeline') ? 'full_chain' : undefined;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
// ── Redacted Summary from Config ─────────────────────────────────────────────
|
|
264
|
-
|
|
265
|
-
/**
|
|
266
|
-
* Produce a redacted summary of the PD config for CLI/Console display.
|
|
267
|
-
* Never includes token/API key values or raw provider objects.
|
|
268
|
-
*/
|
|
269
|
-
export function redactLoadResult(result: PdConfigLoadResult): RedactedPdConfigSummary {
|
|
270
|
-
const effective = result.ok ? result.effective : result.defaults;
|
|
271
|
-
return redactPdConfig(effective);
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
// ── Workspace Discovery ──────────────────────────────────────────────────────
|
|
275
|
-
|
|
276
|
-
/** Result of workspace.default discovery from config files. */
|
|
277
|
-
export interface WorkspaceDiscoveryResult {
|
|
278
|
-
/** The extracted workspace.default path. */
|
|
279
|
-
workspaceDefault: string;
|
|
280
|
-
/** Path to the config file that provided workspace.default. */
|
|
281
|
-
configPath: string;
|
|
282
|
-
/** How the config location was found. */
|
|
283
|
-
source: 'env_var' | 'openclaw_default' | 'openclaw_plugin_config';
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
287
|
-
return value !== null && value !== undefined && typeof value === 'object' && !Array.isArray(value);
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
/** Check if a path is absolute (Windows or POSIX). */
|
|
291
|
-
function isAbsolutePath(p: string): boolean {
|
|
292
|
-
return /^[A-Za-z]:[\\/]/.test(p) || p.startsWith('\\\\') || p.startsWith('/');
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
/**
|
|
296
|
-
* Lightweight extraction of workspace.default from a config file.
|
|
297
|
-
* Does NOT run full validation — just parses YAML and reads the field.
|
|
298
|
-
* Rejects relative paths to prevent PD from writing to unpredictable locations.
|
|
299
|
-
*/
|
|
300
|
-
function extractWorkspaceDefault(configPath: string): string | null {
|
|
301
|
-
try {
|
|
302
|
-
const raw = fs.readFileSync(configPath, 'utf8');
|
|
303
|
-
const parsed: unknown = yaml.load(raw, { schema: yaml.JSON_SCHEMA });
|
|
304
|
-
if (
|
|
305
|
-
isRecord(parsed) &&
|
|
306
|
-
isRecord(parsed.workspace) &&
|
|
307
|
-
typeof parsed.workspace.default === 'string' &&
|
|
308
|
-
parsed.workspace.default.length > 0 &&
|
|
309
|
-
isAbsolutePath(parsed.workspace.default)
|
|
310
|
-
) {
|
|
311
|
-
return parsed.workspace.default;
|
|
312
|
-
}
|
|
313
|
-
} catch (err) {
|
|
314
|
-
// Graceful degradation with observability: log but don't throw
|
|
315
|
-
process.stderr.write(
|
|
316
|
-
`[PD:workspace] WARN: Failed to parse workspace config at ${configPath}: ${err instanceof Error ? err.message : String(err)}\n`,
|
|
317
|
-
);
|
|
318
|
-
}
|
|
319
|
-
return null;
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
/**
|
|
323
|
-
* Read the OpenClaw plugin config file for workspace field.
|
|
324
|
-
* Reuses the same search locations as PathResolver.
|
|
325
|
-
* Returns null if no valid config is found (graceful degradation).
|
|
326
|
-
*/
|
|
327
|
-
function loadOpenClawPluginConfig(): { workspace?: string } | null {
|
|
328
|
-
const configLocations = [
|
|
329
|
-
path.join(process.cwd(), 'principles-disciple.json'),
|
|
330
|
-
path.join(os.homedir(), '.openclaw', 'principles-disciple.json'),
|
|
331
|
-
path.join(os.homedir(), '.principles', 'principles-disciple.json'),
|
|
332
|
-
];
|
|
333
|
-
for (const loc of configLocations) {
|
|
334
|
-
if (fs.existsSync(loc)) {
|
|
335
|
-
try {
|
|
336
|
-
const content = fs.readFileSync(loc, 'utf8');
|
|
337
|
-
const parsed: unknown = JSON.parse(content);
|
|
338
|
-
// Runtime type guard: validate workspace is a non-empty string
|
|
339
|
-
if (
|
|
340
|
-
parsed !== null &&
|
|
341
|
-
typeof parsed === 'object' &&
|
|
342
|
-
!Array.isArray(parsed) &&
|
|
343
|
-
Object.hasOwn(parsed, 'workspace') &&
|
|
344
|
-
typeof (parsed as Record<string, unknown>).workspace === 'string' &&
|
|
345
|
-
((parsed as Record<string, unknown>).workspace as string).length > 0
|
|
346
|
-
) {
|
|
347
|
-
return { workspace: (parsed as Record<string, unknown>).workspace as string };
|
|
348
|
-
}
|
|
349
|
-
} catch (err) {
|
|
350
|
-
// Graceful degradation with observability: log but continue to next location
|
|
351
|
-
process.stderr.write(
|
|
352
|
-
`[PD:workspace] WARN: Failed to parse plugin config at ${loc}: ${err instanceof Error ? err.message : String(err)}\n`,
|
|
353
|
-
);
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
return null;
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
/**
|
|
361
|
-
* Validate a candidate config directory before it is joined into a config
|
|
362
|
-
* path for filesystem reads. Candidate dirs are operator-supplied
|
|
363
|
-
* (PD_WORKSPACE_DIR / plugin config / home default), so we normalize with
|
|
364
|
-
* `path.normalize` (pure string, no filesystem access), then reject empty,
|
|
365
|
-
* parent-traversal, or root paths. This keeps the subsequent
|
|
366
|
-
* `path.join(dir, PD_CONFIG_DIR, ...)` inside the intended directory
|
|
367
|
-
* boundary (CWE-22 mitigation).
|
|
368
|
-
*
|
|
369
|
-
* Platform note: no `path.isAbsolute` check — absolute-ness is
|
|
370
|
-
* platform-dependent (a Windows-style path is not absolute on POSIX
|
|
371
|
-
* runners) and relative dirs resolve inside cwd without traversal risk.
|
|
372
|
-
*/
|
|
373
|
-
function assertConfigDirBoundary(dir: string, source: string): void {
|
|
374
|
-
if (!dir || dir.trim().length === 0) {
|
|
375
|
-
throw new Error(`Invalid config search dir (${source}): path is empty`);
|
|
376
|
-
}
|
|
377
|
-
const normalized = path.normalize(dir);
|
|
378
|
-
if (normalized.split(/[\\/]/).includes('..')) {
|
|
379
|
-
throw new Error(`Invalid config search dir (${source}): "${dir}" contains parent traversal`);
|
|
380
|
-
}
|
|
381
|
-
if (normalized === path.parse(normalized).root) {
|
|
382
|
-
throw new Error(`Invalid config search dir (${source}): "${dir}" resolves to filesystem root`);
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
/**
|
|
387
|
-
* Search known locations for a .pd/config.yaml that contains a workspace.default field.
|
|
388
|
-
* This runs BEFORE workspace resolution and does NOT require knowing the workspace dir.
|
|
389
|
-
*
|
|
390
|
-
* Returns the extracted workspace.default path, or null if not found.
|
|
391
|
-
*/
|
|
392
|
-
export function discoverWorkspaceDefault(): WorkspaceDiscoveryResult | null {
|
|
393
|
-
const candidates: { dir: string; source: 'env_var' | 'openclaw_default' | 'openclaw_plugin_config' }[] = [];
|
|
394
|
-
|
|
395
|
-
// 1. If PD_WORKSPACE_DIR is set, check there first
|
|
396
|
-
const envWorkspace = process.env.PD_WORKSPACE_DIR?.trim();
|
|
397
|
-
if (envWorkspace) {
|
|
398
|
-
candidates.push({ dir: envWorkspace, source: 'env_var' });
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
// 2. OpenClaw default workspace
|
|
402
|
-
const homeDir = os.homedir();
|
|
403
|
-
candidates.push({
|
|
404
|
-
dir: path.join(homeDir, '.openclaw', 'workspace'),
|
|
405
|
-
source: 'openclaw_default',
|
|
406
|
-
});
|
|
407
|
-
|
|
408
|
-
// 3. OpenClaw plugin config (principles-disciple.json) may have workspace field
|
|
409
|
-
const pluginConfig = loadOpenClawPluginConfig();
|
|
410
|
-
if (pluginConfig?.workspace) {
|
|
411
|
-
candidates.push({ dir: pluginConfig.workspace, source: 'openclaw_plugin_config' });
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
// Search each candidate for .pd/config.yaml with workspace.default
|
|
415
|
-
for (const { dir, source } of candidates) {
|
|
416
|
-
assertConfigDirBoundary(dir, source);
|
|
417
|
-
// CWE-22: resolve the candidate root once, then verify the joined config
|
|
418
|
-
// path stays inside that root before any filesystem access.
|
|
419
|
-
const candidateRoot = canonicalPath(dir);
|
|
420
|
-
const configPath = path.resolve(candidateRoot, PD_CONFIG_DIR, PD_CONFIG_FILENAME);
|
|
421
|
-
if (!isPathInside(candidateRoot, configPath)) {
|
|
422
|
-
throw new Error(`Invalid config search dir (${source}): "${dir}" escapes its boundary`);
|
|
423
|
-
}
|
|
424
|
-
if (fs.existsSync(configPath)) {
|
|
425
|
-
const workspaceDefault = extractWorkspaceDefault(configPath);
|
|
426
|
-
if (workspaceDefault) {
|
|
427
|
-
return { workspaceDefault, configPath, source };
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
return null;
|
|
433
|
-
}
|
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
import * as path from 'path';
|
|
2
|
-
import * as os from 'os';
|
|
3
|
-
import {
|
|
4
|
-
runPromptFixture,
|
|
5
|
-
runRuleHostFixture,
|
|
6
|
-
runDeferArchiveFixture,
|
|
7
|
-
computeProvenChannelStatus,
|
|
8
|
-
generateContinuityMatrix,
|
|
9
|
-
recommendProvenChannelNextIssue,
|
|
10
|
-
isMvpChannel,
|
|
11
|
-
MVP_CHANNELS,
|
|
12
|
-
} from '@principles/core/runtime-v2';
|
|
13
|
-
import type {
|
|
14
|
-
ChannelFixtureResult,
|
|
15
|
-
ProvenChannelBaselineSummary,
|
|
16
|
-
MvpChannel,
|
|
17
|
-
} from '@principles/core/runtime-v2';
|
|
18
|
-
|
|
19
|
-
export interface ProvenChannelBaselineRunnerOptions {
|
|
20
|
-
workspaceDir: string;
|
|
21
|
-
workspaceMode: 'temp' | 'explicit_workspace';
|
|
22
|
-
channels?: MvpChannel[];
|
|
23
|
-
unknownChannels?: string[];
|
|
24
|
-
emptyChannelInput?: boolean;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function isProductionWorkspace(workspaceDir: string): boolean {
|
|
28
|
-
const normalized = path.resolve(workspaceDir).toLowerCase();
|
|
29
|
-
const productionPrefixes: string[] = [
|
|
30
|
-
path.resolve(path.join(os.homedir(), '.openclaw', 'workspace')).toLowerCase(),
|
|
31
|
-
];
|
|
32
|
-
// Allow operator to declare additional production paths (cross-platform).
|
|
33
|
-
// Use path.delimiter (; on Windows, : on Unix) to separate multiple paths.
|
|
34
|
-
const extra = process.env.PD_PRODUCTION_WORKSPACE;
|
|
35
|
-
if (extra) {
|
|
36
|
-
for (const p of extra.split(path.delimiter)) {
|
|
37
|
-
const trimmed = p.trim();
|
|
38
|
-
if (trimmed) productionPrefixes.push(path.resolve(trimmed).toLowerCase());
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
for (const prefix of productionPrefixes) {
|
|
42
|
-
if (normalized === prefix || normalized.startsWith(prefix + path.sep)) {
|
|
43
|
-
return true;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
return false;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export async function runProvenChannelBaseline(
|
|
50
|
-
opts: ProvenChannelBaselineRunnerOptions,
|
|
51
|
-
): Promise<ProvenChannelBaselineSummary> {
|
|
52
|
-
const { workspaceDir, workspaceMode } = opts;
|
|
53
|
-
const channels = opts.channels ?? [...MVP_CHANNELS];
|
|
54
|
-
const unknownChannels = opts.unknownChannels ?? [];
|
|
55
|
-
const emptyChannelInput = opts.emptyChannelInput ?? false;
|
|
56
|
-
const generatedAt = new Date().toISOString();
|
|
57
|
-
|
|
58
|
-
if (emptyChannelInput) {
|
|
59
|
-
return {
|
|
60
|
-
status: 'failed',
|
|
61
|
-
generatedAt,
|
|
62
|
-
workspaceMode,
|
|
63
|
-
channels: [],
|
|
64
|
-
inputValidationFailure: {
|
|
65
|
-
reason: 'empty_channel_input',
|
|
66
|
-
message: '--channels was provided but contained no valid channel names',
|
|
67
|
-
nextAction: 'Provide at least one valid MVP channel: prompt, code_tool_hook, defer_archive',
|
|
68
|
-
},
|
|
69
|
-
continuityMatrix: generateContinuityMatrix(),
|
|
70
|
-
recommendedNextIssue: 'PRI-240: --channels input was empty — no fixtures were executed',
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
if (unknownChannels.length > 0) {
|
|
75
|
-
return {
|
|
76
|
-
status: 'failed',
|
|
77
|
-
generatedAt,
|
|
78
|
-
workspaceMode,
|
|
79
|
-
channels: [],
|
|
80
|
-
inputValidationFailure: {
|
|
81
|
-
reason: 'unknown_channels',
|
|
82
|
-
message: `Unknown channels: ${unknownChannels.join(', ')}. Valid channels: prompt, code_tool_hook, defer_archive`,
|
|
83
|
-
nextAction: 'Use only valid MVP channels: prompt, code_tool_hook, defer_archive',
|
|
84
|
-
unknownChannels,
|
|
85
|
-
},
|
|
86
|
-
continuityMatrix: generateContinuityMatrix(),
|
|
87
|
-
recommendedNextIssue: `PRI-240: Unknown channels provided: ${unknownChannels.join(', ')}`,
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
if (isProductionWorkspace(workspaceDir)) {
|
|
92
|
-
return {
|
|
93
|
-
status: 'failed',
|
|
94
|
-
generatedAt,
|
|
95
|
-
workspaceMode,
|
|
96
|
-
channels: [],
|
|
97
|
-
inputValidationFailure: {
|
|
98
|
-
reason: 'production_workspace_blocked',
|
|
99
|
-
message: 'Baseline must not write to production workspace',
|
|
100
|
-
nextAction: 'Use a temp workspace or explicit non-production directory',
|
|
101
|
-
},
|
|
102
|
-
continuityMatrix: generateContinuityMatrix(),
|
|
103
|
-
recommendedNextIssue: 'PRI-240: Production workspace blocked — use temp workspace',
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const results: ChannelFixtureResult[] = [];
|
|
108
|
-
|
|
109
|
-
for (const channel of channels) {
|
|
110
|
-
if (!isMvpChannel(channel)) {
|
|
111
|
-
continue;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
let result: ChannelFixtureResult = {
|
|
115
|
-
channel,
|
|
116
|
-
status: 'failed',
|
|
117
|
-
canActivateResult: { ok: false, reason: 'unsupported_channel', riskLevel: 'low' },
|
|
118
|
-
activationDecision: { decision: 'refused', reason: 'unsupported_channel', channel },
|
|
119
|
-
evidence: {},
|
|
120
|
-
failureReason: `Channel ${channel} is not an MVP channel`,
|
|
121
|
-
nextAction: 'Use one of: prompt, code_tool_hook, defer_archive',
|
|
122
|
-
dependsOnLegacy: false,
|
|
123
|
-
evidenceSource: 'channel_validation',
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
switch (channel) {
|
|
127
|
-
case 'prompt':
|
|
128
|
-
result = await runPromptFixture();
|
|
129
|
-
break;
|
|
130
|
-
case 'code_tool_hook':
|
|
131
|
-
result = await runRuleHostFixture();
|
|
132
|
-
break;
|
|
133
|
-
case 'defer_archive':
|
|
134
|
-
result = await runDeferArchiveFixture();
|
|
135
|
-
break;
|
|
136
|
-
default: {
|
|
137
|
-
const _exhaustive: never = channel;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
results.push(result);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
const status = computeProvenChannelStatus(results);
|
|
145
|
-
const continuityMatrix = generateContinuityMatrix();
|
|
146
|
-
|
|
147
|
-
return {
|
|
148
|
-
status,
|
|
149
|
-
generatedAt,
|
|
150
|
-
workspaceMode,
|
|
151
|
-
channels: results,
|
|
152
|
-
continuityMatrix,
|
|
153
|
-
recommendedNextIssue: recommendProvenChannelNextIssue(results),
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
export { isProductionWorkspace };
|