@open-agent-toolkit/cli 0.2.65 → 0.2.67

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 (238) hide show
  1. package/assets/bundle-metadata.json +1 -1
  2. package/assets/docs/cli-utilities/configuration.md +33 -2
  3. package/assets/docs/cli-utilities/index.md +3 -0
  4. package/assets/docs/cli-utilities/project-log.md +63 -4
  5. package/assets/docs/cli-utilities/remote-project-management.md +191 -0
  6. package/assets/docs/contributing/code.md +8 -4
  7. package/assets/docs/contributing/skills.md +29 -17
  8. package/assets/docs/docs-tooling/commands.md +3 -1
  9. package/assets/docs/provider-sync/manifest-and-drift.md +2 -18
  10. package/assets/docs/reference/cli-reference.md +12 -1
  11. package/assets/docs/reference/file-locations.md +22 -0
  12. package/assets/docs/reference/oat-directory-structure.md +30 -17
  13. package/assets/docs/reference/troubleshooting.md +44 -0
  14. package/assets/docs/workflows/projects/lifecycle.md +17 -0
  15. package/assets/docs/workflows/projects/picking-up-projects.md +18 -0
  16. package/assets/docs/workflows/skills/index.md +33 -0
  17. package/assets/docs/workflows/skills/repo-improve.md +7 -3
  18. package/assets/public-package-versions.json +4 -4
  19. package/assets/skills/create-agnostic-skill/SKILL.md +19 -37
  20. package/assets/skills/create-agnostic-skill/references/docs/skills-guide.md +58 -15
  21. package/assets/skills/create-agnostic-skill/references/skill-template.md +17 -15
  22. package/assets/skills/oat-agent-instructions-apply/SKILL.md +1 -1
  23. package/assets/skills/oat-agent-instructions-apply/references/instruction-file-templates/glob-scoped-rule.md +1 -4
  24. package/assets/skills/oat-doctor/SKILL.md +3 -6
  25. package/assets/skills/oat-pjm-remote/SKILL.md +101 -0
  26. package/assets/skills/oat-pjm-remote/references/external-action-protocol.md +43 -0
  27. package/assets/skills/oat-project-autonomous/references/gate-inventory.md +1 -1
  28. package/assets/skills/oat-project-complete/SKILL.md +158 -30
  29. package/assets/skills/oat-project-complete/scripts/finalize-synced-archive.mjs +26 -7
  30. package/assets/skills/oat-project-complete/scripts/validate-durable-archive-receipt.mjs +183 -0
  31. package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +1 -1
  32. package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +1 -1
  33. package/assets/skills/oat-project-lite/references/docs/autonomy-contract.md +1 -1
  34. package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +1 -1
  35. package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +1 -1
  36. package/assets/skills/oat-project-retro/SKILL.md +1 -1
  37. package/assets/skills/oat-project-retro/references/apply-procedure.md +11 -0
  38. package/assets/skills/oat-project-review-provide/SKILL.md +4 -4
  39. package/assets/skills/oat-project-summary/SKILL.md +24 -2
  40. package/assets/skills/oat-repo-improve/SKILL.md +9 -2
  41. package/assets/skills/oat-repo-improve/references/plan-template.md +4 -6
  42. package/assets/skills/oat-repo-knowledge-index/SKILL.md +11 -9
  43. package/assets/skills/oat-wave-execute/SKILL.md +20 -6
  44. package/assets/skills/oat-wave-program/SKILL.md +9 -4
  45. package/dist/commands/backlog/new.d.ts +1 -0
  46. package/dist/commands/backlog/new.d.ts.map +1 -1
  47. package/dist/commands/backlog/new.js +3 -1
  48. package/dist/commands/config/index.d.ts +3 -1
  49. package/dist/commands/config/index.d.ts.map +1 -1
  50. package/dist/commands/config/index.js +362 -36
  51. package/dist/commands/docs/index-generate/index.d.ts.map +1 -1
  52. package/dist/commands/docs/index-generate/index.js +68 -12
  53. package/dist/commands/docs/init/index.d.ts +11 -0
  54. package/dist/commands/docs/init/index.d.ts.map +1 -1
  55. package/dist/commands/docs/init/index.js +19 -1
  56. package/dist/commands/gate/index.d.ts.map +1 -1
  57. package/dist/commands/gate/index.js +10 -2
  58. package/dist/commands/instructions/instructions.utils.d.ts.map +1 -1
  59. package/dist/commands/instructions/instructions.utils.js +42 -9
  60. package/dist/commands/internal/validate-skill-version-bumps.d.ts.map +1 -1
  61. package/dist/commands/internal/validate-skill-version-bumps.js +5 -5
  62. package/dist/commands/pjm/doctor.d.ts +2 -0
  63. package/dist/commands/pjm/doctor.d.ts.map +1 -1
  64. package/dist/commands/pjm/doctor.js +71 -1
  65. package/dist/commands/pjm/index.d.ts +2 -0
  66. package/dist/commands/pjm/index.d.ts.map +1 -1
  67. package/dist/commands/pjm/index.js +3 -0
  68. package/dist/commands/pjm/remote/__integration__/lifecycle-harness.d.ts +60 -0
  69. package/dist/commands/pjm/remote/__integration__/lifecycle-harness.d.ts.map +1 -0
  70. package/dist/commands/pjm/remote/__integration__/lifecycle-harness.js +151 -0
  71. package/dist/commands/pjm/remote/association.d.ts +27 -0
  72. package/dist/commands/pjm/remote/association.d.ts.map +1 -0
  73. package/dist/commands/pjm/remote/association.js +68 -0
  74. package/dist/commands/pjm/remote/authority.d.ts +210 -0
  75. package/dist/commands/pjm/remote/authority.d.ts.map +1 -0
  76. package/dist/commands/pjm/remote/authority.js +341 -0
  77. package/dist/commands/pjm/remote/batch.d.ts +15 -0
  78. package/dist/commands/pjm/remote/batch.d.ts.map +1 -0
  79. package/dist/commands/pjm/remote/batch.js +126 -0
  80. package/dist/commands/pjm/remote/closeout.d.ts +69 -0
  81. package/dist/commands/pjm/remote/closeout.d.ts.map +1 -0
  82. package/dist/commands/pjm/remote/closeout.js +208 -0
  83. package/dist/commands/pjm/remote/create-binding.d.ts +62 -0
  84. package/dist/commands/pjm/remote/create-binding.d.ts.map +1 -0
  85. package/dist/commands/pjm/remote/create-binding.js +126 -0
  86. package/dist/commands/pjm/remote/credential-safety.d.ts +7 -0
  87. package/dist/commands/pjm/remote/credential-safety.d.ts.map +1 -0
  88. package/dist/commands/pjm/remote/credential-safety.js +21 -0
  89. package/dist/commands/pjm/remote/discussion.d.ts +49 -0
  90. package/dist/commands/pjm/remote/discussion.d.ts.map +1 -0
  91. package/dist/commands/pjm/remote/discussion.js +124 -0
  92. package/dist/commands/pjm/remote/doctor.d.ts +22 -0
  93. package/dist/commands/pjm/remote/doctor.d.ts.map +1 -0
  94. package/dist/commands/pjm/remote/doctor.js +380 -0
  95. package/dist/commands/pjm/remote/external-action.d.ts +208 -0
  96. package/dist/commands/pjm/remote/external-action.d.ts.map +1 -0
  97. package/dist/commands/pjm/remote/external-action.js +367 -0
  98. package/dist/commands/pjm/remote/host-execution.d.ts +28 -0
  99. package/dist/commands/pjm/remote/host-execution.d.ts.map +1 -0
  100. package/dist/commands/pjm/remote/host-execution.js +63 -0
  101. package/dist/commands/pjm/remote/index.d.ts +41 -0
  102. package/dist/commands/pjm/remote/index.d.ts.map +1 -0
  103. package/dist/commands/pjm/remote/index.js +280 -0
  104. package/dist/commands/pjm/remote/jira-adf.d.ts +35 -0
  105. package/dist/commands/pjm/remote/jira-adf.d.ts.map +1 -0
  106. package/dist/commands/pjm/remote/jira-adf.js +169 -0
  107. package/dist/commands/pjm/remote/lifecycle.d.ts +163 -0
  108. package/dist/commands/pjm/remote/lifecycle.d.ts.map +1 -0
  109. package/dist/commands/pjm/remote/lifecycle.js +224 -0
  110. package/dist/commands/pjm/remote/local-projection.d.ts +30 -0
  111. package/dist/commands/pjm/remote/local-projection.d.ts.map +1 -0
  112. package/dist/commands/pjm/remote/local-projection.js +95 -0
  113. package/dist/commands/pjm/remote/managed-markdown.d.ts +30 -0
  114. package/dist/commands/pjm/remote/managed-markdown.d.ts.map +1 -0
  115. package/dist/commands/pjm/remote/managed-markdown.js +128 -0
  116. package/dist/commands/pjm/remote/migrate.d.ts +14 -0
  117. package/dist/commands/pjm/remote/migrate.d.ts.map +1 -0
  118. package/dist/commands/pjm/remote/migrate.js +32 -0
  119. package/dist/commands/pjm/remote/operation-state.d.ts +15 -0
  120. package/dist/commands/pjm/remote/operation-state.d.ts.map +1 -0
  121. package/dist/commands/pjm/remote/operation-state.js +143 -0
  122. package/dist/commands/pjm/remote/outbound-projection-safety.d.ts +25 -0
  123. package/dist/commands/pjm/remote/outbound-projection-safety.d.ts.map +1 -0
  124. package/dist/commands/pjm/remote/outbound-projection-safety.js +99 -0
  125. package/dist/commands/pjm/remote/output.d.ts +60 -0
  126. package/dist/commands/pjm/remote/output.d.ts.map +1 -0
  127. package/dist/commands/pjm/remote/output.js +48 -0
  128. package/dist/commands/pjm/remote/preview.d.ts +88 -0
  129. package/dist/commands/pjm/remote/preview.d.ts.map +1 -0
  130. package/dist/commands/pjm/remote/preview.js +154 -0
  131. package/dist/commands/pjm/remote/provider-conformance.d.ts +13 -0
  132. package/dist/commands/pjm/remote/provider-conformance.d.ts.map +1 -0
  133. package/dist/commands/pjm/remote/provider-conformance.js +37 -0
  134. package/dist/commands/pjm/remote/provider.d.ts +57 -0
  135. package/dist/commands/pjm/remote/provider.d.ts.map +1 -0
  136. package/dist/commands/pjm/remote/provider.js +28 -0
  137. package/dist/commands/pjm/remote/providers/github-publication-safety.d.ts +46 -0
  138. package/dist/commands/pjm/remote/providers/github-publication-safety.d.ts.map +1 -0
  139. package/dist/commands/pjm/remote/providers/github-publication-safety.js +126 -0
  140. package/dist/commands/pjm/remote/providers/github.d.ts +207 -0
  141. package/dist/commands/pjm/remote/providers/github.d.ts.map +1 -0
  142. package/dist/commands/pjm/remote/providers/github.js +1456 -0
  143. package/dist/commands/pjm/remote/providers/jira.d.ts +245 -0
  144. package/dist/commands/pjm/remote/providers/jira.d.ts.map +1 -0
  145. package/dist/commands/pjm/remote/providers/jira.js +1650 -0
  146. package/dist/commands/pjm/remote/providers/linear.d.ts +182 -0
  147. package/dist/commands/pjm/remote/providers/linear.d.ts.map +1 -0
  148. package/dist/commands/pjm/remote/providers/linear.js +1289 -0
  149. package/dist/commands/pjm/remote/purpose-policy.d.ts +29 -0
  150. package/dist/commands/pjm/remote/purpose-policy.d.ts.map +1 -0
  151. package/dist/commands/pjm/remote/purpose-policy.js +118 -0
  152. package/dist/commands/pjm/remote/reconcile.d.ts +42 -0
  153. package/dist/commands/pjm/remote/reconcile.d.ts.map +1 -0
  154. package/dist/commands/pjm/remote/reconcile.js +101 -0
  155. package/dist/commands/pjm/remote/resolution.d.ts +122 -0
  156. package/dist/commands/pjm/remote/resolution.d.ts.map +1 -0
  157. package/dist/commands/pjm/remote/resolution.js +243 -0
  158. package/dist/commands/pjm/remote/schema.d.ts +9309 -0
  159. package/dist/commands/pjm/remote/schema.d.ts.map +1 -0
  160. package/dist/commands/pjm/remote/schema.js +1503 -0
  161. package/dist/commands/pjm/remote/service.d.ts +20 -0
  162. package/dist/commands/pjm/remote/service.d.ts.map +1 -0
  163. package/dist/commands/pjm/remote/service.js +5121 -0
  164. package/dist/commands/pjm/remote/shared-storage.d.ts +36 -0
  165. package/dist/commands/pjm/remote/shared-storage.d.ts.map +1 -0
  166. package/dist/commands/pjm/remote/shared-storage.js +110 -0
  167. package/dist/commands/pjm/remote/snapshot.d.ts +32 -0
  168. package/dist/commands/pjm/remote/snapshot.d.ts.map +1 -0
  169. package/dist/commands/pjm/remote/snapshot.js +140 -0
  170. package/dist/commands/pjm/remote/storage-locator.d.ts +29 -0
  171. package/dist/commands/pjm/remote/storage-locator.d.ts.map +1 -0
  172. package/dist/commands/pjm/remote/storage-locator.js +62 -0
  173. package/dist/commands/pjm/remote/store.d.ts +85 -0
  174. package/dist/commands/pjm/remote/store.d.ts.map +1 -0
  175. package/dist/commands/pjm/remote/store.js +553 -0
  176. package/dist/commands/pjm/remote/verification.d.ts +40 -0
  177. package/dist/commands/pjm/remote/verification.d.ts.map +1 -0
  178. package/dist/commands/pjm/remote/verification.js +100 -0
  179. package/dist/commands/project/dispatch-ceiling/index.d.ts.map +1 -1
  180. package/dist/commands/project/dispatch-ceiling/index.js +32 -18
  181. package/dist/commands/project/log/append.d.ts +48 -0
  182. package/dist/commands/project/log/append.d.ts.map +1 -1
  183. package/dist/commands/project/log/append.js +207 -30
  184. package/dist/commands/project/log/check.d.ts +87 -1
  185. package/dist/commands/project/log/check.d.ts.map +1 -1
  186. package/dist/commands/project/log/check.js +139 -5
  187. package/dist/commands/project/log/grammar.d.ts +165 -0
  188. package/dist/commands/project/log/grammar.d.ts.map +1 -1
  189. package/dist/commands/project/log/grammar.js +219 -1
  190. package/dist/commands/project/log/rollup.d.ts +16 -1
  191. package/dist/commands/project/log/rollup.d.ts.map +1 -1
  192. package/dist/commands/project/log/rollup.js +22 -2
  193. package/dist/commands/project/log/synthesize.d.ts +16 -0
  194. package/dist/commands/project/log/synthesize.d.ts.map +1 -1
  195. package/dist/commands/project/log/synthesize.js +85 -9
  196. package/dist/commands/status/index.d.ts.map +1 -1
  197. package/dist/commands/status/index.js +24 -2
  198. package/dist/commands/sync/apply.d.ts.map +1 -1
  199. package/dist/commands/sync/apply.js +6 -4
  200. package/dist/commands/tools/shared/pack-manifest.d.ts.map +1 -1
  201. package/dist/commands/tools/shared/pack-manifest.js +1 -0
  202. package/dist/config/dispatch-matrix.d.ts.map +1 -1
  203. package/dist/config/dispatch-matrix.js +13 -5
  204. package/dist/config/oat-config.d.ts +41 -0
  205. package/dist/config/oat-config.d.ts.map +1 -1
  206. package/dist/config/oat-config.js +247 -9
  207. package/dist/config/own-keys.d.ts +22 -0
  208. package/dist/config/own-keys.d.ts.map +1 -0
  209. package/dist/config/own-keys.js +32 -0
  210. package/dist/config/resolve.d.ts +11 -0
  211. package/dist/config/resolve.d.ts.map +1 -1
  212. package/dist/config/resolve.js +35 -11
  213. package/dist/config/sync-config.d.ts.map +1 -1
  214. package/dist/config/sync-config.js +16 -0
  215. package/dist/drift/detector.d.ts.map +1 -1
  216. package/dist/drift/detector.js +52 -1
  217. package/dist/drift/skill-view-diagnostic.d.ts.map +1 -1
  218. package/dist/drift/skill-view-diagnostic.js +2 -23
  219. package/dist/engine/compute-plan.d.ts.map +1 -1
  220. package/dist/engine/compute-plan.js +22 -72
  221. package/dist/engine/managed-copy-hash.d.ts +69 -0
  222. package/dist/engine/managed-copy-hash.d.ts.map +1 -0
  223. package/dist/engine/managed-copy-hash.js +175 -0
  224. package/dist/fs/assets.d.ts +11 -0
  225. package/dist/fs/assets.d.ts.map +1 -1
  226. package/dist/fs/assets.js +1 -1
  227. package/dist/manifest/hash.d.ts +110 -0
  228. package/dist/manifest/hash.d.ts.map +1 -1
  229. package/dist/manifest/hash.js +111 -13
  230. package/dist/providers/ceiling/registry.d.ts.map +1 -1
  231. package/dist/providers/ceiling/registry.js +6 -1
  232. package/dist/providers/identity/dispatch-report.d.ts.map +1 -1
  233. package/dist/providers/identity/dispatch-report.js +4 -1
  234. package/dist/release/public-package-contract.d.ts.map +1 -1
  235. package/dist/release/public-package-contract.js +21 -0
  236. package/dist/validation/skills.d.ts.map +1 -1
  237. package/dist/validation/skills.js +305 -40
  238. package/package.json +2 -2
@@ -94,6 +94,28 @@ function isInside(parent, candidate) {
94
94
  * dangling-link hops resolved below.
95
95
  */
96
96
  const MAX_SYMLINK_HOPS = 32;
97
+ /**
98
+ * The hop-cap refusal, addressed to whoever owns the offending path.
99
+ *
100
+ * A derived docs directory is unusable path *configuration*, so it takes
101
+ * `CONFIGURATION_EXIT_CODE` and the `documentation.root` repair, exactly like
102
+ * `missingRootError` and the "not a directory" refusal. An explicitly supplied
103
+ * path stays an actionable flag error.
104
+ */
105
+ function hopCapError(context) {
106
+ const preamble = `Refusing to resolve ${context.origin}: its symlink chain exceeds ` +
107
+ `${MAX_SYMLINK_HOPS} hops. `;
108
+ if (context.role.kind === 'docs-dir') {
109
+ if (context.role.derived) {
110
+ return new CliError(`${preamble}The docs directory is derived from \`documentation.root\` ` +
111
+ 'in .oat/config.json. Repair it with ' +
112
+ '`oat config set documentation.root <path>`, or pass --docs-dir with a ' +
113
+ 'path that is not a deep symlink chain.', CONFIGURATION_EXIT_CODE);
114
+ }
115
+ return new CliError(`${preamble}Pass --docs-dir with a path that is not a deep symlink chain.`, REFUSAL_EXIT_CODE);
116
+ }
117
+ return new CliError(`${preamble}Pass --output with a path that is not a deep symlink chain.`, REFUSAL_EXIT_CODE);
118
+ }
97
119
  /**
98
120
  * Absolute path with symlinks resolved, so a symlinked parent cannot smuggle a
99
121
  * write into a protected tree past the lexical containment checks.
@@ -105,7 +127,7 @@ const MAX_SYMLINK_HOPS = 32;
105
127
  * relative link destination is joined to the parent's *real* location rather
106
128
  * than its lexical spelling.
107
129
  */
108
- async function canonicalize(target, deps, linkHops = 0) {
130
+ async function canonicalize(target, deps, context, linkHops = 0) {
109
131
  const absolute = resolve(target);
110
132
  try {
111
133
  return await deps.realpath(absolute);
@@ -120,7 +142,7 @@ async function canonicalize(target, deps, linkHops = 0) {
120
142
  if (parent === absolute) {
121
143
  return absolute;
122
144
  }
123
- const canonicalParent = await canonicalize(parent, deps, linkHops);
145
+ const canonicalParent = await canonicalize(parent, deps, context, linkHops);
124
146
  const candidate = join(canonicalParent, basename(absolute));
125
147
  const linkTarget = await deps.readLinkIfSymlink(candidate);
126
148
  if (linkTarget === null) {
@@ -128,10 +150,9 @@ async function canonicalize(target, deps, linkHops = 0) {
128
150
  }
129
151
  if (linkHops >= MAX_SYMLINK_HOPS) {
130
152
  // Fail closed: falling through would hand the writer an unresolved link.
131
- throw new CliError(`Refusing to resolve ${target}: its symlink chain exceeds ${MAX_SYMLINK_HOPS} hops. ` +
132
- 'Pass --output with a path that is not a deep symlink chain.', REFUSAL_EXIT_CODE);
153
+ throw hopCapError(context);
133
154
  }
134
- return canonicalize(resolve(canonicalParent, linkTarget), deps, linkHops + 1);
155
+ return canonicalize(resolve(canonicalParent, linkTarget), deps, context, linkHops + 1);
135
156
  }
136
157
  function trimmed(value) {
137
158
  const trimmedValue = value?.trim();
@@ -229,9 +250,9 @@ async function resolveIndexGeneratePaths(context, options, deps) {
229
250
  };
230
251
  }
231
252
  /** `canonicalize`, but an unresolvable path yields null instead of throwing. */
232
- async function canonicalizeOrNull(target, deps) {
253
+ async function canonicalizeOrNull(target, deps, role) {
233
254
  try {
234
- return await canonicalize(target, deps);
255
+ return await canonicalize(target, deps, { role, origin: target });
235
256
  }
236
257
  catch {
237
258
  return null;
@@ -242,20 +263,34 @@ async function canonicalizeIndexGeneratePaths(resolved, deps) {
242
263
  const lexicalDocumentationConfig = documentationConfigValue
243
264
  ? resolve(resolved.repoRoot, documentationConfigValue)
244
265
  : null;
266
+ // Resolution order is load-bearing: the docs directory is canonicalized
267
+ // first, and the safety checks below compare against its canonical form.
245
268
  return {
246
- docsDir: await canonicalize(resolved.docsDir, deps),
247
- outputPath: await canonicalize(resolved.outputPath, deps),
269
+ docsDir: await canonicalize(resolved.docsDir, deps, {
270
+ role: {
271
+ kind: 'docs-dir',
272
+ derived: resolved.docsDirSource !== 'flag',
273
+ },
274
+ origin: resolved.docsDir,
275
+ }),
276
+ outputPath: await canonicalize(resolved.outputPath, deps, {
277
+ role: { kind: 'output' },
278
+ origin: resolved.outputPath,
279
+ }),
248
280
  // An unusable configured root only makes the config write ineligible; it
249
281
  // must not fail a run whose paths were both supplied explicitly.
250
282
  configuredRoot: resolved.configuredRoot
251
- ? await canonicalizeOrNull(resolved.configuredRoot, deps)
283
+ ? await canonicalizeOrNull(resolved.configuredRoot, deps, {
284
+ kind: 'other',
285
+ })
252
286
  : null,
253
287
  lexicalDocumentationConfig,
254
288
  // Falling back to the lexical path keeps the refusal guard intact when the
255
289
  // configured tool config cannot be canonicalized.
256
290
  documentationConfig: lexicalDocumentationConfig
257
- ? ((await canonicalizeOrNull(lexicalDocumentationConfig, deps)) ??
258
- lexicalDocumentationConfig)
291
+ ? ((await canonicalizeOrNull(lexicalDocumentationConfig, deps, {
292
+ kind: 'other',
293
+ })) ?? lexicalDocumentationConfig)
259
294
  : null,
260
295
  };
261
296
  }
@@ -364,11 +399,32 @@ async function runIndexGenerate(context, options, deps) {
364
399
  entriesGenerated: entries.length,
365
400
  docsDir,
366
401
  docsDirSource: resolved.docsDirSource,
402
+ // Exactly the list handed to `deps.generateIndex` above, so a missing
403
+ // page can be attributed without re-deriving the merge.
404
+ excludes: resolved.excludes,
367
405
  outputPath,
368
406
  });
369
407
  return;
370
408
  }
371
409
  context.logger.info(`Generated index with ${entries.length} entries from ${docsDir} → ${outputPath}`);
410
+ // A bare `0 entries` reads identically for an empty tree, a wrong
411
+ // `--docs-dir`, and exclusions that swallowed everything. Say which of those
412
+ // the operator should look at. This reports; it never changes the exit code
413
+ // or the written file.
414
+ //
415
+ // The wording is deliberately observational. This function sees indexed
416
+ // entries, never pattern matches, so it cannot know an exclusion actually
417
+ // matched anything: an empty tree with a pattern that matched nothing lands
418
+ // here too, and blaming the exclusions outright would be false in exactly
419
+ // that case.
420
+ if (entries.length === 0) {
421
+ context.logger.info(resolved.excludes.length > 0
422
+ ? `No pages were indexed, with ${resolved.excludes.length} exclusion ` +
423
+ `pattern${resolved.excludes.length === 1 ? '' : 's'} active ` +
424
+ `(${resolved.excludes.join(', ')}). Check whether ` +
425
+ '`documentation.excludes` or --exclude is hiding the pages you expect.'
426
+ : `No pages were indexed: ${docsDir} contained no indexable pages.`);
427
+ }
372
428
  }
373
429
  async function runIndexGenerateCommand(context, options, dependencies) {
374
430
  try {
@@ -21,6 +21,17 @@ interface DocsInitDependencies {
21
21
  readOatConfig: (repoRoot: string) => Promise<OatConfig>;
22
22
  confirmAction: (message: string, ctx: PromptContext) => Promise<boolean>;
23
23
  }
24
+ /**
25
+ * The AGENTS.md `## Documentation` section for a freshly scaffolded app.
26
+ *
27
+ * Each bullet names the file that owns one role, matching what
28
+ * `buildDocumentationConfig` seeds into `documentation.*`. A Fumadocs app has
29
+ * two index files -- the authored source page under `docs/` and the app-root
30
+ * manifest `oat docs generate-index` writes -- and `documentation.index` names
31
+ * the second, so a single "Index file" bullet pointing at the first documented
32
+ * a file the config does not name. MkDocs has no generated manifest: its
33
+ * `documentation.index` is the nav YAML the Config bullet already names.
34
+ */
24
35
  export declare function buildDocsSectionBody(options: DocsInitResolvedOptions): string;
25
36
  export declare function createDocsInitCommand(overrides?: Partial<DocsInitDependencies>): Command;
26
37
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/docs/init/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,KAAK,mBAAmB,EAIzB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAGL,KAAK,aAAa,EAClB,KAAK,YAAY,EAElB,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EACL,KAAK,SAAS,EAGf,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAG5C,OAAO,EAIL,KAAK,uBAAuB,EAK7B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAEL,KAAK,sBAAsB,EAC5B,MAAM,gBAAgB,CAAC;AAexB,UAAU,uBAAuB;IAC/B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,sBAAsB,CAAC;CAC1C;AAED,UAAU,oBAAoB;IAC5B,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,iBAAiB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACzC,eAAe,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,GAAG,gBAAgB,CAAC,CAAC;IAC9E,gBAAgB,EAAE,CAChB,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,GAAG,EAAE,aAAa,KACf,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC5B,eAAe,EAAE,CAAC,CAAC,SAAS,MAAM,EAChC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,EAC1B,GAAG,EAAE,aAAa,KACf,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACvB,WAAW,EAAE,CACX,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,uBAAuB,EAChC,UAAU,EAAE,MAAM,KACf,OAAO,CAAC,uBAAuB,GAAG,IAAI,CAAC,CAAC;IAC7C,qBAAqB,EAAE,CACrB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,KACT,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAClC,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;IACxD,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC1E;AAqGD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,uBAAuB,GAAG,MAAM,CAc7E;AA6JD,wBAAgB,qBAAqB,CACnC,SAAS,GAAE,OAAO,CAAC,oBAAoB,CAAM,GAC5C,OAAO,CA6CT"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/docs/init/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,KAAK,mBAAmB,EAIzB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAGL,KAAK,aAAa,EAClB,KAAK,YAAY,EAElB,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EACL,KAAK,SAAS,EAGf,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAG5C,OAAO,EAIL,KAAK,uBAAuB,EAK7B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAEL,KAAK,sBAAsB,EAC5B,MAAM,gBAAgB,CAAC;AAexB,UAAU,uBAAuB;IAC/B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,sBAAsB,CAAC;CAC1C;AAED,UAAU,oBAAoB;IAC5B,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,iBAAiB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACzC,eAAe,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,GAAG,gBAAgB,CAAC,CAAC;IAC9E,gBAAgB,EAAE,CAChB,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,GAAG,EAAE,aAAa,KACf,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC5B,eAAe,EAAE,CAAC,CAAC,SAAS,MAAM,EAChC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,EAC1B,GAAG,EAAE,aAAa,KACf,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACvB,WAAW,EAAE,CACX,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,uBAAuB,EAChC,UAAU,EAAE,MAAM,KACf,OAAO,CAAC,uBAAuB,GAAG,IAAI,CAAC,CAAC;IAC7C,qBAAqB,EAAE,CACrB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,KACT,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAClC,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;IACxD,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC1E;AAqGD;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,uBAAuB,GAAG,MAAM,CAuB7E;AA6JD,wBAAgB,qBAAqB,CACnC,SAAS,GAAE,OAAO,CAAC,oBAAoB,CAAM,GAC5C,OAAO,CA6CT"}
@@ -1,3 +1,4 @@
1
+ import { join } from 'node:path';
1
2
  import { buildCommandContext, } from '../../../app/command-context.js';
2
3
  import { formatAgentsMdGuidanceResult, formatAgentsMdMutationFailure, upsertAgentsMdSection, } from '../../shared/agents-md.js';
3
4
  import { confirmAction, inputWithDefault, selectWithAbort, } from '../../shared/shared.prompts.js';
@@ -90,14 +91,31 @@ const FRAMEWORK_LABELS = {
90
91
  fumadocs: 'Fumadocs (Next.js + MDX)',
91
92
  mkdocs: 'MkDocs (Python)',
92
93
  };
94
+ /**
95
+ * The AGENTS.md `## Documentation` section for a freshly scaffolded app.
96
+ *
97
+ * Each bullet names the file that owns one role, matching what
98
+ * `buildDocumentationConfig` seeds into `documentation.*`. A Fumadocs app has
99
+ * two index files -- the authored source page under `docs/` and the app-root
100
+ * manifest `oat docs generate-index` writes -- and `documentation.index` names
101
+ * the second, so a single "Index file" bullet pointing at the first documented
102
+ * a file the config does not name. MkDocs has no generated manifest: its
103
+ * `documentation.index` is the nav YAML the Config bullet already names.
104
+ */
93
105
  export function buildDocsSectionBody(options) {
94
106
  const lines = [
95
107
  '## Documentation',
96
108
  '',
97
109
  `- **Docs root:** \`${options.targetDir}\``,
98
110
  `- **Framework:** ${FRAMEWORK_LABELS[options.framework]}`,
99
- `- **Index file:** \`${options.targetDir}/docs/index.md\``,
111
+ `- **Docs source index:** \`${options.targetDir}/docs/index.md\``,
100
112
  ];
113
+ if (options.framework === 'fumadocs') {
114
+ // Derived exactly like the `documentation.index` seed in `./scaffold`, so
115
+ // the printed path and the recorded path cannot drift apart.
116
+ lines.push(`- **Generated index:** \`${join(options.targetDir, 'index.md')}\` — ` +
117
+ 'regenerated by `oat docs generate-index`; do not hand-edit.');
118
+ }
101
119
  if (options.framework === 'mkdocs') {
102
120
  lines.push(`- **Config:** \`${options.targetDir}/mkdocs.yml\``);
103
121
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/gate/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/gate/index.ts"],"names":[],"mappings":"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"}
@@ -9,6 +9,7 @@ import { getFrontmatterBlock, parseFrontmatterScalarFields, parseGeneratedTime,
9
9
  import { readGlobalOptions } from '../shared/shared.utils.js';
10
10
  import { parseJsonConfig } from '../../config/json.js';
11
11
  import { BUILTIN_EXEC_TARGETS, MAX_GATE_TIMEOUT_MS, MIN_GATE_TIMEOUT_MS, isValidGateTimeoutMs, readOatConfig, readOatLocalConfig, readUserConfig, writeOatConfig, writeOatLocalConfig, writeUserConfig, } from '../../config/oat-config.js';
12
+ import { getOwnKey } from '../../config/own-keys.js';
12
13
  import { resolveEffectiveConfig, resolveExecTargetViews, resolveExecTargets, resolveGate, resolveGateWithSource, } from '../../config/resolve.js';
13
14
  import { dirExists, fileExists } from '../../fs/io.js';
14
15
  import { normalizeToPosixPath, resolveProjectRoot, validateRealPathWithinScope, } from '../../fs/paths.js';
@@ -634,7 +635,11 @@ function unsetSkillGate(config, skillName) {
634
635
  }
635
636
  function setExecTarget(config, targetId, target) {
636
637
  return updateWorkflowGates(config, (gates) => {
637
- const existing = gates.execTargets?.[targetId];
638
+ // `targetId` comes from `oat gate target set <id>`. Without the own-key
639
+ // guard, an id of `__proto__` reads `Object.prototype`, which is truthy,
640
+ // so this takes the merge branch and silently omits the `priority: 0`
641
+ // default the create branch applies.
642
+ const existing = getOwnKey(gates.execTargets ?? {}, targetId);
638
643
  const value = target === null
639
644
  ? target
640
645
  : existing === null || existing === undefined
@@ -1034,7 +1039,10 @@ async function selectAvailableExecTarget(registry, currentRuntime, avoid, produc
1034
1039
  async function resolveSelectedExecTarget(targets, options, producerIdentity, context, dependencies) {
1035
1040
  const explicitTarget = options.target?.trim();
1036
1041
  if (explicitTarget) {
1037
- const target = targets[explicitTarget];
1042
+ // `--target <id>` is a free-form user string. Without the own-key read an
1043
+ // id of `__proto__` or `constructor` returns a truthy inherited member and
1044
+ // slips past the unknown-target rejection below.
1045
+ const target = getOwnKey(targets, explicitTarget);
1038
1046
  if (!target) {
1039
1047
  throw new Error(`Unknown exec target "${explicitTarget}".`);
1040
1048
  }
@@ -1 +1 @@
1
- {"version":3,"file":"instructions.utils.d.ts","sourceRoot":"","sources":["../../../src/commands/instructions/instructions.utils.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EACV,uBAAuB,EACvB,uBAAuB,EACvB,gBAAgB,EAChB,uBAAuB,EACvB,gBAAgB,EAChB,4BAA4B,EAC5B,uBAAuB,EACvB,4BAA4B,EAE5B,mBAAmB,EACpB,MAAM,sBAAsB,CAAC;AAE9B,eAAO,MAAM,uBAAuB,iBAAiB,CAAC;AACtD,eAAO,MAAM,iCAAiC,EAAE,uBACrC,CAAC;AAcZ,UAAU,4BAA4B;IACpC,IAAI,EAAE,gBAAgB,CAAC;IACvB,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,OAAO,EAAE,uBAAuB,EAAE,CAAC;IACnC,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,sBAAsB,CAAC,EAAE,MAAM,EAAE,CAAC;IAClC,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC9B;AAiCD,wBAAgB,8BAA8B,CAC5C,QAAQ,CAAC,EAAE,uBAAuB,GACjC,uBAAuB,CAEzB;AA2ED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,sBAAsB,CACpC,aAAa,GAAE,SAAS,MAAM,EAAO,GACpC,MAAM,EAAE,CAyBV;AAsDD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAsB,iCAAiC,CACrD,QAAQ,EAAE,MAAM,EAChB,SAAS,GAAE,OAAO,CAAC,4BAA4B,CAAM,GACpD,OAAO,CAAC,4BAA4B,CAAC,CAuEvC;AAgID,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,uBAA4B,EACrC,SAAS,GAAE,OAAO,CAAC,4BAA4B,CAAM,GACpD,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAkO7B;AAED,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,gBAAgB,EAAE,EAC3B,OAAO,EAAE,uBAAuB,EAAE,GACjC,mBAAmB,CAoBrB;AAgBD,wBAAgB,wBAAwB,CAAC,EACvC,IAAI,EACJ,OAAO,EACP,OAAO,EACP,aAAa,EACb,sBAAsB,EACtB,iBAAiB,GAClB,EAAE,4BAA4B,GAAG,uBAAuB,CAgCxD;AAED,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,uBAAuB,EAChC,QAAQ,CAAC,EAAE,MAAM,GAChB,MAAM,CAmCR"}
1
+ {"version":3,"file":"instructions.utils.d.ts","sourceRoot":"","sources":["../../../src/commands/instructions/instructions.utils.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EACV,uBAAuB,EACvB,uBAAuB,EACvB,gBAAgB,EAChB,uBAAuB,EACvB,gBAAgB,EAChB,4BAA4B,EAC5B,uBAAuB,EACvB,4BAA4B,EAE5B,mBAAmB,EACpB,MAAM,sBAAsB,CAAC;AAE9B,eAAO,MAAM,uBAAuB,iBAAiB,CAAC;AACtD,eAAO,MAAM,iCAAiC,EAAE,uBACrC,CAAC;AAcZ,UAAU,4BAA4B;IACpC,IAAI,EAAE,gBAAgB,CAAC;IACvB,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,OAAO,EAAE,uBAAuB,EAAE,CAAC;IACnC,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,sBAAsB,CAAC,EAAE,MAAM,EAAE,CAAC;IAClC,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC9B;AAiCD,wBAAgB,8BAA8B,CAC5C,QAAQ,CAAC,EAAE,uBAAuB,GACjC,uBAAuB,CAEzB;AA2ED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,sBAAsB,CACpC,aAAa,GAAE,SAAS,MAAM,EAAO,GACpC,MAAM,EAAE,CAyBV;AA0FD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAsB,iCAAiC,CACrD,QAAQ,EAAE,MAAM,EAChB,SAAS,GAAE,OAAO,CAAC,4BAA4B,CAAM,GACpD,OAAO,CAAC,4BAA4B,CAAC,CAgGvC;AAgID,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,uBAA4B,EACrC,SAAS,GAAE,OAAO,CAAC,4BAA4B,CAAM,GACpD,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAkO7B;AAED,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,gBAAgB,EAAE,EAC3B,OAAO,EAAE,uBAAuB,EAAE,GACjC,mBAAmB,CAoBrB;AAgBD,wBAAgB,wBAAwB,CAAC,EACvC,IAAI,EACJ,OAAO,EACP,OAAO,EACP,aAAa,EACb,sBAAsB,EACtB,iBAAiB,GAClB,EAAE,4BAA4B,GAAG,uBAAuB,CAgCxD;AAED,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,uBAAuB,EAChC,QAAQ,CAAC,EAAE,MAAM,GAChB,MAAM,CAmCR"}
@@ -142,7 +142,7 @@ export function normalizeExcludedPaths(excludedPaths = []) {
142
142
  const UNEXCLUDABLE_PATHS = new Set([...ROOT_EXCLUDED_DIRECTORY_CARVE_INS].map(([directory, carveIn]) => `${directory}/${carveIn}`));
143
143
  /**
144
144
  * Whether `relativePath` names a real directory whose on-disk spelling matches
145
- * exactly.
145
+ * exactly, and when it does not, where it actually leads.
146
146
  *
147
147
  * The case check is the point. On a case-insensitive filesystem (APFS, NTFS) a
148
148
  * plain existence test accepts `Apps/Docsapp/docs` for a directory really named
@@ -150,24 +150,44 @@ const UNEXCLUDABLE_PATHS = new Set([...ROOT_EXCLUDED_DIRECTORY_CARVE_INS].map(([
150
150
  * which always yields the true on-disk case. The exclusion would then be
151
151
  * reported as applied while matching nothing — issue #238 recurring silently on
152
152
  * the default developer platform. Resolving through `realpath` and comparing
153
- * the result to the requested spelling catches that, and returns false for a
154
- * path that does not exist at all.
153
+ * the result to the requested spelling catches that, and reports a path that
154
+ * does not exist at all as `absent`.
155
155
  *
156
156
  * `repoRoot` is realpath'd too, so a symlinked checkout (`/tmp` on macOS) does
157
157
  * not make every entry look like a mismatch.
158
+ *
159
+ * `caseOnly` is derived from the resolved path rather than from the platform: a
160
+ * case-insensitive host is not the only way to land on a differing spelling,
161
+ * and a platform check would attach the case-sensitivity hint to symlinks,
162
+ * where it is false.
158
163
  */
159
- async function isCaseExactDirectory(dependencies, repoRoot, relativePath) {
164
+ async function probeExclusionDirectory(dependencies, repoRoot, relativePath) {
160
165
  try {
161
166
  const realRoot = await dependencies.realpath(repoRoot);
162
167
  const candidate = join(realRoot, relativePath);
163
168
  if (!(await directoryExists(dependencies, candidate))) {
164
- return false;
169
+ return { kind: 'absent' };
165
170
  }
166
171
  const realCandidate = await dependencies.realpath(candidate);
167
- return toPosixPath(relative(realRoot, realCandidate)) === relativePath;
172
+ const resolved = toPosixPath(relative(realRoot, realCandidate));
173
+ if (resolved === relativePath) {
174
+ return { kind: 'exact' };
175
+ }
176
+ // A target outside the repository reads as a plain absolute path; a `../`
177
+ // chain relative to a root the operator never typed would be worse than no
178
+ // target at all. An empty `resolved` means the entry landed on the
179
+ // repository root itself, which is equally unhelpful as a relative path.
180
+ const resolvedInsideRepository = resolved.length > 0 && resolved !== '..' && !resolved.startsWith('../');
181
+ return {
182
+ kind: 'resolved-elsewhere',
183
+ resolvedPath: resolvedInsideRepository
184
+ ? resolved
185
+ : toPosixPath(realCandidate),
186
+ caseOnly: resolved.toLowerCase() === relativePath.toLowerCase(),
187
+ };
168
188
  }
169
189
  catch {
170
- return false;
190
+ return { kind: 'absent' };
171
191
  }
172
192
  }
173
193
  /**
@@ -244,11 +264,24 @@ export async function resolveInstructionPointerExcludes(repoRoot, overrides = {}
244
264
  warnings.push(`${source} entry ${JSON.stringify(normalizedPath)} has no effect: ${normalizedPath} is always scanned.`);
245
265
  continue;
246
266
  }
247
- if (!(await isCaseExactDirectory(dependencies, repoRoot, normalizedPath))) {
267
+ const probe = await probeExclusionDirectory(dependencies, repoRoot, normalizedPath);
268
+ if (probe.kind === 'exact') {
269
+ effective.push(normalizedPath);
270
+ continue;
271
+ }
272
+ if (probe.kind === 'absent') {
248
273
  warnings.push(`${source} entry ${JSON.stringify(normalizedPath)} matches no directory in this repository (matching is case-sensitive), so it excludes nothing.`);
249
274
  continue;
250
275
  }
251
- effective.push(normalizedPath);
276
+ // Stated, not left implied by elimination, and without a catch-all
277
+ // `default` that would silently absorb a future variant: this annotation
278
+ // stops compiling the moment `ExclusionDirectoryProbe` grows a variant with
279
+ // no branch above — including one that happens to carry the same fields and
280
+ // would otherwise inherit a message written for a different situation.
281
+ const resolvedElsewhere = probe;
282
+ warnings.push(resolvedElsewhere.caseOnly
283
+ ? `${source} entry ${JSON.stringify(normalizedPath)} matches no directory in this repository (matching is case-sensitive; the directory on disk is ${JSON.stringify(resolvedElsewhere.resolvedPath)}), so it excludes nothing.`
284
+ : `${source} entry ${JSON.stringify(normalizedPath)} resolves to ${JSON.stringify(resolvedElsewhere.resolvedPath)}, not to itself, so the scan never matches it and it excludes nothing. Point the entry at the resolved directory, or remove the symlink.`);
252
285
  }
253
286
  return { configured, effective, warnings };
254
287
  }
@@ -1 +1 @@
1
- {"version":3,"file":"validate-skill-version-bumps.d.ts","sourceRoot":"","sources":["../../../src/commands/internal/validate-skill-version-bumps.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAEL,KAAK,uCAAuC,EAC5C,KAAK,sCAAsC,EAC5C,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,UAAU,qCAAqC;IAC7C,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,gCAAgC,EAAE,CAChC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,uCAAuC,KAC7C,OAAO,CAAC,sCAAsC,CAAC,CAAC;CACtD;AA8ED,wBAAgB,sCAAsC,CACpD,SAAS,GAAE,OAAO,CAAC,qCAAqC,CAAM,GAC7D,OAAO,CAyBT"}
1
+ {"version":3,"file":"validate-skill-version-bumps.d.ts","sourceRoot":"","sources":["../../../src/commands/internal/validate-skill-version-bumps.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAEL,KAAK,uCAAuC,EAC5C,KAAK,sCAAsC,EAC5C,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,UAAU,qCAAqC;IAC7C,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,gCAAgC,EAAE,CAChC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,uCAAuC,KAC7C,OAAO,CAAC,sCAAsC,CAAC,CAAC;CACtD;AAgFD,wBAAgB,sCAAsC,CACpD,SAAS,GAAE,OAAO,CAAC,qCAAqC,CAAM,GAC7D,OAAO,CAyBT"}
@@ -16,7 +16,7 @@ function reportFindings(context, baseRef, result) {
16
16
  });
17
17
  return;
18
18
  }
19
- context.logger.error('Canonical skill version validation failed:\n');
19
+ context.logger.error('Canonical skill and agent role version validation failed:\n');
20
20
  for (const finding of result.findings) {
21
21
  context.logger.error(`- ${finding.file}: ${finding.message}`);
22
22
  }
@@ -40,10 +40,10 @@ async function runValidateSkillVersionBumps(context, options, dependencies) {
40
40
  }
41
41
  else {
42
42
  if (result.validatedSkillCount === 0) {
43
- context.logger.info(`OK: 0 canonical skills changed relative to ${options.baseRef} - nothing to validate`);
43
+ context.logger.info(`OK: 0 canonical skills or agent roles changed relative to ${options.baseRef} - nothing to validate`);
44
44
  }
45
45
  else {
46
- context.logger.info(`OK: validated ${result.validatedSkillCount} changed canonical skill version bump checks against ${options.baseRef}`);
46
+ context.logger.info(`OK: validated ${result.validatedSkillCount} changed canonical skill and agent role version bump checks against ${options.baseRef}`);
47
47
  }
48
48
  }
49
49
  process.exitCode = 0;
@@ -65,8 +65,8 @@ export function createValidateSkillVersionBumpsCommand(overrides = {}) {
65
65
  ...overrides,
66
66
  };
67
67
  return new Command('validate-skill-version-bumps')
68
- .description('Validate that changed canonical skills bump version relative to a git base ref')
69
- .requiredOption('--base-ref <ref>', 'Git ref used as the comparison base for changed canonical skills')
68
+ .description('Validate that changed canonical skills and agent roles bump version relative to a git base ref')
69
+ .requiredOption('--base-ref <ref>', 'Git ref used as the comparison base for changed canonical skills and agent roles')
70
70
  .action(async (options, command) => {
71
71
  const context = dependencies.buildCommandContext(readGlobalOptions(command));
72
72
  await runValidateSkillVersionBumps(context, options, dependencies);
@@ -1,8 +1,10 @@
1
1
  import type { DoctorCheck } from '../../ui/output.js';
2
2
  import { type PjmAdoption } from './adoption.js';
3
+ import { type RemoteDoctorInput } from './remote/doctor.js';
3
4
  export interface PjmDoctorOptions {
4
5
  projectRoot?: string;
5
6
  adoption?: PjmAdoption;
7
+ remote?: RemoteDoctorInput;
6
8
  }
7
9
  export declare function runPjmDoctorChecks(repoRoot: string, options?: PjmDoctorOptions): Promise<DoctorCheck[]>;
8
10
  //# sourceMappingURL=doctor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../../src/commands/pjm/doctor.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,OAAO,EAAsB,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AA4MlE,MAAM,WAAW,gBAAgB;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,WAAW,CAAC;CACxB;AAED,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,WAAW,EAAE,CAAC,CA2UxB"}
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../../src/commands/pjm/doctor.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,OAAO,EAAsB,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAElE,OAAO,EAAyB,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AA8MhF,MAAM,WAAW,gBAAgB;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,WAAW,CAAC;IACvB,MAAM,CAAC,EAAE,iBAAiB,CAAC;CAC5B;AAED,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,WAAW,EAAE,CAAC,CAmVxB"}
@@ -1,9 +1,15 @@
1
+ import { execFile as execFileCallback } from 'node:child_process';
1
2
  import { access, readdir, readFile } from 'node:fs/promises';
2
- import { basename, dirname, join } from 'node:path';
3
+ import { basename, dirname, isAbsolute, join, resolve } from 'node:path';
4
+ import { promisify } from 'node:util';
3
5
  import { BACKLOG_ITEM_STATUSES, extractBacklogStatus, isTerminalBacklogStatus, isValidBacklogStatus, } from '../backlog/shared/item-status.js';
4
6
  import { getFrontmatterBlock } from '../shared/frontmatter.js';
7
+ import { parseJsonConfig } from '../../config/json.js';
5
8
  import { resolvePjmAdoption } from './adoption.js';
6
9
  import { CANONICAL_REPO_REFERENCE_PATHS } from './init.js';
10
+ import { runRemoteDoctorChecks } from './remote/doctor.js';
11
+ import { resolveRemoteStorageLocations } from './remote/storage-locator.js';
12
+ const execFileAsync = promisify(execFileCallback);
7
13
  const ALLOWED_TOP_LEVEL_DIRECTORIES = new Set([
8
14
  'pjm',
9
15
  'reference',
@@ -435,5 +441,69 @@ export async function runPjmDoctorChecks(repoRoot, options = {}) {
435
441
  ? undefined
436
442
  : 'Run `oat backlog archive <id>` to archive each completed item still under items/.',
437
443
  });
444
+ const defaultRemote = await resolveDefaultRemoteDoctorInput(projectRoot, repoRoot);
445
+ checks.push(...(await runRemoteDoctorChecks(options.remote ?? defaultRemote)));
438
446
  return checks;
439
447
  }
448
+ async function resolveDefaultRemoteDoctorInput(projectRoot, pjmRepoRoot) {
449
+ const rawConfig = await readRawRemoteConfig(projectRoot);
450
+ const stateStorage = isRecord(rawConfig) &&
451
+ isRecord(rawConfig.storage) &&
452
+ rawConfig.storage.state === 'shared'
453
+ ? 'shared'
454
+ : 'local';
455
+ try {
456
+ const [{ stdout: commonDirOutput }, { stdout: originOutput }] = await Promise.all([
457
+ execFileAsync('git', ['rev-parse', '--git-common-dir'], {
458
+ cwd: projectRoot,
459
+ }),
460
+ execFileAsync('git', ['config', '--get', 'remote.origin.url'], {
461
+ cwd: projectRoot,
462
+ }).catch(() => ({ stdout: '' })),
463
+ ]);
464
+ const commonDir = commonDirOutput.trim();
465
+ const gitCommonDir = isAbsolute(commonDir)
466
+ ? commonDir
467
+ : resolve(projectRoot, commonDir);
468
+ const repositoryIdentity = originOutput.trim() || `local-repository:${resolve(projectRoot)}`;
469
+ const locations = resolveRemoteStorageLocations({
470
+ repoRoot: projectRoot,
471
+ gitCommonDir,
472
+ repositoryIdentity,
473
+ stateStorage,
474
+ target: { kind: 'backlog', scope: 'shared', path: null },
475
+ });
476
+ return {
477
+ portableBindingsDir: locations.portable.bindingsDir,
478
+ operationalBindingsDir: locations.operational.bindingsDir,
479
+ operationsDir: locations.operational.operationsDir,
480
+ policy: rawConfig,
481
+ };
482
+ }
483
+ catch {
484
+ const fallbackRoot = join(pjmRepoRoot, 'pjm', 'remote');
485
+ return {
486
+ portableBindingsDir: join(fallbackRoot, 'bindings'),
487
+ operationalBindingsDir: join(fallbackRoot, 'state', 'bindings'),
488
+ operationsDir: join(fallbackRoot, 'state', 'operations'),
489
+ policy: rawConfig,
490
+ };
491
+ }
492
+ }
493
+ async function readRawRemoteConfig(projectRoot) {
494
+ const content = await readIfExists(join(projectRoot, '.oat', 'config.json'));
495
+ if (!content)
496
+ return undefined;
497
+ try {
498
+ const config = parseJsonConfig(content, join(projectRoot, '.oat', 'config.json'));
499
+ if (!isRecord(config) || !isRecord(config.pjm))
500
+ return undefined;
501
+ return config.pjm.remote;
502
+ }
503
+ catch {
504
+ return undefined;
505
+ }
506
+ }
507
+ function isRecord(value) {
508
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
509
+ }
@@ -6,6 +6,7 @@ import { resolvePjmAdoption } from './adoption.js';
6
6
  import { runPjmDoctorChecks } from './doctor.js';
7
7
  import { initializeRepoReference } from './init.js';
8
8
  import { migratePjmRepo, readPjmMigrationPrompt } from './migrate.js';
9
+ import { createPjmRemoteCommand } from './remote/index.js';
9
10
  interface PjmCommandDependencies {
10
11
  buildCommandContext: typeof buildCommandContext;
11
12
  resolveProjectRoot: typeof resolveProjectRoot;
@@ -15,6 +16,7 @@ interface PjmCommandDependencies {
15
16
  runPjmDoctorChecks: typeof runPjmDoctorChecks;
16
17
  migratePjmRepo: typeof migratePjmRepo;
17
18
  readPjmMigrationPrompt: typeof readPjmMigrationPrompt;
19
+ createPjmRemoteCommand: typeof createPjmRemoteCommand;
18
20
  }
19
21
  export declare function createPjmCommand(overrides?: Partial<PjmCommandDependencies>): Command;
20
22
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/pjm/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAuB,MAAM,sBAAsB,CAAC;AAGhF,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAE/C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,EAAE,uBAAuB,EAA0B,MAAM,QAAQ,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AAiBnE,UAAU,sBAAsB;IAC9B,mBAAmB,EAAE,OAAO,mBAAmB,CAAC;IAChD,kBAAkB,EAAE,OAAO,kBAAkB,CAAC;IAC9C,iBAAiB,EAAE,OAAO,iBAAiB,CAAC;IAC5C,kBAAkB,EAAE,OAAO,kBAAkB,CAAC;IAC9C,uBAAuB,EAAE,OAAO,uBAAuB,CAAC;IACxD,kBAAkB,EAAE,OAAO,kBAAkB,CAAC;IAC9C,cAAc,EAAE,OAAO,cAAc,CAAC;IACtC,sBAAsB,EAAE,OAAO,sBAAsB,CAAC;CACvD;AA6FD,wBAAgB,gBAAgB,CAC9B,SAAS,GAAE,OAAO,CAAC,sBAAsB,CAAM,GAC9C,OAAO,CAyLT"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/pjm/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAuB,MAAM,sBAAsB,CAAC;AAGhF,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAE/C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,EAAE,uBAAuB,EAA0B,MAAM,QAAQ,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAiBxD,UAAU,sBAAsB;IAC9B,mBAAmB,EAAE,OAAO,mBAAmB,CAAC;IAChD,kBAAkB,EAAE,OAAO,kBAAkB,CAAC;IAC9C,iBAAiB,EAAE,OAAO,iBAAiB,CAAC;IAC5C,kBAAkB,EAAE,OAAO,kBAAkB,CAAC;IAC9C,uBAAuB,EAAE,OAAO,uBAAuB,CAAC;IACxD,kBAAkB,EAAE,OAAO,kBAAkB,CAAC;IAC9C,cAAc,EAAE,OAAO,cAAc,CAAC;IACtC,sBAAsB,EAAE,OAAO,sBAAsB,CAAC;IACtD,sBAAsB,EAAE,OAAO,sBAAsB,CAAC;CACvD;AA8FD,wBAAgB,gBAAgB,CAC9B,SAAS,GAAE,OAAO,CAAC,sBAAsB,CAAM,GAC9C,OAAO,CA0LT"}
@@ -10,6 +10,7 @@ import { resolvePjmAdoption } from './adoption.js';
10
10
  import { runPjmDoctorChecks } from './doctor.js';
11
11
  import { initializeRepoReference, INSTRUCTIONS_SYNC_HINT } from './init.js';
12
12
  import { migratePjmRepo, readPjmMigrationPrompt } from './migrate.js';
13
+ import { createPjmRemoteCommand } from './remote/index.js';
13
14
  const DEFAULT_DEPENDENCIES = {
14
15
  buildCommandContext,
15
16
  resolveProjectRoot,
@@ -19,6 +20,7 @@ const DEFAULT_DEPENDENCIES = {
19
20
  runPjmDoctorChecks,
20
21
  migratePjmRepo,
21
22
  readPjmMigrationPrompt,
23
+ createPjmRemoteCommand,
22
24
  };
23
25
  async function resolveRepoRoot(context, projectRoot, configuredRoot) {
24
26
  if (configuredRoot) {
@@ -86,6 +88,7 @@ export function createPjmCommand(overrides = {}) {
86
88
  ...overrides,
87
89
  };
88
90
  const cmd = new Command('pjm').description('Manage project-management repo reference docs');
91
+ cmd.addCommand(dependencies.createPjmRemoteCommand());
89
92
  cmd
90
93
  .command('init')
91
94
  .description('Scaffold the canonical PJM repo reference surface')
@@ -0,0 +1,60 @@
1
+ import { type ExternalActionEnvelope } from '../external-action.js';
2
+ import { type OutboundProjection } from '../outbound-projection-safety.js';
3
+ export type CrashPoint = 'after-planned' | 'after-attempt-started' | 'after-observation' | 'after-metadata' | 'after-state' | 'after-snapshot' | 'after-baseline' | 'after-association' | 'after-terminal' | null;
4
+ export interface HarnessOperation {
5
+ operationId: string;
6
+ bindingId: string;
7
+ state: 'planned' | 'attempt-started' | 'verification-pending' | 'materializing' | 'verified' | 'uncertain' | 'blocked';
8
+ previewDigest: string;
9
+ approvalDigest: string;
10
+ capabilityEvidenceDigest: string;
11
+ action: ExternalActionEnvelope | null;
12
+ observationDigest: string | null;
13
+ materializationSteps: string[];
14
+ }
15
+ export declare class FakeLifecycleStore {
16
+ readonly operations: Map<string, HarnessOperation>;
17
+ }
18
+ export declare class GenericHostExecutor {
19
+ readonly result: {
20
+ classification: 'committed' | 'unknown';
21
+ observationDigest: string;
22
+ };
23
+ calls: number;
24
+ constructor(result?: {
25
+ classification: 'committed' | 'unknown';
26
+ observationDigest: string;
27
+ });
28
+ execute(_action: ExternalActionEnvelope): Promise<{
29
+ classification: 'committed' | 'unknown';
30
+ observationDigest: string;
31
+ }>;
32
+ }
33
+ export interface LifecycleHarnessOptions {
34
+ store?: FakeLifecycleStore;
35
+ executor?: GenericHostExecutor;
36
+ now?: () => string;
37
+ id?: () => string;
38
+ readback?: () => Promise<OutboundProjection>;
39
+ }
40
+ export declare class LifecycleHarness {
41
+ readonly store: FakeLifecycleStore;
42
+ readonly executor: GenericHostExecutor;
43
+ readonly now: () => string;
44
+ readonly id: () => string;
45
+ readonly readback: () => Promise<OutboundProjection>;
46
+ constructor(options?: LifecycleHarnessOptions);
47
+ publish(input: {
48
+ operationId?: string;
49
+ bindingId: string;
50
+ provider: 'github' | 'linear' | 'jira';
51
+ context: Record<string, string>;
52
+ projection: OutboundProjection;
53
+ previewDigest: string;
54
+ approvalDigest: string;
55
+ capabilityEvidenceDigest: string;
56
+ crashAt?: CrashPoint;
57
+ }): Promise<HarnessOperation>;
58
+ private crash;
59
+ }
60
+ //# sourceMappingURL=lifecycle-harness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lifecycle-harness.d.ts","sourceRoot":"","sources":["../../../../../src/commands/pjm/remote/__integration__/lifecycle-harness.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,sBAAsB,EAC5B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAEL,KAAK,kBAAkB,EACxB,MAAM,+BAA+B,CAAC;AAEvC,MAAM,MAAM,UAAU,GAClB,eAAe,GACf,uBAAuB,GACvB,mBAAmB,GACnB,gBAAgB,GAChB,aAAa,GACb,gBAAgB,GAChB,gBAAgB,GAChB,mBAAmB,GACnB,gBAAgB,GAChB,IAAI,CAAC;AAET,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EACD,SAAS,GACT,iBAAiB,GACjB,sBAAsB,GACtB,eAAe,GACf,UAAU,GACV,WAAW,GACX,SAAS,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,wBAAwB,EAAE,MAAM,CAAC;IACjC,MAAM,EAAE,sBAAsB,GAAG,IAAI,CAAC;IACtC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,oBAAoB,EAAE,MAAM,EAAE,CAAC;CAChC;AAED,qBAAa,kBAAkB;IAC7B,QAAQ,CAAC,UAAU,gCAAuC;CAC3D;AAED,qBAAa,mBAAmB;IAG5B,QAAQ,CAAC,MAAM,EAAE;QACf,cAAc,EAAE,WAAW,GAAG,SAAS,CAAC;QACxC,iBAAiB,EAAE,MAAM,CAAC;KAC3B;IALH,KAAK,SAAK;IACV,YACW,MAAM,GAAE;QACf,cAAc,EAAE,WAAW,GAAG,SAAS,CAAC;QACxC,iBAAiB,EAAE,MAAM,CAAC;KAI3B,EACC;IAEE,OAAO,CAAC,OAAO,EAAE,sBAAsB;wBARzB,WAAW,GAAG,SAAS;2BACpB,MAAM;OAU5B;CACF;AAED,MAAM,WAAW,uBAAuB;IACtC,KAAK,CAAC,EAAE,kBAAkB,CAAC;IAC3B,QAAQ,CAAC,EAAE,mBAAmB,CAAC;IAC/B,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,EAAE,CAAC,EAAE,MAAM,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,kBAAkB,CAAC,CAAC;CAC9C;AAED,qBAAa,gBAAgB;IAC3B,QAAQ,CAAC,KAAK,EAAE,kBAAkB,CAAC;IACnC,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,CAAC;IACvC,QAAQ,CAAC,GAAG,EAAE,MAAM,MAAM,CAAC;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAErD,YAAY,OAAO,GAAE,uBAA4B,EAOhD;IAEK,OAAO,CAAC,KAAK,EAAE;QACnB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;QACvC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAChC,UAAU,EAAE,kBAAkB,CAAC;QAC/B,aAAa,EAAE,MAAM,CAAC;QACtB,cAAc,EAAE,MAAM,CAAC;QACvB,wBAAwB,EAAE,MAAM,CAAC;QACjC,OAAO,CAAC,EAAE,UAAU,CAAC;KACtB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAuH5B;IAED,OAAO,CAAC,KAAK;CAGd"}