@deftai/directive-core 0.103.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.
Files changed (255) hide show
  1. package/dist/authz/classify.js +682 -35
  2. package/dist/check/cached-orchestrator.d.ts +1 -1
  3. package/dist/check/cached-orchestrator.js +2 -2
  4. package/dist/check/gate-lists.d.ts +3 -2
  5. package/dist/check/gate-lists.js +5 -2
  6. package/dist/check/index.d.ts +1 -0
  7. package/dist/check/index.js +1 -0
  8. package/dist/check/named-cause.d.ts +1 -1
  9. package/dist/check/named-cause.js +33 -3
  10. package/dist/check/session-completed-ac.d.ts +39 -0
  11. package/dist/check/session-completed-ac.js +198 -0
  12. package/dist/codebase/default-extractor.d.ts +5 -0
  13. package/dist/codebase/default-extractor.js +7 -15
  14. package/dist/deposit/copy-tree.js +60 -0
  15. package/dist/deposit/python-free.js +26 -18
  16. package/dist/doctor/checks.d.ts +8 -0
  17. package/dist/doctor/checks.js +37 -25
  18. package/dist/doctor/doctor-state.d.ts +4 -0
  19. package/dist/doctor/doctor-state.js +7 -1
  20. package/dist/doctor/main.js +9 -14
  21. package/dist/doctor/types.d.ts +9 -0
  22. package/dist/fs/contained-write.d.ts +115 -1
  23. package/dist/fs/contained-write.js +242 -5
  24. package/dist/fs/mutation-ledger.d.ts +54 -0
  25. package/dist/fs/mutation-ledger.js +133 -0
  26. package/dist/fs/non-product-dirs.d.ts +79 -0
  27. package/dist/fs/non-product-dirs.js +96 -0
  28. package/dist/hooks/dispatcher.d.ts +3 -1
  29. package/dist/hooks/dispatcher.js +14 -0
  30. package/dist/index.d.ts +2 -0
  31. package/dist/index.js +3 -0
  32. package/dist/init-deposit/agent-hooks.js +17 -15
  33. package/dist/init-deposit/core-guard-pin-content.d.ts +7 -0
  34. package/dist/init-deposit/core-guard-pin-content.js +393 -0
  35. package/dist/init-deposit/gitignore.js +9 -0
  36. package/dist/init-deposit/hygiene.d.ts +47 -11
  37. package/dist/init-deposit/hygiene.js +172 -37
  38. package/dist/init-deposit/legacy-detect.js +6 -2
  39. package/dist/init-deposit/refresh.d.ts +21 -1
  40. package/dist/init-deposit/refresh.js +106 -9
  41. package/dist/init-deposit/scaffold.js +28 -279
  42. package/dist/init-deposit/slash-deposit.js +13 -7
  43. package/dist/init-deposit/xbrief-projections.d.ts +8 -1
  44. package/dist/init-deposit/xbrief-projections.js +24 -11
  45. package/dist/intake/clause-derivation.d.ts +74 -0
  46. package/dist/intake/clause-derivation.js +409 -0
  47. package/dist/intake/index.d.ts +1 -0
  48. package/dist/intake/index.js +1 -0
  49. package/dist/intake/issue-ingest.d.ts +3 -1
  50. package/dist/intake/issue-ingest.js +36 -43
  51. package/dist/lifecycle/completed-tracked-on-delivery.d.ts +5 -0
  52. package/dist/lifecycle/completed-tracked-on-delivery.js +85 -18
  53. package/dist/literal-acceptance/capture.d.ts +10 -0
  54. package/dist/literal-acceptance/capture.js +224 -75
  55. package/dist/literal-acceptance/evaluate.d.ts +29 -4
  56. package/dist/literal-acceptance/evaluate.js +70 -2
  57. package/dist/literal-acceptance/index.d.ts +3 -3
  58. package/dist/literal-acceptance/index.js +3 -3
  59. package/dist/literal-acceptance/safety.d.ts +41 -0
  60. package/dist/literal-acceptance/safety.js +126 -2
  61. package/dist/literal-acceptance/types.d.ts +8 -0
  62. package/dist/orphan-active/evaluate.d.ts +7 -1
  63. package/dist/orphan-active/evaluate.js +102 -23
  64. package/dist/platform/platform-capabilities.js +2 -3
  65. package/dist/policy/base-branch.d.ts +37 -0
  66. package/dist/policy/base-branch.js +114 -0
  67. package/dist/policy/branch-sync.d.ts +80 -0
  68. package/dist/policy/branch-sync.js +211 -0
  69. package/dist/policy/ceremony-dial-escalation.js +1 -0
  70. package/dist/policy/ceremony-dial.js +4 -14
  71. package/dist/policy/delivery-branch.d.ts +5 -3
  72. package/dist/policy/delivery-branch.js +7 -3
  73. package/dist/policy/file-size-thresholds.d.ts +24 -0
  74. package/dist/policy/file-size-thresholds.js +23 -0
  75. package/dist/policy/forge-outage-retry.d.ts +47 -0
  76. package/dist/policy/forge-outage-retry.js +157 -0
  77. package/dist/policy/index.d.ts +7 -0
  78. package/dist/policy/index.js +66 -7
  79. package/dist/policy/project-invariants.d.ts +50 -0
  80. package/dist/policy/project-invariants.js +205 -0
  81. package/dist/policy/sync-default.d.ts +129 -0
  82. package/dist/policy/sync-default.js +452 -0
  83. package/dist/policy/sync-max-files.d.ts +93 -0
  84. package/dist/policy/sync-max-files.js +192 -0
  85. package/dist/pr-monitor/absent-required.d.ts +11 -0
  86. package/dist/pr-monitor/absent-required.js +61 -0
  87. package/dist/pr-monitor/constants.d.ts +7 -0
  88. package/dist/pr-monitor/constants.js +7 -0
  89. package/dist/pr-monitor/index.d.ts +2 -1
  90. package/dist/pr-monitor/index.js +2 -1
  91. package/dist/pr-monitor/main.js +4 -0
  92. package/dist/pr-monitor/monitor.js +24 -1
  93. package/dist/pr-wait-mergeable/classify.js +6 -0
  94. package/dist/preflight/evaluate.d.ts +9 -0
  95. package/dist/preflight/evaluate.js +49 -1
  96. package/dist/preflight/index.d.ts +5 -1
  97. package/dist/preflight/index.js +2 -0
  98. package/dist/preflight/intended-placement.d.ts +62 -0
  99. package/dist/preflight/intended-placement.js +275 -0
  100. package/dist/preflight/project-invariants-gate.d.ts +29 -0
  101. package/dist/preflight/project-invariants-gate.js +82 -0
  102. package/dist/product-first-done-gate/acceptance-resolver.d.ts +128 -0
  103. package/dist/product-first-done-gate/acceptance-resolver.js +144 -0
  104. package/dist/product-first-done-gate/acceptance.d.ts +7 -4
  105. package/dist/product-first-done-gate/acceptance.js +79 -8
  106. package/dist/product-first-done-gate/empty-resolution.d.ts +5 -2
  107. package/dist/product-first-done-gate/empty-resolution.js +13 -2
  108. package/dist/product-first-done-gate/evaluate.d.ts +29 -0
  109. package/dist/product-first-done-gate/evaluate.js +307 -33
  110. package/dist/product-first-done-gate/index.d.ts +3 -1
  111. package/dist/product-first-done-gate/index.js +2 -1
  112. package/dist/release/build-dist.d.ts +101 -0
  113. package/dist/release/build-dist.js +428 -46
  114. package/dist/run-summary/emit.d.ts +50 -4
  115. package/dist/run-summary/emit.js +262 -26
  116. package/dist/run-summary/index.d.ts +3 -2
  117. package/dist/run-summary/index.js +2 -1
  118. package/dist/run-summary/session-id.d.ts +21 -0
  119. package/dist/run-summary/session-id.js +92 -0
  120. package/dist/run-summary/share.d.ts +1 -1
  121. package/dist/run-summary/share.js +2 -2
  122. package/dist/run-summary/types.d.ts +38 -6
  123. package/dist/run-summary/types.js +1 -0
  124. package/dist/scope/acceptance-activate-gate.d.ts +1 -1
  125. package/dist/scope/acceptance-activate-gate.js +4 -4
  126. package/dist/scope/acceptance-evidence.d.ts +27 -0
  127. package/dist/scope/acceptance-evidence.js +66 -0
  128. package/dist/scope/capacity-stamp.d.ts +2 -0
  129. package/dist/scope/capacity-stamp.js +4 -0
  130. package/dist/scope/delivery-evidence.d.ts +9 -3
  131. package/dist/scope/delivery-evidence.js +39 -27
  132. package/dist/scope/index.d.ts +1 -0
  133. package/dist/scope/index.js +1 -0
  134. package/dist/scope/parent-lineage.js +7 -6
  135. package/dist/scope/project-invariant-coverage.d.ts +54 -0
  136. package/dist/scope/project-invariant-coverage.js +322 -0
  137. package/dist/scope/transition.js +66 -4
  138. package/dist/scope-provenance/compare-intent.d.ts +27 -0
  139. package/dist/scope-provenance/compare-intent.js +233 -0
  140. package/dist/scope-provenance/digest.d.ts +18 -1
  141. package/dist/scope-provenance/digest.js +16 -11
  142. package/dist/scope-provenance/evaluate.d.ts +5 -1
  143. package/dist/scope-provenance/evaluate.js +64 -4
  144. package/dist/scope-provenance/extract-intent.d.ts +43 -0
  145. package/dist/scope-provenance/extract-intent.js +262 -0
  146. package/dist/scope-provenance/index.d.ts +7 -1
  147. package/dist/scope-provenance/index.js +7 -1
  148. package/dist/scope-provenance/intent-digest.d.ts +12 -0
  149. package/dist/scope-provenance/intent-digest.js +33 -0
  150. package/dist/scope-provenance/intent-evaluate.d.ts +43 -0
  151. package/dist/scope-provenance/intent-evaluate.js +149 -0
  152. package/dist/scope-provenance/json-tokenizer.d.ts +19 -0
  153. package/dist/scope-provenance/json-tokenizer.js +225 -0
  154. package/dist/scope-provenance/known-machine.d.ts +38 -0
  155. package/dist/scope-provenance/known-machine.js +157 -0
  156. package/dist/scope-provenance/mint-artifacts.d.ts +102 -0
  157. package/dist/scope-provenance/mint-artifacts.js +425 -0
  158. package/dist/session/ac-pass-banking.d.ts +4 -36
  159. package/dist/session/ac-pass-banking.js +30 -77
  160. package/dist/session/ac-pass-reuse.d.ts +53 -0
  161. package/dist/session/ac-pass-reuse.js +95 -0
  162. package/dist/session/ceremony-dial-evidence.d.ts +42 -0
  163. package/dist/session/ceremony-dial-evidence.js +194 -0
  164. package/dist/session/git.js +19 -4
  165. package/dist/session/index.d.ts +5 -0
  166. package/dist/session/index.js +5 -0
  167. package/dist/session/occupancy-stress-worker.d.ts +7 -0
  168. package/dist/session/occupancy-stress-worker.js +36 -0
  169. package/dist/session/occupancy.d.ts +97 -0
  170. package/dist/session/occupancy.js +422 -0
  171. package/dist/session/openclaw-soft-rebind-deposit.js +6 -6
  172. package/dist/session/product-state-hash.d.ts +26 -0
  173. package/dist/session/product-state-hash.js +683 -0
  174. package/dist/session/session-ready.d.ts +2 -0
  175. package/dist/session/session-ready.js +52 -30
  176. package/dist/session/session-start.d.ts +7 -0
  177. package/dist/session/session-start.js +88 -5
  178. package/dist/session/verify-ac-session-cache.d.ts +42 -0
  179. package/dist/session/verify-ac-session-cache.js +126 -0
  180. package/dist/session/verify-session-ritual.d.ts +5 -0
  181. package/dist/session/verify-session-ritual.js +9 -0
  182. package/dist/slash/openclaw-deposit.js +13 -9
  183. package/dist/slice/constants.d.ts +2 -2
  184. package/dist/slice/constants.js +2 -2
  185. package/dist/slice/existing.js +21 -4
  186. package/dist/slice/lock.d.ts +16 -1
  187. package/dist/slice/lock.js +137 -11
  188. package/dist/slice/record.d.ts +8 -5
  189. package/dist/slice/record.js +21 -13
  190. package/dist/story-ready/evaluate.d.ts +2 -0
  191. package/dist/story-ready/evaluate.js +13 -0
  192. package/dist/swarm/complete-cohort.d.ts +3 -0
  193. package/dist/swarm/complete-cohort.js +59 -11
  194. package/dist/swarm/finalize-cohort.js +33 -2
  195. package/dist/swarm/launch.d.ts +22 -0
  196. package/dist/swarm/launch.js +155 -0
  197. package/dist/swarm/routing-set-cli.d.ts +11 -1
  198. package/dist/swarm/routing-set-cli.js +13 -3
  199. package/dist/swarm/routing-verify.d.ts +12 -0
  200. package/dist/swarm/routing-verify.js +59 -20
  201. package/dist/swarm/routing.d.ts +14 -0
  202. package/dist/swarm/routing.js +53 -3
  203. package/dist/telemetry-coverage/evaluate.d.ts +42 -0
  204. package/dist/telemetry-coverage/evaluate.js +148 -0
  205. package/dist/telemetry-coverage/fake-trial.d.ts +45 -0
  206. package/dist/telemetry-coverage/fake-trial.js +204 -0
  207. package/dist/telemetry-coverage/index.d.ts +5 -0
  208. package/dist/telemetry-coverage/index.js +5 -0
  209. package/dist/telemetry-coverage/kinds.d.ts +19 -0
  210. package/dist/telemetry-coverage/kinds.js +54 -0
  211. package/dist/telemetry-coverage/scan-callers.d.ts +25 -0
  212. package/dist/telemetry-coverage/scan-callers.js +168 -0
  213. package/dist/triage/actions/index.js +4 -1
  214. package/dist/ts-check-lane/index.d.ts +3 -0
  215. package/dist/ts-check-lane/index.js +2 -0
  216. package/dist/ts-check-lane/progress-reporter.d.ts +17 -0
  217. package/dist/ts-check-lane/progress-reporter.js +38 -0
  218. package/dist/ts-check-lane/progress.d.ts +32 -0
  219. package/dist/ts-check-lane/progress.js +57 -0
  220. package/dist/ts-check-lane/run-lane.d.ts +3 -1
  221. package/dist/ts-check-lane/run-lane.js +8 -6
  222. package/dist/validate-content/validate-links.d.ts +8 -0
  223. package/dist/validate-content/validate-links.js +9 -15
  224. package/dist/value/feedback-file.js +12 -2
  225. package/dist/vbrief-build/index.d.ts +1 -0
  226. package/dist/vbrief-build/index.js +1 -0
  227. package/dist/vbrief-build/project-invariants-io.d.ts +16 -0
  228. package/dist/vbrief-build/project-invariants-io.js +41 -0
  229. package/dist/vbrief-reconcile/graph.js +18 -1
  230. package/dist/vbrief-reconcile/index.d.ts +3 -1
  231. package/dist/vbrief-reconcile/index.js +2 -1
  232. package/dist/vbrief-reconcile/origin-freshness.d.ts +44 -0
  233. package/dist/vbrief-reconcile/origin-freshness.js +221 -0
  234. package/dist/vbrief-reconcile/types.d.ts +13 -0
  235. package/dist/vbrief-reconcile/umbrellas.d.ts +14 -0
  236. package/dist/vbrief-reconcile/umbrellas.js +261 -26
  237. package/dist/vbrief-validate/index.d.ts +1 -1
  238. package/dist/vbrief-validate/index.js +1 -1
  239. package/dist/vbrief-validate/plan-hooks.d.ts +4 -0
  240. package/dist/vbrief-validate/plan-hooks.js +68 -0
  241. package/dist/verify-ac/evaluate.d.ts +7 -1
  242. package/dist/verify-ac/evaluate.js +34 -26
  243. package/dist/verify-ac/flag.d.ts +4 -0
  244. package/dist/verify-ac/flag.js +16 -0
  245. package/dist/verify-ac/index.d.ts +2 -2
  246. package/dist/verify-ac/index.js +2 -2
  247. package/dist/verify-source/contained-writes.js +2 -0
  248. package/dist/verify-source/index.d.ts +1 -0
  249. package/dist/verify-source/index.js +1 -0
  250. package/dist/verify-source/verify-stubs.d.ts +15 -1
  251. package/dist/verify-source/verify-stubs.js +20 -16
  252. package/dist/vitest-runner/win32-coverage-tmp-setup.d.ts +5 -6
  253. package/dist/vitest-runner/win32-coverage-tmp-setup.js +5 -6
  254. package/dist/xbrief-migrate/migrate-project.js +2 -5
  255. package/package.json +3 -3
@@ -0,0 +1,211 @@
1
+ /**
2
+ * Shared branch-sync detector (#3388 / #3377 Wave 1).
3
+ *
4
+ * Dest = deliveryBranch. Source = typed baseBranch (unset equals dest → not a
5
+ * sync). Predicate: PR base is dest AND head is already on origin/<source>
6
+ * after fetch (tip or ancestor). Name-only and label-only exemptions are not
7
+ * implemented. origin/develop is never load-bearing identity.
8
+ *
9
+ * This module is the only is-this-a-sync source for later children (#3390/#3391)
10
+ * and for core-guard.
11
+ */
12
+ import { defaultGitRunner, gitIsAncestor } from "../session/git.js";
13
+ import { ORIGIN_DEVELOP_HINT } from "./base-branch.js";
14
+ import { resolveGitDefaultDeliveryBranch } from "./delivery-branch.js";
15
+ import { readPlanPolicy } from "./plan-extensions.js";
16
+ /** Dest-ref blob used for dest/source. Never the PR working tree (#3388 P1). */
17
+ export const BRANCH_SYNC_POLICY_BLOB = "xbrief/PROJECT-DEFINITION.xbrief.json";
18
+ export const BRANCH_SYNC_EXEMPTION_PREFIX = "sync PR detected: all commits already guard-checked on";
19
+ export function formatBranchSyncExemptionMessage(integrationBranch) {
20
+ return `${BRANCH_SYNC_EXEMPTION_PREFIX} ${integrationBranch}`;
21
+ }
22
+ function notSync(input, reason) {
23
+ return {
24
+ isSync: false,
25
+ dest: input.dest,
26
+ source: input.source,
27
+ sourceTyped: input.sourceTyped,
28
+ reason,
29
+ message: "",
30
+ developHint: input.developHint ?? null,
31
+ };
32
+ }
33
+ /**
34
+ * Evidence-based sync predicate (#3388 Q3). Fetch first. Do not trust PR
35
+ * branch names or labels.
36
+ */
37
+ export function detectBranchSync(input) {
38
+ const dest = input.dest.trim();
39
+ const source = input.source.trim();
40
+ if (source.length === 0 || dest.length === 0 || source === dest) {
41
+ return notSync({ ...input, dest, source }, "source-equals-dest");
42
+ }
43
+ if (input.prBase.trim() !== dest) {
44
+ return notSync({ ...input, dest, source }, "base-is-not-dest");
45
+ }
46
+ const runGit = input.runGit ?? defaultGitRunner;
47
+ const fetched = runGit(input.projectRoot, ["fetch", "--quiet", "origin", source]);
48
+ if (fetched.code !== 0) {
49
+ return notSync({ ...input, dest, source }, "fetch-failed");
50
+ }
51
+ const onIntegration = gitIsAncestor(input.projectRoot, input.headSha, `origin/${source}`, runGit);
52
+ if (onIntegration !== true) {
53
+ return notSync({ ...input, dest, source }, "head-not-on-integration");
54
+ }
55
+ return {
56
+ isSync: true,
57
+ dest,
58
+ source,
59
+ sourceTyped: input.sourceTyped,
60
+ reason: "sync",
61
+ message: formatBranchSyncExemptionMessage(source),
62
+ developHint: input.developHint ?? null,
63
+ };
64
+ }
65
+ function parseTypedPolicyBranches(jsonText) {
66
+ try {
67
+ const data = JSON.parse(jsonText);
68
+ if (typeof data !== "object" || data === null || Array.isArray(data)) {
69
+ return { dest: null, source: null };
70
+ }
71
+ const policyBlock = readPlanPolicy(data.plan);
72
+ if (typeof policyBlock !== "object" || policyBlock === null || Array.isArray(policyBlock)) {
73
+ return { dest: null, source: null };
74
+ }
75
+ const rec = policyBlock;
76
+ const destRaw = rec.deliveryBranch;
77
+ const sourceRaw = rec.baseBranch;
78
+ return {
79
+ dest: typeof destRaw === "string" && destRaw.trim().length > 0 ? destRaw.trim() : null,
80
+ source: typeof sourceRaw === "string" && sourceRaw.trim().length > 0 ? sourceRaw.trim() : null,
81
+ };
82
+ }
83
+ catch {
84
+ return { dest: null, source: null };
85
+ }
86
+ }
87
+ /**
88
+ * Load dest/source from origin/<prBase>, not the PR checkout.
89
+ *
90
+ * A feature PR that rewrites working-tree baseBranch cannot become a sync.
91
+ */
92
+ export function resolveSyncPolicyFromDestRef(options) {
93
+ const runGit = options.runGit ?? defaultGitRunner;
94
+ const prBase = options.prBase.trim();
95
+ const fetched = runGit(options.projectRoot, ["fetch", "--quiet", "origin", prBase]);
96
+ if (fetched.code !== 0) {
97
+ const dest = resolveGitDefaultDeliveryBranch(options.projectRoot, runGit);
98
+ const developHint = runGit(options.projectRoot, [
99
+ "show-ref",
100
+ "--verify",
101
+ "--quiet",
102
+ "refs/remotes/origin/develop",
103
+ ]).code === 0
104
+ ? ORIGIN_DEVELOP_HINT
105
+ : null;
106
+ return { dest, source: dest, sourceTyped: false, developHint };
107
+ }
108
+ const shown = runGit(options.projectRoot, [
109
+ "show",
110
+ `origin/${prBase}:${BRANCH_SYNC_POLICY_BLOB}`,
111
+ ]);
112
+ const parsed = shown.code === 0 && shown.stdout.length > 0
113
+ ? parseTypedPolicyBranches(shown.stdout)
114
+ : { dest: null, source: null };
115
+ const dest = parsed.dest ?? resolveGitDefaultDeliveryBranch(options.projectRoot, runGit);
116
+ const sourceTyped = parsed.source !== null;
117
+ const source = parsed.source ?? dest;
118
+ const developHint = sourceTyped ||
119
+ runGit(options.projectRoot, ["show-ref", "--verify", "--quiet", "refs/remotes/origin/develop"])
120
+ .code !== 0
121
+ ? null
122
+ : ORIGIN_DEVELOP_HINT;
123
+ return { dest, source, sourceTyped, developHint };
124
+ }
125
+ /** Load dest/source from dest-ref policy, then run {@link detectBranchSync}. */
126
+ export function detectBranchSyncFromProject(options) {
127
+ const runGit = options.runGit ?? defaultGitRunner;
128
+ const policy = resolveSyncPolicyFromDestRef({
129
+ projectRoot: options.projectRoot,
130
+ prBase: options.prBase,
131
+ runGit,
132
+ });
133
+ return detectBranchSync({
134
+ dest: policy.dest,
135
+ source: policy.source,
136
+ sourceTyped: policy.sourceTyped,
137
+ prBase: options.prBase,
138
+ headSha: options.headSha,
139
+ projectRoot: options.projectRoot,
140
+ developHint: policy.developHint,
141
+ runGit,
142
+ });
143
+ }
144
+ /**
145
+ * Core-guard mix result after the shared sync predicate. Sync PRs pass
146
+ * loudly; mixed feature PRs still fail.
147
+ */
148
+ export function applyCoreGuardWithBranchSync(classification, sync) {
149
+ if (!classification.wouldFail) {
150
+ return { wouldFail: false, loudMessage: null };
151
+ }
152
+ if (sync.isSync) {
153
+ return { wouldFail: false, loudMessage: formatBranchSyncExemptionMessage(sync.source) };
154
+ }
155
+ return { wouldFail: true, loudMessage: null };
156
+ }
157
+ /** Compact Python body for the deposited deft-core-guard (#3388). */
158
+ export function coreGuardBranchSyncPythonBody() {
159
+ return [
160
+ "import json, subprocess, sys",
161
+ "head_sha, pr_base = sys.argv[1], sys.argv[2]",
162
+ "def git(*a):",
163
+ " return subprocess.run(['git', *a], capture_output=True, text=True)",
164
+ "dest = source = None",
165
+ "if git('fetch', '--quiet', 'origin', pr_base).returncode != 0: sys.exit(1)",
166
+ `shown = git('show', 'origin/' + pr_base + ':${BRANCH_SYNC_POLICY_BLOB}')`,
167
+ "if shown.returncode == 0:",
168
+ " try:",
169
+ " plan = json.loads(shown.stdout).get('plan')",
170
+ " except Exception:",
171
+ " plan = None",
172
+ " if isinstance(plan, dict):",
173
+ " pol = plan.get('x-directive/policy') or plan.get('policy') or {}",
174
+ " if isinstance(pol, dict):",
175
+ " d, s = pol.get('deliveryBranch'), pol.get('baseBranch')",
176
+ " if isinstance(d, str) and d.strip(): dest = d.strip()",
177
+ " if isinstance(s, str) and s.strip(): source = s.strip()",
178
+ "if not dest:",
179
+ " r = git('symbolic-ref', 'refs/remotes/origin/HEAD', '--short')",
180
+ " if r.returncode == 0 and r.stdout.strip():",
181
+ " dest = r.stdout.strip().split('/', 1)[-1]",
182
+ " else:",
183
+ " for n in ('main', 'master'):",
184
+ " if git('show-ref', '--verify', '--quiet', 'refs/remotes/origin/' + n).returncode == 0:",
185
+ " dest = n",
186
+ " break",
187
+ " if not dest:",
188
+ " for n in ('main', 'master'):",
189
+ " if git('show-ref', '--verify', '--quiet', 'refs/heads/' + n).returncode == 0:",
190
+ " dest = n",
191
+ " break",
192
+ " if not dest: dest = 'master'",
193
+ "if not source: source = dest",
194
+ "if source == dest or pr_base != dest: sys.exit(1)",
195
+ "if git('fetch', '--quiet', 'origin', source).returncode != 0: sys.exit(1)",
196
+ "if git('merge-base', '--is-ancestor', head_sha, 'origin/' + source).returncode != 0: sys.exit(1)",
197
+ `print('${BRANCH_SYNC_EXEMPTION_PREFIX} ' + source)`,
198
+ ];
199
+ }
200
+ /** Indented `if` block: detector success exits 0 (loud print); else fall through. */
201
+ export function renderCoreGuardBranchSyncIfBlock(indent) {
202
+ return [
203
+ `${indent}if python3 - "$HEAD_SHA" "$BASE_REF" <<'PY'`,
204
+ ...coreGuardBranchSyncPythonBody().map((line) => `${indent}${line}`),
205
+ `${indent}PY`,
206
+ `${indent}then`,
207
+ `${indent} exit 0`,
208
+ `${indent}fi`,
209
+ ].join("\n");
210
+ }
211
+ //# sourceMappingURL=branch-sync.js.map
@@ -77,6 +77,7 @@ export function emitCeremonyDialEscalationEvaluation(options) {
77
77
  projectRoot: options.projectRoot,
78
78
  sessionId: options.sessionId,
79
79
  env: options.env,
80
+ component: "ceremony-dial",
80
81
  });
81
82
  emitter.emitDialEscalationEvaluation({
82
83
  tier: options.evaluation.tier,
@@ -990,12 +990,6 @@ export function escalateCeremonyDial(projectRoot, options) {
990
990
  return;
991
991
  }
992
992
  try {
993
- const audit = readCeremonyDialAudit(projectRoot);
994
- const rawSid = audit.raw?.session_id;
995
- const sid = options.sessionId ??
996
- (typeof rawSid === "string" && rawSid.length > 0
997
- ? rawSid
998
- : `dial-${Date.now().toString(36)}`);
999
993
  const rank = {
1000
994
  minimal: 0,
1001
995
  rapid: 1,
@@ -1012,8 +1006,9 @@ export function escalateCeremonyDial(projectRoot, options) {
1012
1006
  : baseReason;
1013
1007
  const emitter = new RunSummaryEmitter({
1014
1008
  projectRoot,
1015
- sessionId: sid,
1009
+ sessionId: options.sessionId,
1016
1010
  env: options.env,
1011
+ component: "ceremony-dial",
1017
1012
  });
1018
1013
  emitter.emitDialEscalationEvaluation({
1019
1014
  tier: outcome === "escalated" ? options.to : from,
@@ -1065,16 +1060,11 @@ export function escalateCeremonyDial(projectRoot, options) {
1065
1060
  // #3282: event-driven dial_transition line (fail-open).
1066
1061
  if (options.emitRunSummary !== false) {
1067
1062
  try {
1068
- const audit = readCeremonyDialAudit(projectRoot);
1069
- const rawSid = audit.raw?.session_id;
1070
- const sid = options.sessionId ??
1071
- (typeof rawSid === "string" && rawSid.length > 0
1072
- ? rawSid
1073
- : `dial-${Date.now().toString(36)}`);
1074
1063
  const emitter = new RunSummaryEmitter({
1075
1064
  projectRoot,
1076
- sessionId: sid,
1065
+ sessionId: options.sessionId,
1077
1066
  env: options.env,
1067
+ component: "ceremony-dial",
1078
1068
  });
1079
1069
  emitter.emitDialTransition({
1080
1070
  from,
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * Typed plan.policy.deliveryBranch (#3041).
3
3
  *
4
- * Distinct from swarm/PR `baseBranch` (integration target for PRs / finalize
5
- * sweep PRs). deliveryBranch is where shipped work must land for a delivered
6
- * completion disposition.
4
+ * Distinct from typed `plan.policy.baseBranch` (#3388), the integration-branch
5
+ * source for the shared branch-sync detector. deliveryBranch is dest: where
6
+ * shipped work must land for a delivered completion disposition.
7
7
  */
8
8
  import { type GitRunner } from "../session/git.js";
9
9
  export declare const FIELD_DELIVERY_BRANCH = "plan.policy.deliveryBranch";
@@ -16,6 +16,8 @@ export interface DeliveryBranchResult {
16
16
  readonly source: DeliveryBranchSource;
17
17
  readonly error: string | null;
18
18
  }
19
+ /** Git-only dest when dest-ref policy has no typed deliveryBranch (#3388). */
20
+ export declare function resolveGitDefaultDeliveryBranch(projectRoot: string, runGit?: GitRunner): string;
19
21
  /**
20
22
  * Resolve the project's delivery branch (#3041).
21
23
  *
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * Typed plan.policy.deliveryBranch (#3041).
3
3
  *
4
- * Distinct from swarm/PR `baseBranch` (integration target for PRs / finalize
5
- * sweep PRs). deliveryBranch is where shipped work must land for a delivered
6
- * completion disposition.
4
+ * Distinct from typed `plan.policy.baseBranch` (#3388), the integration-branch
5
+ * source for the shared branch-sync detector. deliveryBranch is dest: where
6
+ * shipped work must land for a delivered completion disposition.
7
7
  */
8
8
  import { defaultGitRunner } from "../session/git.js";
9
9
  import { readPlanPolicy } from "./plan-extensions.js";
@@ -50,6 +50,10 @@ function defaultBranchCandidates(projectRoot, runGit) {
50
50
  }
51
51
  return candidates;
52
52
  }
53
+ /** Git-only dest when dest-ref policy has no typed deliveryBranch (#3388). */
54
+ export function resolveGitDefaultDeliveryBranch(projectRoot, runGit = defaultGitRunner) {
55
+ return defaultBranchCandidates(projectRoot, runGit)[0] ?? DEFAULT_DELIVERY_BRANCH_FALLBACK;
56
+ }
53
57
  /**
54
58
  * Resolve the project's delivery branch (#3041).
55
59
  *
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Single machine-readable source of truth for per-file size guidance (#3424).
3
+ *
4
+ * `coding.md` and companion prose MUST reference these exports. They are
5
+ * review / planning triggers, not a hard line cap (#1488).
6
+ */
7
+ /** Preferred size for a focused file. */
8
+ export declare const FILE_SIZE_IDEAL_LINES = 300;
9
+ /** Recommended upper bound before a file should be treated as large. */
10
+ export declare const FILE_SIZE_RECOMMENDED_LINES = 500;
11
+ /**
12
+ * Review-trigger line count. A declared file at or above this size cannot
13
+ * pass preflight without a recorded split plan or cohesion exemption.
14
+ * Size alone is never a fail-closed reject.
15
+ */
16
+ export declare const FILE_SIZE_REVIEW_TRIGGER_LINES = 1000;
17
+ /** Canonical bundle so callers do not restate the three numbers. */
18
+ export declare const FILE_SIZE_THRESHOLDS: {
19
+ readonly idealLines: 300;
20
+ readonly recommendedLines: 500;
21
+ readonly reviewTriggerLines: 1000;
22
+ };
23
+ export type FileSizeThresholds = typeof FILE_SIZE_THRESHOLDS;
24
+ //# sourceMappingURL=file-size-thresholds.d.ts.map
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Single machine-readable source of truth for per-file size guidance (#3424).
3
+ *
4
+ * `coding.md` and companion prose MUST reference these exports. They are
5
+ * review / planning triggers, not a hard line cap (#1488).
6
+ */
7
+ /** Preferred size for a focused file. */
8
+ export const FILE_SIZE_IDEAL_LINES = 300;
9
+ /** Recommended upper bound before a file should be treated as large. */
10
+ export const FILE_SIZE_RECOMMENDED_LINES = 500;
11
+ /**
12
+ * Review-trigger line count. A declared file at or above this size cannot
13
+ * pass preflight without a recorded split plan or cohesion exemption.
14
+ * Size alone is never a fail-closed reject.
15
+ */
16
+ export const FILE_SIZE_REVIEW_TRIGGER_LINES = 1000;
17
+ /** Canonical bundle so callers do not restate the three numbers. */
18
+ export const FILE_SIZE_THRESHOLDS = {
19
+ idealLines: FILE_SIZE_IDEAL_LINES,
20
+ recommendedLines: FILE_SIZE_RECOMMENDED_LINES,
21
+ reviewTriggerLines: FILE_SIZE_REVIEW_TRIGGER_LINES,
22
+ };
23
+ //# sourceMappingURL=file-size-thresholds.js.map
@@ -0,0 +1,47 @@
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
+ export declare const FIELD_FORGE_OUTAGE_RETRY_MINUTES = "plan.policy.forgeOutageRetryMinutes";
9
+ export declare const FIELD_FORGE_OUTAGE_RETRY_MINUTES_CLI_ALIAS = "forgeOutageRetryMinutes";
10
+ export declare const DEFAULT_FORGE_OUTAGE_RETRY_MINUTES = 30;
11
+ export declare const MIN_FORGE_OUTAGE_RETRY_MINUTES = 5;
12
+ export type ForgeOutageRetrySource = "user-md" | "typed" | "default" | "default-on-error";
13
+ export interface ForgeOutageRetryResolved {
14
+ readonly minutes: number;
15
+ readonly source: ForgeOutageRetrySource;
16
+ readonly error: string | null;
17
+ }
18
+ export interface ForgeOutageRetryPolicyField {
19
+ readonly name: typeof FIELD_FORGE_OUTAGE_RETRY_MINUTES;
20
+ readonly current: number;
21
+ readonly default: number;
22
+ readonly source: string;
23
+ }
24
+ export interface ResolveForgeOutageRetryOptions {
25
+ readonly projectRoot?: string | null;
26
+ readonly env?: NodeJS.ProcessEnv;
27
+ readonly userMdText?: string | null;
28
+ }
29
+ /** Validate a raw integer-minutes value. */
30
+ export declare function validateForgeOutageRetryMinutes(raw: unknown): string | null;
31
+ /**
32
+ * Parse USER.md Personal forge-outage retry minutes.
33
+ *
34
+ * Accepts `forgeOutageRetryMinutes: 15` or `Forge outage retry: 15m`.
35
+ */
36
+ export declare function parseForgeOutageRetryMinutesFromUserMd(text: string): number | null;
37
+ /**
38
+ * Resolve forge-outage re-probe minutes (#3422).
39
+ *
40
+ * 1. Valid USER.md Personal value
41
+ * 2. Valid plan.policy.forgeOutageRetryMinutes
42
+ * 3. Framework default 30
43
+ */
44
+ export declare function resolveForgeOutageRetryMinutes(options?: ResolveForgeOutageRetryOptions): ForgeOutageRetryResolved;
45
+ /** Inspector row for `task policy:show --field=forgeOutageRetryMinutes`. */
46
+ export declare function inspectForgeOutageRetryMinutes(_data: Record<string, unknown> | null, projectRoot?: string): ForgeOutageRetryPolicyField;
47
+ //# sourceMappingURL=forge-outage-retry.d.ts.map
@@ -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
@@ -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";