@deftai/directive-core 0.104.0 → 0.105.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/authz/classify.js +526 -42
- package/dist/check/cached-orchestrator.d.ts +1 -1
- package/dist/check/cached-orchestrator.js +2 -2
- package/dist/check/named-cause.d.ts +1 -1
- package/dist/check/named-cause.js +33 -3
- package/dist/codebase/default-extractor.d.ts +5 -0
- package/dist/codebase/default-extractor.js +7 -15
- package/dist/deposit/copy-tree.js +60 -0
- package/dist/deposit/python-free.js +26 -18
- package/dist/doctor/checks.d.ts +8 -0
- package/dist/doctor/checks.js +37 -25
- package/dist/doctor/doctor-state.d.ts +4 -0
- package/dist/doctor/doctor-state.js +7 -1
- package/dist/doctor/main.js +9 -19
- package/dist/doctor/types.d.ts +9 -0
- package/dist/fs/contained-write.d.ts +115 -1
- package/dist/fs/contained-write.js +241 -5
- package/dist/fs/mutation-ledger.d.ts +54 -0
- package/dist/fs/mutation-ledger.js +133 -0
- package/dist/fs/non-product-dirs.d.ts +79 -0
- package/dist/fs/non-product-dirs.js +96 -0
- package/dist/hooks/dispatcher.d.ts +3 -1
- package/dist/hooks/dispatcher.js +14 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/init-deposit/agent-hooks.js +17 -15
- package/dist/init-deposit/core-guard-pin-content.d.ts +7 -0
- package/dist/init-deposit/core-guard-pin-content.js +393 -0
- package/dist/init-deposit/gitignore.js +9 -0
- package/dist/init-deposit/hygiene.d.ts +47 -11
- package/dist/init-deposit/hygiene.js +172 -37
- package/dist/init-deposit/legacy-detect.js +6 -2
- package/dist/init-deposit/refresh.d.ts +21 -1
- package/dist/init-deposit/refresh.js +106 -9
- package/dist/init-deposit/scaffold.js +28 -279
- package/dist/init-deposit/slash-deposit.js +13 -7
- package/dist/init-deposit/xbrief-projections.d.ts +8 -1
- package/dist/init-deposit/xbrief-projections.js +24 -11
- package/dist/intake/clause-derivation.d.ts +38 -1
- package/dist/intake/clause-derivation.js +211 -9
- package/dist/intake/issue-ingest.d.ts +3 -1
- package/dist/intake/issue-ingest.js +35 -6
- package/dist/lifecycle/completed-tracked-on-delivery.d.ts +5 -0
- package/dist/lifecycle/completed-tracked-on-delivery.js +85 -18
- package/dist/literal-acceptance/capture.d.ts +10 -0
- package/dist/literal-acceptance/capture.js +224 -75
- package/dist/literal-acceptance/evaluate.d.ts +29 -4
- package/dist/literal-acceptance/evaluate.js +70 -2
- package/dist/literal-acceptance/index.d.ts +3 -3
- package/dist/literal-acceptance/index.js +3 -3
- package/dist/literal-acceptance/safety.d.ts +41 -0
- package/dist/literal-acceptance/safety.js +126 -2
- package/dist/literal-acceptance/types.d.ts +8 -0
- package/dist/orphan-active/evaluate.d.ts +7 -1
- package/dist/orphan-active/evaluate.js +102 -23
- package/dist/platform/platform-capabilities.js +2 -3
- package/dist/policy/base-branch.d.ts +37 -0
- package/dist/policy/base-branch.js +114 -0
- package/dist/policy/branch-sync.d.ts +80 -0
- package/dist/policy/branch-sync.js +211 -0
- package/dist/policy/ceremony-dial-escalation.js +1 -0
- package/dist/policy/ceremony-dial.js +4 -14
- package/dist/policy/delivery-branch.d.ts +5 -3
- package/dist/policy/delivery-branch.js +7 -3
- package/dist/policy/file-size-thresholds.d.ts +24 -0
- package/dist/policy/file-size-thresholds.js +23 -0
- package/dist/policy/forge-outage-retry.d.ts +47 -0
- package/dist/policy/forge-outage-retry.js +157 -0
- package/dist/policy/index.d.ts +7 -0
- package/dist/policy/index.js +66 -7
- package/dist/policy/project-invariants.d.ts +50 -0
- package/dist/policy/project-invariants.js +205 -0
- package/dist/policy/sync-default.d.ts +129 -0
- package/dist/policy/sync-default.js +452 -0
- package/dist/policy/sync-max-files.d.ts +93 -0
- package/dist/policy/sync-max-files.js +192 -0
- package/dist/pr-monitor/absent-required.d.ts +11 -0
- package/dist/pr-monitor/absent-required.js +61 -0
- package/dist/pr-monitor/constants.d.ts +7 -0
- package/dist/pr-monitor/constants.js +7 -0
- package/dist/pr-monitor/index.d.ts +2 -1
- package/dist/pr-monitor/index.js +2 -1
- package/dist/pr-monitor/main.js +4 -0
- package/dist/pr-monitor/monitor.js +24 -1
- package/dist/pr-wait-mergeable/classify.js +6 -0
- package/dist/preflight/evaluate.d.ts +4 -0
- package/dist/preflight/evaluate.js +35 -1
- package/dist/preflight/index.d.ts +4 -0
- package/dist/preflight/index.js +2 -0
- package/dist/preflight/intended-placement.d.ts +62 -0
- package/dist/preflight/intended-placement.js +275 -0
- package/dist/preflight/project-invariants-gate.d.ts +29 -0
- package/dist/preflight/project-invariants-gate.js +82 -0
- package/dist/product-first-done-gate/acceptance-resolver.d.ts +128 -0
- package/dist/product-first-done-gate/acceptance-resolver.js +144 -0
- package/dist/product-first-done-gate/acceptance.d.ts +7 -4
- package/dist/product-first-done-gate/acceptance.js +79 -8
- package/dist/product-first-done-gate/empty-resolution.d.ts +4 -1
- package/dist/product-first-done-gate/empty-resolution.js +12 -1
- package/dist/product-first-done-gate/evaluate.d.ts +12 -0
- package/dist/product-first-done-gate/evaluate.js +254 -31
- package/dist/product-first-done-gate/index.d.ts +2 -0
- package/dist/product-first-done-gate/index.js +1 -0
- package/dist/release/build-dist.d.ts +101 -0
- package/dist/release/build-dist.js +428 -46
- package/dist/run-summary/emit.d.ts +16 -10
- package/dist/run-summary/emit.js +26 -15
- package/dist/run-summary/index.d.ts +3 -2
- package/dist/run-summary/index.js +2 -1
- package/dist/run-summary/session-id.d.ts +21 -0
- package/dist/run-summary/session-id.js +92 -0
- package/dist/run-summary/types.d.ts +29 -4
- package/dist/run-summary/types.js +1 -0
- package/dist/scope/acceptance-evidence.d.ts +19 -7
- package/dist/scope/acceptance-evidence.js +38 -11
- package/dist/scope/delivery-evidence.d.ts +3 -3
- package/dist/scope/delivery-evidence.js +22 -27
- package/dist/scope/index.d.ts +1 -0
- package/dist/scope/index.js +1 -0
- package/dist/scope/parent-lineage.js +7 -6
- package/dist/scope/project-invariant-coverage.d.ts +54 -0
- package/dist/scope/project-invariant-coverage.js +322 -0
- package/dist/scope/transition.js +1 -1
- package/dist/scope-provenance/compare-intent.d.ts +27 -0
- package/dist/scope-provenance/compare-intent.js +233 -0
- package/dist/scope-provenance/digest.d.ts +18 -1
- package/dist/scope-provenance/digest.js +16 -11
- package/dist/scope-provenance/evaluate.d.ts +5 -1
- package/dist/scope-provenance/evaluate.js +64 -4
- package/dist/scope-provenance/extract-intent.d.ts +43 -0
- package/dist/scope-provenance/extract-intent.js +262 -0
- package/dist/scope-provenance/index.d.ts +7 -1
- package/dist/scope-provenance/index.js +7 -1
- package/dist/scope-provenance/intent-digest.d.ts +12 -0
- package/dist/scope-provenance/intent-digest.js +33 -0
- package/dist/scope-provenance/intent-evaluate.d.ts +43 -0
- package/dist/scope-provenance/intent-evaluate.js +149 -0
- package/dist/scope-provenance/json-tokenizer.d.ts +19 -0
- package/dist/scope-provenance/json-tokenizer.js +225 -0
- package/dist/scope-provenance/known-machine.d.ts +38 -0
- package/dist/scope-provenance/known-machine.js +157 -0
- package/dist/scope-provenance/mint-artifacts.d.ts +102 -0
- package/dist/scope-provenance/mint-artifacts.js +425 -0
- package/dist/session/ac-pass-banking.d.ts +4 -36
- package/dist/session/ac-pass-banking.js +30 -77
- package/dist/session/ac-pass-reuse.d.ts +53 -0
- package/dist/session/ac-pass-reuse.js +95 -0
- package/dist/session/git.js +19 -4
- package/dist/session/index.d.ts +4 -0
- package/dist/session/index.js +4 -0
- package/dist/session/occupancy-stress-worker.d.ts +7 -0
- package/dist/session/occupancy-stress-worker.js +36 -0
- package/dist/session/occupancy.d.ts +97 -0
- package/dist/session/occupancy.js +422 -0
- package/dist/session/openclaw-soft-rebind-deposit.js +6 -6
- package/dist/session/product-state-hash.d.ts +26 -0
- package/dist/session/product-state-hash.js +683 -0
- package/dist/session/session-ready.d.ts +2 -0
- package/dist/session/session-ready.js +52 -30
- package/dist/session/session-start.d.ts +7 -0
- package/dist/session/session-start.js +71 -7
- package/dist/session/verify-ac-session-cache.d.ts +42 -0
- package/dist/session/verify-ac-session-cache.js +126 -0
- package/dist/session/verify-session-ritual.d.ts +5 -0
- package/dist/session/verify-session-ritual.js +9 -0
- package/dist/slash/openclaw-deposit.js +13 -9
- package/dist/slice/constants.d.ts +2 -2
- package/dist/slice/constants.js +2 -2
- package/dist/slice/existing.js +9 -3
- package/dist/slice/lock.d.ts +16 -1
- package/dist/slice/lock.js +137 -11
- package/dist/story-ready/evaluate.d.ts +2 -0
- package/dist/story-ready/evaluate.js +13 -0
- package/dist/swarm/complete-cohort.d.ts +3 -0
- package/dist/swarm/complete-cohort.js +59 -11
- package/dist/swarm/finalize-cohort.js +33 -2
- package/dist/swarm/launch.d.ts +22 -0
- package/dist/swarm/launch.js +155 -0
- package/dist/swarm/routing-set-cli.d.ts +11 -1
- package/dist/swarm/routing-set-cli.js +13 -3
- package/dist/swarm/routing-verify.d.ts +12 -0
- package/dist/swarm/routing-verify.js +59 -20
- package/dist/swarm/routing.d.ts +14 -0
- package/dist/swarm/routing.js +53 -3
- package/dist/telemetry-coverage/fake-trial.js +10 -0
- package/dist/telemetry-coverage/kinds.js +2 -0
- package/dist/triage/actions/index.js +4 -1
- package/dist/ts-check-lane/index.d.ts +3 -0
- package/dist/ts-check-lane/index.js +2 -0
- package/dist/ts-check-lane/progress-reporter.d.ts +17 -0
- package/dist/ts-check-lane/progress-reporter.js +38 -0
- package/dist/ts-check-lane/progress.d.ts +32 -0
- package/dist/ts-check-lane/progress.js +57 -0
- package/dist/ts-check-lane/run-lane.d.ts +3 -1
- package/dist/ts-check-lane/run-lane.js +8 -6
- package/dist/validate-content/validate-links.d.ts +8 -0
- package/dist/validate-content/validate-links.js +9 -15
- package/dist/value/feedback-file.js +12 -2
- package/dist/vbrief-build/index.d.ts +1 -0
- package/dist/vbrief-build/index.js +1 -0
- package/dist/vbrief-build/project-invariants-io.d.ts +16 -0
- package/dist/vbrief-build/project-invariants-io.js +41 -0
- package/dist/vbrief-reconcile/graph.js +18 -1
- package/dist/vbrief-reconcile/index.d.ts +1 -1
- package/dist/vbrief-reconcile/index.js +1 -1
- package/dist/vbrief-reconcile/types.d.ts +13 -0
- package/dist/vbrief-reconcile/umbrellas.d.ts +14 -0
- package/dist/vbrief-reconcile/umbrellas.js +261 -26
- package/dist/vbrief-validate/index.d.ts +1 -1
- package/dist/vbrief-validate/index.js +1 -1
- package/dist/vbrief-validate/plan-hooks.d.ts +4 -0
- package/dist/vbrief-validate/plan-hooks.js +68 -0
- package/dist/verify-ac/evaluate.d.ts +7 -1
- package/dist/verify-ac/evaluate.js +34 -26
- package/dist/verify-ac/flag.d.ts +4 -0
- package/dist/verify-ac/flag.js +16 -0
- package/dist/verify-ac/index.d.ts +2 -2
- package/dist/verify-ac/index.js +2 -2
- package/dist/verify-source/contained-writes.js +2 -0
- package/dist/verify-source/verify-stubs.d.ts +15 -1
- package/dist/verify-source/verify-stubs.js +20 -16
- package/dist/vitest-runner/win32-coverage-tmp-setup.d.ts +5 -6
- package/dist/vitest-runner/win32-coverage-tmp-setup.js +5 -6
- package/dist/xbrief-migrate/migrate-project.js +2 -5
- package/package.json +3 -3
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed plan.policy.forgeOutageRetryMinutes (#3422).
|
|
3
|
+
*
|
|
4
|
+
* Re-probe interval after a forge / SCM API outage drop-back.
|
|
5
|
+
* Precedence: USER.md Personal > project policy > framework default 30.
|
|
6
|
+
* Integer minutes, minimum 5.
|
|
7
|
+
*/
|
|
8
|
+
import { readFileSync } from "node:fs";
|
|
9
|
+
import { resolveUserMdPath } from "../user-config/resolve-user-md.js";
|
|
10
|
+
import { readPlanPolicy } from "./plan-extensions.js";
|
|
11
|
+
import { loadProjectDefinition } from "./resolve.js";
|
|
12
|
+
export const FIELD_FORGE_OUTAGE_RETRY_MINUTES = "plan.policy.forgeOutageRetryMinutes";
|
|
13
|
+
export const FIELD_FORGE_OUTAGE_RETRY_MINUTES_CLI_ALIAS = "forgeOutageRetryMinutes";
|
|
14
|
+
export const DEFAULT_FORGE_OUTAGE_RETRY_MINUTES = 30;
|
|
15
|
+
export const MIN_FORGE_OUTAGE_RETRY_MINUTES = 5;
|
|
16
|
+
/** Validate a raw integer-minutes value. */
|
|
17
|
+
export function validateForgeOutageRetryMinutes(raw) {
|
|
18
|
+
if (typeof raw !== "number" || !Number.isInteger(raw)) {
|
|
19
|
+
return (`${FIELD_FORGE_OUTAGE_RETRY_MINUTES} must be an integer >= ` +
|
|
20
|
+
`${MIN_FORGE_OUTAGE_RETRY_MINUTES}; got ${typeof raw}`);
|
|
21
|
+
}
|
|
22
|
+
if (raw < MIN_FORGE_OUTAGE_RETRY_MINUTES) {
|
|
23
|
+
return (`${FIELD_FORGE_OUTAGE_RETRY_MINUTES} must be >= ` +
|
|
24
|
+
`${MIN_FORGE_OUTAGE_RETRY_MINUTES}; got ${raw}`);
|
|
25
|
+
}
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Parse USER.md Personal forge-outage retry minutes.
|
|
30
|
+
*
|
|
31
|
+
* Accepts `forgeOutageRetryMinutes: 15` or `Forge outage retry: 15m`.
|
|
32
|
+
*/
|
|
33
|
+
export function parseForgeOutageRetryMinutesFromUserMd(text) {
|
|
34
|
+
const lines = text.split(/\r?\n/);
|
|
35
|
+
let inPersonal = false;
|
|
36
|
+
for (const line of lines) {
|
|
37
|
+
const trimmed = line.trim();
|
|
38
|
+
if (/^##\s+personal\b/i.test(trimmed)) {
|
|
39
|
+
inPersonal = true;
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
if (inPersonal && /^##\s+/.test(trimmed)) {
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
if (!inPersonal)
|
|
46
|
+
continue;
|
|
47
|
+
const stripped = trimmed.replace(/\*\*/g, "").replace(/^-\s*/, "");
|
|
48
|
+
const keyed = stripped.match(/^forgeOutageRetryMinutes\s*:\s*(.+)$/i);
|
|
49
|
+
const labeled = stripped.match(/^Forge outage retry\s*:\s*(.+)$/i);
|
|
50
|
+
const raw = keyed?.[1] ?? labeled?.[1];
|
|
51
|
+
if (raw === undefined)
|
|
52
|
+
continue;
|
|
53
|
+
const parsed = parseMinutesToken(raw);
|
|
54
|
+
if (parsed !== null)
|
|
55
|
+
return parsed;
|
|
56
|
+
}
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
function parseMinutesToken(raw) {
|
|
60
|
+
const token = raw.replace(/\*\*/g, "").trim();
|
|
61
|
+
const match = token.match(/^(\d+)\s*(?:m(?:in(?:ute)?s?)?)?$/i);
|
|
62
|
+
if (match?.[1] === undefined)
|
|
63
|
+
return null;
|
|
64
|
+
const minutes = Number(match[1]);
|
|
65
|
+
if (!Number.isInteger(minutes))
|
|
66
|
+
return null;
|
|
67
|
+
return minutes;
|
|
68
|
+
}
|
|
69
|
+
function readUserMdText(options) {
|
|
70
|
+
if (options.userMdText !== undefined) {
|
|
71
|
+
return options.userMdText;
|
|
72
|
+
}
|
|
73
|
+
const projectRoot = options.projectRoot ?? process.cwd();
|
|
74
|
+
const resolved = resolveUserMdPath({
|
|
75
|
+
projectRoot,
|
|
76
|
+
env: options.env ?? process.env,
|
|
77
|
+
});
|
|
78
|
+
if (!resolved.found)
|
|
79
|
+
return null;
|
|
80
|
+
try {
|
|
81
|
+
return readFileSync(resolved.path, { encoding: "utf8" });
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function readProjectMinutes(projectRoot) {
|
|
88
|
+
const [data, err] = loadProjectDefinition(projectRoot);
|
|
89
|
+
if (data === null) {
|
|
90
|
+
return { present: false, minutes: null, error: err };
|
|
91
|
+
}
|
|
92
|
+
const policyBlock = readPlanPolicy(data.plan);
|
|
93
|
+
if (typeof policyBlock !== "object" ||
|
|
94
|
+
policyBlock === null ||
|
|
95
|
+
Array.isArray(policyBlock) ||
|
|
96
|
+
!("forgeOutageRetryMinutes" in policyBlock)) {
|
|
97
|
+
return { present: false, minutes: null, error: null };
|
|
98
|
+
}
|
|
99
|
+
const raw = policyBlock.forgeOutageRetryMinutes;
|
|
100
|
+
if (raw === null) {
|
|
101
|
+
return { present: false, minutes: null, error: null };
|
|
102
|
+
}
|
|
103
|
+
const validationError = validateForgeOutageRetryMinutes(raw);
|
|
104
|
+
if (validationError !== null) {
|
|
105
|
+
return { present: true, minutes: null, error: validationError };
|
|
106
|
+
}
|
|
107
|
+
return { present: true, minutes: raw, error: null };
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Resolve forge-outage re-probe minutes (#3422).
|
|
111
|
+
*
|
|
112
|
+
* 1. Valid USER.md Personal value
|
|
113
|
+
* 2. Valid plan.policy.forgeOutageRetryMinutes
|
|
114
|
+
* 3. Framework default 30
|
|
115
|
+
*/
|
|
116
|
+
export function resolveForgeOutageRetryMinutes(options = {}) {
|
|
117
|
+
const userMdText = readUserMdText(options);
|
|
118
|
+
if (userMdText !== null) {
|
|
119
|
+
const personal = parseForgeOutageRetryMinutesFromUserMd(userMdText);
|
|
120
|
+
if (personal !== null) {
|
|
121
|
+
const personalError = validateForgeOutageRetryMinutes(personal);
|
|
122
|
+
if (personalError === null) {
|
|
123
|
+
return { minutes: personal, source: "user-md", error: null };
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
const projectRoot = options.projectRoot;
|
|
128
|
+
if (projectRoot !== undefined && projectRoot !== null && projectRoot.length > 0) {
|
|
129
|
+
const project = readProjectMinutes(projectRoot);
|
|
130
|
+
if (project.minutes !== null) {
|
|
131
|
+
return { minutes: project.minutes, source: "typed", error: null };
|
|
132
|
+
}
|
|
133
|
+
if (project.present && project.error !== null) {
|
|
134
|
+
return {
|
|
135
|
+
minutes: DEFAULT_FORGE_OUTAGE_RETRY_MINUTES,
|
|
136
|
+
source: "default-on-error",
|
|
137
|
+
error: project.error,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return {
|
|
142
|
+
minutes: DEFAULT_FORGE_OUTAGE_RETRY_MINUTES,
|
|
143
|
+
source: "default",
|
|
144
|
+
error: null,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
/** Inspector row for `task policy:show --field=forgeOutageRetryMinutes`. */
|
|
148
|
+
export function inspectForgeOutageRetryMinutes(_data, projectRoot) {
|
|
149
|
+
const resolved = resolveForgeOutageRetryMinutes({ projectRoot });
|
|
150
|
+
return {
|
|
151
|
+
name: FIELD_FORGE_OUTAGE_RETRY_MINUTES,
|
|
152
|
+
current: resolved.minutes,
|
|
153
|
+
default: DEFAULT_FORGE_OUTAGE_RETRY_MINUTES,
|
|
154
|
+
source: resolved.source,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=forge-outage-retry.js.map
|
package/dist/policy/index.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export * from "./ac-pass-banking.js";
|
|
2
2
|
export * from "./agents-md-advisory.js";
|
|
3
3
|
export * from "./autonomy.js";
|
|
4
|
+
export * from "./base-branch.js";
|
|
5
|
+
export * from "./branch-sync.js";
|
|
4
6
|
export * from "./capacity.js";
|
|
5
7
|
export * from "./ceremony-dial.js";
|
|
6
8
|
export * from "./ceremony-dial-escalation.js";
|
|
@@ -10,6 +12,8 @@ export * from "./decisions.js";
|
|
|
10
12
|
export * from "./deft-directive-disable.js";
|
|
11
13
|
export * from "./delivery-branch.js";
|
|
12
14
|
export * from "./disclosure.js";
|
|
15
|
+
export * from "./file-size-thresholds.js";
|
|
16
|
+
export * from "./forge-outage-retry.js";
|
|
13
17
|
export * from "./host-hooks.js";
|
|
14
18
|
export * from "./host-slash-commands.js";
|
|
15
19
|
export * from "./hotfix-criteria.js";
|
|
@@ -21,10 +25,13 @@ export * from "./org-force-on-migration.js";
|
|
|
21
25
|
export * from "./plan-extensions.js";
|
|
22
26
|
export * from "./policy-invocation.js";
|
|
23
27
|
export * from "./product-signal.js";
|
|
28
|
+
export * from "./project-invariants.js";
|
|
24
29
|
export * from "./require-human-merge.js";
|
|
25
30
|
export * from "./resolve.js";
|
|
26
31
|
export * from "./runtime-authority.js";
|
|
27
32
|
export * from "./staleness-tickler.js";
|
|
33
|
+
export * from "./sync-default.js";
|
|
34
|
+
export * from "./sync-max-files.js";
|
|
28
35
|
export * from "./value-feedback.js";
|
|
29
36
|
export * from "./value-feedback-autoenable.js";
|
|
30
37
|
export * from "./wip.js";
|
package/dist/policy/index.js
CHANGED
|
@@ -1,25 +1,31 @@
|
|
|
1
1
|
import { FIELD_HOST_SKILL_DISCOVERY, FIELD_HOST_SKILL_DISCOVERY_CLI_ALIAS, inspectHostSkillDiscovery, } from "../init-deposit/skill-discovery-hosts.js";
|
|
2
2
|
import { FIELD_OPENCLAW_PRODUCT_COMMANDS, FIELD_OPENCLAW_PRODUCT_COMMANDS_CLI_ALIAS, inspectOpenClawProductCommands, } from "../slash/openclaw-deposit.js";
|
|
3
3
|
import { FIELD_AC_PASS_BANKING, FIELD_AC_PASS_BANKING_CLI_ALIAS, inspectAcPassBanking, } from "./ac-pass-banking.js";
|
|
4
|
+
import { FIELD_BASE_BRANCH, FIELD_BASE_BRANCH_CLI_ALIAS, inspectBaseBranch, } from "./base-branch.js";
|
|
4
5
|
import { FIELD_CEREMONY_DIAL, FIELD_CEREMONY_DIAL_CLI_ALIAS, inspectCeremonyDial, } from "./ceremony-dial.js";
|
|
5
6
|
import { FIELD_CHECK_RESUME, FIELD_CHECK_RESUME_CLI_ALIAS, inspectCheckResume, } from "./check-resume.js";
|
|
6
7
|
import { FIELD_COVERAGE_DEBT, FIELD_COVERAGE_DEBT_CLI_ALIAS, inspectCoverageDebt, } from "./coverage-debt.js";
|
|
7
8
|
import { FIELD_DELIVERY_BRANCH, FIELD_DELIVERY_BRANCH_CLI_ALIAS, inspectDeliveryBranch, } from "./delivery-branch.js";
|
|
9
|
+
import { FIELD_FORGE_OUTAGE_RETRY_MINUTES, FIELD_FORGE_OUTAGE_RETRY_MINUTES_CLI_ALIAS, inspectForgeOutageRetryMinutes, } from "./forge-outage-retry.js";
|
|
8
10
|
import { FIELD_HOST_HOOKS, FIELD_HOST_HOOKS_CLI_ALIAS, inspectHostHooks } from "./host-hooks.js";
|
|
9
11
|
import { FIELD_HOST_SLASH_COMMANDS, FIELD_HOST_SLASH_COMMANDS_CLI_ALIAS, inspectHostSlashCommands, } from "./host-slash-commands.js";
|
|
10
12
|
import { FIELD_HOTFIX_CRITERIA, FIELD_HOTFIX_CRITERIA_CLI_ALIAS, inspectHotfixCriteria, } from "./hotfix-criteria.js";
|
|
11
13
|
import { FIELD_MIN_GREPTILE_CONFIDENCE, FIELD_MIN_GREPTILE_CONFIDENCE_CLI_ALIAS, inspectMinGreptileConfidence, } from "./min-greptile-confidence.js";
|
|
12
14
|
import { readPlanPolicy } from "./plan-extensions.js";
|
|
13
15
|
import { FIELD_PRODUCT_SIGNAL, FIELD_PRODUCT_SIGNAL_CLI_ALIAS, inspectProductSignal, } from "./product-signal.js";
|
|
16
|
+
import { FIELD_PROJECT_INVARIANTS, FIELD_PROJECT_INVARIANTS_CLI_ALIAS, inspectProjectInvariants, } from "./project-invariants.js";
|
|
14
17
|
import { FIELD_REQUIRE_HUMAN_MERGE, FIELD_REQUIRE_HUMAN_MERGE_CLI_ALIAS, inspectRequireHumanMerge, } from "./require-human-merge.js";
|
|
15
18
|
import { coerceLegacyNarrative, LEGACY_NARRATIVE_KEY, loadProjectDefinition } from "./resolve.js";
|
|
16
19
|
import { FIELD_RUNTIME_AUTHORITY, FIELD_RUNTIME_AUTHORITY_CLI_ALIAS, inspectRuntimeAuthority, } from "./runtime-authority.js";
|
|
17
20
|
import { FIELD_STALENESS_TICKLER, FIELD_STALENESS_TICKLER_CLI_ALIAS, inspectStalenessTickler, } from "./staleness-tickler.js";
|
|
21
|
+
import { FIELD_SYNC_MAX_FILES, FIELD_SYNC_MAX_FILES_CLI_ALIAS, inspectSyncMaxFiles, } from "./sync-max-files.js";
|
|
18
22
|
import { FIELD_VALUE_FEEDBACK, FIELD_VALUE_FEEDBACK_CLI_ALIAS, inspectValueFeedback, } from "./value-feedback.js";
|
|
19
23
|
import { DEFAULT_WIP_CAP } from "./wip.js";
|
|
20
24
|
export * from "./ac-pass-banking.js";
|
|
21
25
|
export * from "./agents-md-advisory.js";
|
|
22
26
|
export * from "./autonomy.js";
|
|
27
|
+
export * from "./base-branch.js";
|
|
28
|
+
export * from "./branch-sync.js";
|
|
23
29
|
export * from "./capacity.js";
|
|
24
30
|
export * from "./ceremony-dial.js";
|
|
25
31
|
export * from "./ceremony-dial-escalation.js";
|
|
@@ -29,6 +35,8 @@ export * from "./decisions.js";
|
|
|
29
35
|
export * from "./deft-directive-disable.js";
|
|
30
36
|
export * from "./delivery-branch.js";
|
|
31
37
|
export * from "./disclosure.js";
|
|
38
|
+
export * from "./file-size-thresholds.js";
|
|
39
|
+
export * from "./forge-outage-retry.js";
|
|
32
40
|
export * from "./host-hooks.js";
|
|
33
41
|
export * from "./host-slash-commands.js";
|
|
34
42
|
export * from "./hotfix-criteria.js";
|
|
@@ -40,10 +48,13 @@ export * from "./org-force-on-migration.js";
|
|
|
40
48
|
export * from "./plan-extensions.js";
|
|
41
49
|
export * from "./policy-invocation.js";
|
|
42
50
|
export * from "./product-signal.js";
|
|
51
|
+
export * from "./project-invariants.js";
|
|
43
52
|
export * from "./require-human-merge.js";
|
|
44
53
|
export * from "./resolve.js";
|
|
45
54
|
export * from "./runtime-authority.js";
|
|
46
55
|
export * from "./staleness-tickler.js";
|
|
56
|
+
export * from "./sync-default.js";
|
|
57
|
+
export * from "./sync-max-files.js";
|
|
47
58
|
export * from "./value-feedback.js";
|
|
48
59
|
export * from "./value-feedback-autoenable.js";
|
|
49
60
|
export * from "./wip.js";
|
|
@@ -404,6 +415,15 @@ function inspectDeliveryBranchField(data, projectRoot) {
|
|
|
404
415
|
source: field.source,
|
|
405
416
|
};
|
|
406
417
|
}
|
|
418
|
+
function inspectBaseBranchField(data, projectRoot) {
|
|
419
|
+
const field = inspectBaseBranch(data, projectRoot);
|
|
420
|
+
return {
|
|
421
|
+
name: field.name,
|
|
422
|
+
current: field.current,
|
|
423
|
+
default: field.default,
|
|
424
|
+
source: field.source,
|
|
425
|
+
};
|
|
426
|
+
}
|
|
407
427
|
function inspectMinGreptileConfidenceField(data, projectRoot) {
|
|
408
428
|
const field = inspectMinGreptileConfidence(data, projectRoot);
|
|
409
429
|
return {
|
|
@@ -431,6 +451,33 @@ function inspectAcPassBankingField(data, projectRoot) {
|
|
|
431
451
|
source: field.source,
|
|
432
452
|
};
|
|
433
453
|
}
|
|
454
|
+
function inspectSyncMaxFilesField(data, projectRoot) {
|
|
455
|
+
const field = inspectSyncMaxFiles(data, projectRoot);
|
|
456
|
+
return {
|
|
457
|
+
name: field.name,
|
|
458
|
+
current: field.current,
|
|
459
|
+
default: field.default,
|
|
460
|
+
source: field.source,
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
function inspectForgeOutageRetryMinutesField(data, projectRoot) {
|
|
464
|
+
const field = inspectForgeOutageRetryMinutes(data, projectRoot);
|
|
465
|
+
return {
|
|
466
|
+
name: field.name,
|
|
467
|
+
current: field.current,
|
|
468
|
+
default: field.default,
|
|
469
|
+
source: field.source,
|
|
470
|
+
};
|
|
471
|
+
}
|
|
472
|
+
function inspectProjectInvariantsField(data, projectRoot) {
|
|
473
|
+
const field = inspectProjectInvariants(data, projectRoot);
|
|
474
|
+
return {
|
|
475
|
+
name: field.name,
|
|
476
|
+
current: field.current,
|
|
477
|
+
default: field.default,
|
|
478
|
+
source: field.source,
|
|
479
|
+
};
|
|
480
|
+
}
|
|
434
481
|
const REGISTERED_POLICIES = [
|
|
435
482
|
inspectAllowDirectCommits,
|
|
436
483
|
inspectWipCap,
|
|
@@ -445,6 +492,7 @@ const REGISTERED_POLICIES = [
|
|
|
445
492
|
inspectTriageLabelMirrorField,
|
|
446
493
|
inspectSwarmSubagentBackend,
|
|
447
494
|
inspectDeliveryBranchField,
|
|
495
|
+
inspectBaseBranchField,
|
|
448
496
|
inspectMinGreptileConfidenceField,
|
|
449
497
|
inspectHostHooksField,
|
|
450
498
|
inspectHostSlashCommandsField,
|
|
@@ -460,6 +508,9 @@ const REGISTERED_POLICIES = [
|
|
|
460
508
|
inspectHotfixCriteriaField,
|
|
461
509
|
inspectCeremonyDialField,
|
|
462
510
|
inspectAcPassBankingField,
|
|
511
|
+
inspectSyncMaxFilesField,
|
|
512
|
+
inspectForgeOutageRetryMinutesField,
|
|
513
|
+
inspectProjectInvariantsField,
|
|
463
514
|
];
|
|
464
515
|
/** Walk registered inspectors and return one row per field (#1148). */
|
|
465
516
|
export function inspectAllPolicies(projectRoot) {
|
|
@@ -494,13 +545,21 @@ export function inspectOnePolicy(name, projectRoot) {
|
|
|
494
545
|
? FIELD_HOTFIX_CRITERIA
|
|
495
546
|
: name === FIELD_DELIVERY_BRANCH_CLI_ALIAS
|
|
496
547
|
? FIELD_DELIVERY_BRANCH
|
|
497
|
-
: name ===
|
|
498
|
-
?
|
|
499
|
-
: name ===
|
|
500
|
-
?
|
|
501
|
-
: name ===
|
|
502
|
-
?
|
|
503
|
-
: name
|
|
548
|
+
: name === FIELD_BASE_BRANCH_CLI_ALIAS
|
|
549
|
+
? FIELD_BASE_BRANCH
|
|
550
|
+
: name === FIELD_MIN_GREPTILE_CONFIDENCE_CLI_ALIAS
|
|
551
|
+
? FIELD_MIN_GREPTILE_CONFIDENCE
|
|
552
|
+
: name === FIELD_CEREMONY_DIAL_CLI_ALIAS
|
|
553
|
+
? FIELD_CEREMONY_DIAL
|
|
554
|
+
: name === FIELD_AC_PASS_BANKING_CLI_ALIAS
|
|
555
|
+
? FIELD_AC_PASS_BANKING
|
|
556
|
+
: name === FIELD_SYNC_MAX_FILES_CLI_ALIAS
|
|
557
|
+
? FIELD_SYNC_MAX_FILES
|
|
558
|
+
: name === FIELD_FORGE_OUTAGE_RETRY_MINUTES_CLI_ALIAS
|
|
559
|
+
? FIELD_FORGE_OUTAGE_RETRY_MINUTES
|
|
560
|
+
: name === FIELD_PROJECT_INVARIANTS_CLI_ALIAS
|
|
561
|
+
? FIELD_PROJECT_INVARIANTS
|
|
562
|
+
: name;
|
|
504
563
|
for (const field of inspectAllPolicies(projectRoot)) {
|
|
505
564
|
if (field.name === normalized)
|
|
506
565
|
return field;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed plan.policy.projectInvariants (#3425 Story A).
|
|
3
|
+
*
|
|
4
|
+
* Authored project-level must-not-break contracts. Empty or absent list is a
|
|
5
|
+
* no-op. Parse/validate only — preflight fail-closed is Story B.
|
|
6
|
+
*/
|
|
7
|
+
export declare const FIELD_PROJECT_INVARIANTS = "plan.policy.projectInvariants";
|
|
8
|
+
export declare const FIELD_PROJECT_INVARIANTS_CLI_ALIAS = "projectInvariants";
|
|
9
|
+
export interface ProjectInvariantContractSurface {
|
|
10
|
+
readonly paths: readonly string[];
|
|
11
|
+
readonly moduleIds: readonly string[];
|
|
12
|
+
}
|
|
13
|
+
export interface ProjectInvariant {
|
|
14
|
+
readonly id: string;
|
|
15
|
+
readonly statement: string;
|
|
16
|
+
readonly contractSurface: ProjectInvariantContractSurface;
|
|
17
|
+
}
|
|
18
|
+
export type ProjectInvariantsSource = "typed" | "default" | "default-on-error";
|
|
19
|
+
export interface ProjectInvariantsParseResult {
|
|
20
|
+
readonly invariants: readonly ProjectInvariant[];
|
|
21
|
+
readonly errors: readonly string[];
|
|
22
|
+
}
|
|
23
|
+
export interface ProjectInvariantsResolved {
|
|
24
|
+
readonly invariants: readonly ProjectInvariant[];
|
|
25
|
+
readonly source: ProjectInvariantsSource;
|
|
26
|
+
readonly error: string | null;
|
|
27
|
+
}
|
|
28
|
+
export interface ProjectInvariantsPolicyField {
|
|
29
|
+
readonly name: typeof FIELD_PROJECT_INVARIANTS;
|
|
30
|
+
readonly current: readonly ProjectInvariant[];
|
|
31
|
+
readonly default: readonly ProjectInvariant[];
|
|
32
|
+
readonly source: string;
|
|
33
|
+
}
|
|
34
|
+
/** Parse a raw projectInvariants value. Absent/null → empty list, no errors. */
|
|
35
|
+
export declare function parseProjectInvariants(raw: unknown): ProjectInvariantsParseResult;
|
|
36
|
+
/**
|
|
37
|
+
* Map codeStructure.modules[] id → pathGlobs for applicability intersection.
|
|
38
|
+
* Pure: pass PROJECT-DEFINITION (or plan) data, no disk IO.
|
|
39
|
+
*/
|
|
40
|
+
export declare function extractModulePathGlobs(projectDefinition: unknown): Record<string, string[]>;
|
|
41
|
+
/**
|
|
42
|
+
* Resolve projectInvariants from PROJECT-DEFINITION data already in memory.
|
|
43
|
+
* Absent/null → default empty. Present invalid → default-on-error + message.
|
|
44
|
+
*/
|
|
45
|
+
export declare function resolveProjectInvariantsFromData(data: Record<string, unknown> | null): ProjectInvariantsResolved;
|
|
46
|
+
/** Resolve from a project root via the PROJECT-DEFINITION IO path. */
|
|
47
|
+
export declare function resolveProjectInvariants(projectRoot: string): ProjectInvariantsResolved;
|
|
48
|
+
/** Inspector row for `task policy:show --field=projectInvariants`. */
|
|
49
|
+
export declare function inspectProjectInvariants(data: Record<string, unknown> | null, projectRoot?: string): ProjectInvariantsPolicyField;
|
|
50
|
+
//# sourceMappingURL=project-invariants.d.ts.map
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed plan.policy.projectInvariants (#3425 Story A).
|
|
3
|
+
*
|
|
4
|
+
* Authored project-level must-not-break contracts. Empty or absent list is a
|
|
5
|
+
* no-op. Parse/validate only — preflight fail-closed is Story B.
|
|
6
|
+
*/
|
|
7
|
+
import { readPlanPolicy } from "./plan-extensions.js";
|
|
8
|
+
import { loadProjectDefinition } from "./resolve.js";
|
|
9
|
+
export const FIELD_PROJECT_INVARIANTS = "plan.policy.projectInvariants";
|
|
10
|
+
export const FIELD_PROJECT_INVARIANTS_CLI_ALIAS = "projectInvariants";
|
|
11
|
+
const EMPTY = [];
|
|
12
|
+
function asRecord(value) {
|
|
13
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
14
|
+
return value;
|
|
15
|
+
}
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
function isNonEmptyString(value) {
|
|
19
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
20
|
+
}
|
|
21
|
+
function asStrList(value) {
|
|
22
|
+
if (value === null || value === undefined)
|
|
23
|
+
return [];
|
|
24
|
+
if (typeof value === "string")
|
|
25
|
+
return value.trim().length > 0 ? [value.trim()] : [];
|
|
26
|
+
if (Array.isArray(value)) {
|
|
27
|
+
return value.map((item) => String(item).trim()).filter((s) => s.length > 0);
|
|
28
|
+
}
|
|
29
|
+
return [];
|
|
30
|
+
}
|
|
31
|
+
function pythonTypeName(value) {
|
|
32
|
+
if (value === null)
|
|
33
|
+
return "None";
|
|
34
|
+
if (Array.isArray(value))
|
|
35
|
+
return "list";
|
|
36
|
+
if (typeof value === "boolean")
|
|
37
|
+
return "bool";
|
|
38
|
+
if (typeof value === "number")
|
|
39
|
+
return Number.isInteger(value) ? "int" : "float";
|
|
40
|
+
if (typeof value === "string")
|
|
41
|
+
return "str";
|
|
42
|
+
if (typeof value === "object")
|
|
43
|
+
return "dict";
|
|
44
|
+
return typeof value;
|
|
45
|
+
}
|
|
46
|
+
function parseContractSurface(body, loc) {
|
|
47
|
+
const nested = asRecord(body.contractSurface) ?? asRecord(body.contract_surface) ?? asRecord(body.contract);
|
|
48
|
+
const pathSource = nested ?? body;
|
|
49
|
+
const moduleSource = nested ?? body;
|
|
50
|
+
const pathsRaw = pathSource.paths ?? pathSource.pathGlobs ?? pathSource.path_globs ?? body.paths;
|
|
51
|
+
const moduleRaw = moduleSource.moduleIds ??
|
|
52
|
+
moduleSource.module_ids ??
|
|
53
|
+
moduleSource.modules ??
|
|
54
|
+
body.moduleIds ??
|
|
55
|
+
body.module_ids;
|
|
56
|
+
// Shorthand: contractSurface / contract_surface as a string list of paths.
|
|
57
|
+
const shorthand = body.contractSurface ?? body.contract_surface ?? body.contract;
|
|
58
|
+
const paths = [...asStrList(pathsRaw), ...(nested === null ? asStrList(shorthand) : [])];
|
|
59
|
+
const moduleIds = asStrList(moduleRaw);
|
|
60
|
+
if (paths.length === 0 && moduleIds.length === 0) {
|
|
61
|
+
return {
|
|
62
|
+
surface: null,
|
|
63
|
+
errors: [
|
|
64
|
+
`${loc}: contract surface requires paths[] and/or moduleIds[] ` +
|
|
65
|
+
`(must-not-break module/contract)`,
|
|
66
|
+
],
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
surface: { paths, moduleIds },
|
|
71
|
+
errors: [],
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/** Parse a raw projectInvariants value. Absent/null → empty list, no errors. */
|
|
75
|
+
export function parseProjectInvariants(raw) {
|
|
76
|
+
if (raw === null || raw === undefined) {
|
|
77
|
+
return { invariants: EMPTY, errors: [] };
|
|
78
|
+
}
|
|
79
|
+
if (!Array.isArray(raw)) {
|
|
80
|
+
return {
|
|
81
|
+
invariants: EMPTY,
|
|
82
|
+
errors: [`${FIELD_PROJECT_INVARIANTS} must be an array; got ${pythonTypeName(raw)}`],
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
const invariants = [];
|
|
86
|
+
const errors = [];
|
|
87
|
+
const seen = new Set();
|
|
88
|
+
for (let i = 0; i < raw.length; i += 1) {
|
|
89
|
+
const loc = `${FIELD_PROJECT_INVARIANTS}[${i}]`;
|
|
90
|
+
const item = raw[i];
|
|
91
|
+
const rec = asRecord(item);
|
|
92
|
+
if (rec === null) {
|
|
93
|
+
errors.push(`${loc}: entry must be an object`);
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
const id = rec.id;
|
|
97
|
+
const statement = rec.statement ?? rec.Statement;
|
|
98
|
+
if (!isNonEmptyString(id)) {
|
|
99
|
+
errors.push(`${loc}: id is required`);
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
const trimmedId = id.trim();
|
|
103
|
+
if (seen.has(trimmedId)) {
|
|
104
|
+
errors.push(`${loc}: duplicate id '${trimmedId}'`);
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
if (!isNonEmptyString(statement)) {
|
|
108
|
+
errors.push(`${loc}: statement is required`);
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
const { surface, errors: surfaceErrors } = parseContractSurface(rec, loc);
|
|
112
|
+
errors.push(...surfaceErrors);
|
|
113
|
+
if (surface === null)
|
|
114
|
+
continue;
|
|
115
|
+
seen.add(trimmedId);
|
|
116
|
+
invariants.push({
|
|
117
|
+
id: trimmedId,
|
|
118
|
+
statement: String(statement).trim(),
|
|
119
|
+
contractSurface: surface,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
return { invariants, errors };
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Map codeStructure.modules[] id → pathGlobs for applicability intersection.
|
|
126
|
+
* Pure: pass PROJECT-DEFINITION (or plan) data, no disk IO.
|
|
127
|
+
*/
|
|
128
|
+
export function extractModulePathGlobs(projectDefinition) {
|
|
129
|
+
const root = asRecord(projectDefinition);
|
|
130
|
+
if (root === null)
|
|
131
|
+
return {};
|
|
132
|
+
const plan = asRecord(root.plan) ?? root;
|
|
133
|
+
const architecture = asRecord(plan.architecture);
|
|
134
|
+
if (architecture === null)
|
|
135
|
+
return {};
|
|
136
|
+
const codeStructure = asRecord(architecture.codeStructure ?? architecture.code_structure);
|
|
137
|
+
if (codeStructure === null)
|
|
138
|
+
return {};
|
|
139
|
+
const modules = codeStructure.modules;
|
|
140
|
+
if (!Array.isArray(modules))
|
|
141
|
+
return {};
|
|
142
|
+
const out = {};
|
|
143
|
+
for (const item of modules) {
|
|
144
|
+
const rec = asRecord(item);
|
|
145
|
+
if (rec === null || !isNonEmptyString(rec.id))
|
|
146
|
+
continue;
|
|
147
|
+
const globs = asStrList(rec.pathGlobs ?? rec.path_globs ?? rec.paths);
|
|
148
|
+
if (globs.length === 0)
|
|
149
|
+
continue;
|
|
150
|
+
out[rec.id.trim()] = globs;
|
|
151
|
+
}
|
|
152
|
+
return out;
|
|
153
|
+
}
|
|
154
|
+
function readPolicyBlock(data) {
|
|
155
|
+
if (data === null)
|
|
156
|
+
return null;
|
|
157
|
+
const policy = readPlanPolicy(data.plan);
|
|
158
|
+
return asRecord(policy);
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Resolve projectInvariants from PROJECT-DEFINITION data already in memory.
|
|
162
|
+
* Absent/null → default empty. Present invalid → default-on-error + message.
|
|
163
|
+
*/
|
|
164
|
+
export function resolveProjectInvariantsFromData(data) {
|
|
165
|
+
const policy = readPolicyBlock(data);
|
|
166
|
+
if (policy === null || !("projectInvariants" in policy)) {
|
|
167
|
+
return { invariants: EMPTY, source: "default", error: null };
|
|
168
|
+
}
|
|
169
|
+
const raw = policy.projectInvariants;
|
|
170
|
+
if (raw === null) {
|
|
171
|
+
return { invariants: EMPTY, source: "default", error: null };
|
|
172
|
+
}
|
|
173
|
+
const parsed = parseProjectInvariants(raw);
|
|
174
|
+
if (parsed.errors.length > 0) {
|
|
175
|
+
return {
|
|
176
|
+
invariants: EMPTY,
|
|
177
|
+
source: "default-on-error",
|
|
178
|
+
error: parsed.errors.join("; "),
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
return { invariants: parsed.invariants, source: "typed", error: null };
|
|
182
|
+
}
|
|
183
|
+
/** Resolve from a project root via the PROJECT-DEFINITION IO path. */
|
|
184
|
+
export function resolveProjectInvariants(projectRoot) {
|
|
185
|
+
const [data, err] = loadProjectDefinition(projectRoot);
|
|
186
|
+
if (data === null) {
|
|
187
|
+
return { invariants: EMPTY, source: "default", error: err };
|
|
188
|
+
}
|
|
189
|
+
return resolveProjectInvariantsFromData(data);
|
|
190
|
+
}
|
|
191
|
+
/** Inspector row for `task policy:show --field=projectInvariants`. */
|
|
192
|
+
export function inspectProjectInvariants(data, projectRoot) {
|
|
193
|
+
const resolved = data !== null
|
|
194
|
+
? resolveProjectInvariantsFromData(data)
|
|
195
|
+
: projectRoot !== undefined && projectRoot.length > 0
|
|
196
|
+
? resolveProjectInvariants(projectRoot)
|
|
197
|
+
: { invariants: EMPTY, source: "default", error: null };
|
|
198
|
+
return {
|
|
199
|
+
name: FIELD_PROJECT_INVARIANTS,
|
|
200
|
+
current: resolved.invariants,
|
|
201
|
+
default: EMPTY,
|
|
202
|
+
source: resolved.source,
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
//# sourceMappingURL=project-invariants.js.map
|