@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
@@ -0,0 +1,367 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { z } from 'zod';
3
+ import { containsSensitiveContentSignal, containsSensitiveContentSignalInValue, } from './credential-safety.js';
4
+ import { requireCurrentOutboundSafety, } from './outbound-projection-safety.js';
5
+ import { RemoteAccountContextSchema, WHOLE_FIELD_SUPPRESSION_MARKER, } from './schema.js';
6
+ const MAX_ACTION_BYTES = 65_536;
7
+ const MAX_OBSERVATION_BYTES = 65_536;
8
+ const MAX_VALUE_DEPTH = 6;
9
+ const SemanticFieldNameSchema = z
10
+ .string()
11
+ .min(1)
12
+ .max(64)
13
+ .regex(/^[A-Za-z][A-Za-z0-9_-]*$/);
14
+ const SuppressedFieldReferenceSchema = z.discriminatedUnion('kind', [
15
+ z
16
+ .object({
17
+ kind: z.literal('core'),
18
+ name: z.enum(['title', 'description', 'priority', 'status']),
19
+ })
20
+ .strict(),
21
+ z
22
+ .object({ kind: z.literal('extension'), key: SemanticFieldNameSchema })
23
+ .strict(),
24
+ ]);
25
+ const DurableActionIdSchema = z
26
+ .string()
27
+ .min(1)
28
+ .max(128)
29
+ .regex(/^[A-Za-z0-9][A-Za-z0-9._-]*$/);
30
+ const ProviderSchema = z.enum(['github', 'linear', 'jira']);
31
+ const SemanticOperationSchema = z.enum([
32
+ 'read',
33
+ 'read-discussion',
34
+ 'search-duplicates',
35
+ 'create',
36
+ 'update',
37
+ 'transition',
38
+ 'annotate',
39
+ ]);
40
+ export const ExternalObservationEnvelopeSchema = z
41
+ .object({
42
+ schemaVersion: z.literal(1),
43
+ operationId: DurableActionIdSchema,
44
+ stepId: DurableActionIdSchema,
45
+ actionDigest: z.string().min(1).max(512),
46
+ observedAt: z.string().datetime({ offset: true }),
47
+ surfaceKind: z.enum(['connector', 'configured-cli']),
48
+ capabilityEvidenceDigest: z.string().min(1).max(512),
49
+ provider: ProviderSchema,
50
+ context: RemoteAccountContextSchema,
51
+ outcome: z
52
+ .object({
53
+ classification: z.enum([
54
+ 'observed',
55
+ 'not-committed',
56
+ 'unknown',
57
+ 'rejected',
58
+ ]),
59
+ identity: z
60
+ .object({
61
+ stableId: z.string().min(1).max(512),
62
+ aliases: z.array(z.string().max(2_048)).max(64),
63
+ })
64
+ .strict()
65
+ .nullable(),
66
+ fields: z.record(z.union([z.string(), z.number(), z.boolean(), z.null()])),
67
+ extensions: z
68
+ .record(z.union([z.string(), z.number(), z.boolean(), z.null()]))
69
+ .optional(),
70
+ revisionDigest: z.string().min(1).max(512).nullable(),
71
+ diagnosticCode: z.string().min(1).max(128).nullable(),
72
+ })
73
+ .strict(),
74
+ })
75
+ .strict();
76
+ const WritablePlanningFieldsSchema = z
77
+ .object({
78
+ title: z.string().max(8_192).optional(),
79
+ description: z.string().max(1_048_576).nullable().optional(),
80
+ priority: z.string().max(255).nullable().optional(),
81
+ })
82
+ .strict();
83
+ const IdentityIntentSchema = z
84
+ .object({
85
+ stableId: z.string().min(1).max(512),
86
+ localTarget: z
87
+ .object({
88
+ kind: z.literal('backlog'),
89
+ scope: z.literal('shared'),
90
+ id: z.string().min(1).max(255),
91
+ path: z.string().min(1).max(4_096),
92
+ })
93
+ .strict()
94
+ .optional(),
95
+ })
96
+ .strict();
97
+ const ActionIntentSchemas = {
98
+ read: IdentityIntentSchema,
99
+ 'read-discussion': z
100
+ .object({
101
+ stableId: z.string().min(1).max(512),
102
+ limit: z.number().int().min(1).max(100),
103
+ cursor: z.string().max(512).optional(),
104
+ })
105
+ .strict(),
106
+ 'search-duplicates': z
107
+ .object({ query: z.string().min(1).max(8_192) })
108
+ .strict(),
109
+ create: z
110
+ .object({
111
+ target: z
112
+ .object({
113
+ kind: z.enum(['backlog', 'project']),
114
+ id: z.string().min(1).max(255),
115
+ scope: z.enum(['shared', 'synced', 'local']),
116
+ })
117
+ .strict(),
118
+ fields: WritablePlanningFieldsSchema,
119
+ provenanceToken: z.string().min(1).max(512),
120
+ })
121
+ .strict(),
122
+ update: z
123
+ .object({
124
+ stableId: z.string().min(1).max(512).nullable().optional(),
125
+ fields: WritablePlanningFieldsSchema,
126
+ })
127
+ .strict(),
128
+ transition: z
129
+ .object({
130
+ stableId: z.string().min(1).max(512),
131
+ transition: z.string().min(1).max(255),
132
+ })
133
+ .strict(),
134
+ annotate: z
135
+ .object({
136
+ stableId: z.string().min(1).max(512),
137
+ body: z.string().max(1_048_576),
138
+ })
139
+ .strict(),
140
+ };
141
+ const ExternalActionBaseSchema = z
142
+ .object({
143
+ schemaVersion: z.literal(1),
144
+ operationId: DurableActionIdSchema,
145
+ stepId: DurableActionIdSchema,
146
+ actionDigest: z.string().min(1).max(512),
147
+ provider: ProviderSchema,
148
+ semanticOperation: SemanticOperationSchema,
149
+ context: RemoteAccountContextSchema,
150
+ intent: z.record(z.unknown()),
151
+ expectedObservation: z
152
+ .object({
153
+ fields: z.array(SemanticFieldNameSchema).max(64),
154
+ extensionFields: z.array(SemanticFieldNameSchema).max(32).optional(),
155
+ requireIdentity: z.boolean(),
156
+ stableId: z.string().min(1).max(512).nullable().optional(),
157
+ capabilityEvidenceDigest: z.string().min(1).max(512).optional(),
158
+ })
159
+ .strict(),
160
+ outboundSafety: z
161
+ .object({
162
+ projectionDigest: z.string().min(1).max(512),
163
+ resultDigest: z.string().min(1).max(512),
164
+ })
165
+ .strict()
166
+ .nullable(),
167
+ })
168
+ .strict();
169
+ export function parseExternalAction(value) {
170
+ if (Buffer.byteLength(JSON.stringify(value), 'utf8') > MAX_ACTION_BYTES) {
171
+ throw new Error('External action exceeds the size limit.');
172
+ }
173
+ const action = ExternalActionBaseSchema.parse(value);
174
+ assertDepth(action.intent, 0);
175
+ ActionIntentSchemas[action.semanticOperation].parse(action.intent);
176
+ const { actionDigest, ...body } = action;
177
+ if (digest(body) !== actionDigest) {
178
+ throw new Error('External action digest is stale or mismatched.');
179
+ }
180
+ return action;
181
+ }
182
+ export function buildExternalAction(input) {
183
+ const mutation = ['create', 'update', 'transition', 'annotate'].includes(input.semanticOperation);
184
+ assertDepth(input.intent, 0);
185
+ const intent = ActionIntentSchemas[input.semanticOperation].parse(input.intent);
186
+ let outboundSafety = null;
187
+ if (mutation) {
188
+ if (!input.projection)
189
+ throw new Error('Mutation action requires an explicit outbound projection.');
190
+ if (canonicalJson(writableProjection(input.semanticOperation, intent)) !==
191
+ canonicalJson(input.projection)) {
192
+ throw new Error('Mutation action writable fields must exactly match its gated projection.');
193
+ }
194
+ requireCurrentOutboundSafety(input.projection, input.outboundSafety);
195
+ if (input.persistedPreview.projectionDigest !==
196
+ input.outboundSafety.projectionDigest ||
197
+ input.persistedPreview.safetyResultDigest !==
198
+ input.outboundSafety.resultDigest) {
199
+ throw new Error('Mutation action safety evidence does not match the persisted preview.');
200
+ }
201
+ outboundSafety = {
202
+ projectionDigest: input.outboundSafety.projectionDigest,
203
+ resultDigest: input.outboundSafety.resultDigest,
204
+ };
205
+ }
206
+ const expectedFields = input.expectedObservation.fields.map((field) => SemanticFieldNameSchema.parse(field));
207
+ const expectedExtensionFields = (input.expectedObservation.extensionFields ?? []).map((field) => SemanticFieldNameSchema.parse(field));
208
+ if (new Set(expectedExtensionFields).size !== expectedExtensionFields.length) {
209
+ throw new Error('External action extension fields must be unique and bounded.');
210
+ }
211
+ if (new Set(expectedFields).size !== expectedFields.length ||
212
+ expectedFields.length > 64) {
213
+ throw new Error('External action expected fields must be unique and bounded.');
214
+ }
215
+ if (mutation &&
216
+ expectedFields.some((field) => !Object.hasOwn(input.projection, field))) {
217
+ throw new Error('Mutation action expected fields must match its projection.');
218
+ }
219
+ const actionWithoutDigest = {
220
+ schemaVersion: 1,
221
+ operationId: input.operationId,
222
+ stepId: input.stepId,
223
+ provider: input.provider,
224
+ semanticOperation: SemanticOperationSchema.parse(input.semanticOperation),
225
+ context: RemoteAccountContextSchema.parse(input.context),
226
+ intent,
227
+ expectedObservation: {
228
+ ...input.expectedObservation,
229
+ fields: expectedFields,
230
+ ...(expectedExtensionFields.length > 0
231
+ ? { extensionFields: expectedExtensionFields }
232
+ : {}),
233
+ stableId: input.expectedObservation.stableId,
234
+ capabilityEvidenceDigest: input.expectedObservation.capabilityEvidenceDigest,
235
+ },
236
+ outboundSafety,
237
+ };
238
+ if (Buffer.byteLength(canonicalJson(actionWithoutDigest), 'utf8') >
239
+ MAX_ACTION_BYTES) {
240
+ throw new Error('External action exceeds the size limit.');
241
+ }
242
+ return { ...actionWithoutDigest, actionDigest: digest(actionWithoutDigest) };
243
+ }
244
+ export function acceptExternalObservation(input) {
245
+ const bytes = Buffer.byteLength(JSON.stringify(input.observation), 'utf8');
246
+ if (bytes > MAX_OBSERVATION_BYTES)
247
+ throw new Error('External observation exceeds the size limit.');
248
+ const observation = ExternalObservationEnvelopeSchema.parse(input.observation);
249
+ if (input.acceptedStepDigests?.has(observation.actionDigest)) {
250
+ throw new Error('External observation duplicates an accepted action.');
251
+ }
252
+ if (observation.operationId !== input.action.operationId ||
253
+ observation.stepId !== input.action.stepId ||
254
+ observation.actionDigest !== input.action.actionDigest) {
255
+ throw new Error('External observation is stale or mismatched.');
256
+ }
257
+ if (observation.provider !== input.action.provider ||
258
+ canonicalJson(observation.context) !== canonicalJson(input.action.context)) {
259
+ throw new Error('External observation provider context is mismatched.');
260
+ }
261
+ if (observation.capabilityEvidenceDigest !==
262
+ input.action.expectedObservation.capabilityEvidenceDigest) {
263
+ throw new Error('External observation capability evidence is mismatched.');
264
+ }
265
+ const expected = new Set(input.action.expectedObservation.fields);
266
+ const actual = Object.keys(observation.outcome.fields);
267
+ if (actual.some((field) => !expected.has(field))) {
268
+ throw new Error('External observation contains an unexpected field.');
269
+ }
270
+ const expectedExtensions = new Set(input.action.expectedObservation.extensionFields ?? []);
271
+ const actualExtensions = Object.keys(observation.outcome.extensions ?? {});
272
+ if (actualExtensions.some((field) => !expectedExtensions.has(field))) {
273
+ throw new Error('External observation contains an unexpected adapter extension.');
274
+ }
275
+ if (observation.outcome.classification === 'observed' &&
276
+ input.action.expectedObservation.requireIdentity &&
277
+ !observation.outcome.identity) {
278
+ throw new Error('External observation is missing required identity.');
279
+ }
280
+ if (input.action.expectedObservation.stableId !== null &&
281
+ observation.outcome.identity?.stableId !==
282
+ input.action.expectedObservation.stableId) {
283
+ throw new Error('External observation stable identity is mismatched.');
284
+ }
285
+ if (observation.outcome.identity &&
286
+ [
287
+ observation.outcome.identity.stableId,
288
+ ...observation.outcome.identity.aliases,
289
+ ].some((value) => containsSensitiveContentSignal(value))) {
290
+ throw new Error('External observation identity evidence is unsafe.');
291
+ }
292
+ if (Object.values(observation.context).some((value) => containsSensitiveContentSignal(value))) {
293
+ throw new Error('External observation context evidence is unsafe.');
294
+ }
295
+ if (observation.outcome.diagnosticCode &&
296
+ containsSensitiveContentSignal(observation.outcome.diagnosticCode)) {
297
+ throw new Error('External observation diagnostic evidence is unsafe.');
298
+ }
299
+ const suppressedFields = [];
300
+ const fields = Object.fromEntries(actual.map((field) => {
301
+ const value = observation.outcome.fields[field] ?? null;
302
+ const suppressed = typeof value === 'string' &&
303
+ containsSensitiveContentSignalInValue(value);
304
+ if (suppressed) {
305
+ if (!isCoreObservationField(field)) {
306
+ throw new Error(`Sensitive observation field '${field}' requires a declared adapter extension.`);
307
+ }
308
+ suppressedFields.push({ kind: 'core', name: field });
309
+ }
310
+ return [field, suppressed ? WHOLE_FIELD_SUPPRESSION_MARKER : value];
311
+ }));
312
+ const extensions = Object.fromEntries(actualExtensions.map((key) => {
313
+ const value = observation.outcome.extensions?.[key] ?? null;
314
+ const suppressed = containsSensitiveContentSignalInValue(value);
315
+ if (suppressed)
316
+ suppressedFields.push({ kind: 'extension', key });
317
+ return [key, suppressed ? WHOLE_FIELD_SUPPRESSION_MARKER : value];
318
+ }));
319
+ return {
320
+ ...observation,
321
+ outcome: {
322
+ ...observation.outcome,
323
+ fields,
324
+ ...(actualExtensions.length > 0 ? { extensions } : {}),
325
+ suppressedFields,
326
+ },
327
+ };
328
+ }
329
+ function isCoreObservationField(field) {
330
+ return ['title', 'description', 'priority', 'status'].includes(field);
331
+ }
332
+ function writableProjection(semanticOperation, intent) {
333
+ switch (semanticOperation) {
334
+ case 'create':
335
+ case 'update':
336
+ return intent.fields;
337
+ case 'transition':
338
+ return { status: intent.transition };
339
+ case 'annotate':
340
+ return { annotation: intent.body };
341
+ default:
342
+ return null;
343
+ }
344
+ }
345
+ function assertDepth(value, depth) {
346
+ if (depth > MAX_VALUE_DEPTH)
347
+ throw new Error('External action exceeds the depth limit.');
348
+ if (!value || typeof value !== 'object')
349
+ return;
350
+ for (const item of Object.values(value))
351
+ assertDepth(item, depth + 1);
352
+ }
353
+ function digest(value) {
354
+ return `sha256:${createHash('sha256').update(canonicalJson(value)).digest('hex')}`;
355
+ }
356
+ function canonicalJson(value) {
357
+ return JSON.stringify(value && typeof value === 'object' && !Array.isArray(value)
358
+ ? Object.fromEntries(Object.entries(value)
359
+ .sort(([left], [right]) => left.localeCompare(right))
360
+ .map(([key, item]) => [
361
+ key,
362
+ item && typeof item === 'object'
363
+ ? JSON.parse(canonicalJson(item))
364
+ : item,
365
+ ]))
366
+ : value);
367
+ }
@@ -0,0 +1,28 @@
1
+ import { type ProviderContext, type RemoteProvider, type SemanticOperation } from './provider.js';
2
+ export type HostSurfaceKind = 'connector' | 'configured-cli';
3
+ export interface HostCapabilityEvidence {
4
+ provider: RemoteProvider;
5
+ context: ProviderContext;
6
+ surfaceKind: HostSurfaceKind;
7
+ availability: 'available' | 'authorization-required' | 'unsupported-or-unresolved' | 'disabled';
8
+ semanticCapabilities: SemanticOperation[];
9
+ evidenceDigest: string;
10
+ observedAt: string;
11
+ }
12
+ export declare function parseHostCapabilityEvidence(value: unknown): HostCapabilityEvidence;
13
+ export type HostExecutionSelection = {
14
+ selected: true;
15
+ evidence: HostCapabilityEvidence;
16
+ fallbackUsed: boolean;
17
+ } | {
18
+ selected: false;
19
+ reason: 'unavailable' | 'authorization-required' | 'context-mismatch' | 'capability-missing' | 'disabled' | 'attempt-started';
20
+ };
21
+ export declare function selectHostExecution(input: {
22
+ provider: RemoteProvider;
23
+ context: ProviderContext;
24
+ operation: SemanticOperation;
25
+ candidates: readonly HostCapabilityEvidence[];
26
+ attemptStarted: boolean;
27
+ }): HostExecutionSelection;
28
+ //# sourceMappingURL=host-execution.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-execution.d.ts","sourceRoot":"","sources":["../../../../src/commands/pjm/remote/host-execution.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACvB,MAAM,YAAY,CAAC;AAGpB,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG,gBAAgB,CAAC;AAE7D,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,cAAc,CAAC;IACzB,OAAO,EAAE,eAAe,CAAC;IACzB,WAAW,EAAE,eAAe,CAAC;IAC7B,YAAY,EACR,WAAW,GACX,wBAAwB,GACxB,2BAA2B,GAC3B,UAAU,CAAC;IACf,oBAAoB,EAAE,iBAAiB,EAAE,CAAC;IAC1C,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;CACpB;AA+BD,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,OAAO,GACb,sBAAsB,CAExB;AAED,MAAM,MAAM,sBAAsB,GAC9B;IAAE,QAAQ,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,sBAAsB,CAAC;IAAC,YAAY,EAAE,OAAO,CAAA;CAAE,GAC3E;IACE,QAAQ,EAAE,KAAK,CAAC;IAChB,MAAM,EACF,aAAa,GACb,wBAAwB,GACxB,kBAAkB,GAClB,oBAAoB,GACpB,UAAU,GACV,iBAAiB,CAAC;CACvB,CAAC;AAEN,wBAAgB,mBAAmB,CAAC,KAAK,EAAE;IACzC,QAAQ,EAAE,cAAc,CAAC;IACzB,OAAO,EAAE,eAAe,CAAC;IACzB,SAAS,EAAE,iBAAiB,CAAC;IAC7B,UAAU,EAAE,SAAS,sBAAsB,EAAE,CAAC;IAC9C,cAAc,EAAE,OAAO,CAAC;CACzB,GAAG,sBAAsB,CA6CzB"}
@@ -0,0 +1,63 @@
1
+ import { z } from 'zod';
2
+ import { contextsEqual, } from './provider.js';
3
+ import { RemoteAccountContextSchema } from './schema.js';
4
+ const HostCapabilityEvidenceSchema = z
5
+ .object({
6
+ provider: z.enum(['github', 'linear', 'jira']),
7
+ context: RemoteAccountContextSchema,
8
+ surfaceKind: z.enum(['connector', 'configured-cli']),
9
+ availability: z.enum([
10
+ 'available',
11
+ 'authorization-required',
12
+ 'unsupported-or-unresolved',
13
+ 'disabled',
14
+ ]),
15
+ semanticCapabilities: z
16
+ .array(z.enum([
17
+ 'read',
18
+ 'read-discussion',
19
+ 'search-duplicates',
20
+ 'create',
21
+ 'update',
22
+ 'transition',
23
+ 'annotate',
24
+ ]))
25
+ .max(32),
26
+ evidenceDigest: z.string().min(1).max(512),
27
+ observedAt: z.string().datetime({ offset: true }),
28
+ })
29
+ .strict();
30
+ export function parseHostCapabilityEvidence(value) {
31
+ return HostCapabilityEvidenceSchema.parse(value);
32
+ }
33
+ export function selectHostExecution(input) {
34
+ const relevant = input.candidates.filter((candidate) => candidate.provider === input.provider);
35
+ if (relevant.some((candidate) => candidate.availability === 'disabled')) {
36
+ return { selected: false, reason: 'disabled' };
37
+ }
38
+ if (input.attemptStarted)
39
+ return { selected: false, reason: 'attempt-started' };
40
+ const contextual = relevant.filter((candidate) => contextsEqual(candidate.context, input.context));
41
+ if (relevant.length > 0 && contextual.length === 0) {
42
+ return { selected: false, reason: 'context-mismatch' };
43
+ }
44
+ const capable = contextual.filter((candidate) => candidate.semanticCapabilities.includes(input.operation));
45
+ if (contextual.length > 0 && capable.length === 0) {
46
+ return { selected: false, reason: 'capability-missing' };
47
+ }
48
+ const available = capable.filter((candidate) => candidate.availability === 'available');
49
+ const connector = available.find((candidate) => candidate.surfaceKind === 'connector');
50
+ const selected = connector ??
51
+ available.find((candidate) => candidate.surfaceKind === 'configured-cli');
52
+ if (selected) {
53
+ return {
54
+ selected: true,
55
+ evidence: selected,
56
+ fallbackUsed: selected.surfaceKind === 'configured-cli',
57
+ };
58
+ }
59
+ if (capable.some((candidate) => candidate.availability === 'authorization-required')) {
60
+ return { selected: false, reason: 'authorization-required' };
61
+ }
62
+ return { selected: false, reason: 'unavailable' };
63
+ }
@@ -0,0 +1,41 @@
1
+ import { Command } from 'commander';
2
+ import { type RemoteCommandEnvelope } from './output.js';
3
+ export type RemoteLifecycleOperation = 'intake' | 'publish' | 'refresh' | 'reconcile' | 'closeout' | 'discussion' | 'resolve' | 'doctor' | 'migrate' | 'storage-transition' | 'operation-continue';
4
+ export interface RemoteCommandRequest {
5
+ operation: RemoteLifecycleOperation;
6
+ projectRoot: string;
7
+ bindingId?: string;
8
+ operationId?: string;
9
+ previewOperationId?: string;
10
+ providerRef?: string;
11
+ backlogId?: string;
12
+ projectPath?: string;
13
+ discussionLimit?: number;
14
+ resolutionKind?: 'relink' | 'detach' | 'recreate';
15
+ migrationMode?: 'check' | 'apply';
16
+ migrationApprovalDigest?: string;
17
+ createTarget?: {
18
+ provider: string;
19
+ localKind: 'backlog' | 'project';
20
+ localId: string;
21
+ publicationFile?: string;
22
+ };
23
+ observationStdin?: boolean;
24
+ capabilityEvidenceStdin?: boolean;
25
+ authorityEvidenceFile?: string;
26
+ storage?: {
27
+ repositoryFingerprint: string;
28
+ configTarget: string;
29
+ currentMode: 'local' | 'shared';
30
+ proposedPaths: string[];
31
+ apply: boolean;
32
+ };
33
+ storageApprovalDigest?: string;
34
+ }
35
+ export interface PjmRemoteCommandDependencies {
36
+ resolveProjectRoot(cwd: string): Promise<string>;
37
+ checkAdoption(projectRoot: string): Promise<'complete' | 'partial' | 'absent'>;
38
+ run(request: RemoteCommandRequest): Promise<RemoteCommandEnvelope>;
39
+ }
40
+ export declare function createPjmRemoteCommand(overrides?: Partial<PjmRemoteCommandDependencies>): Command;
41
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/pjm/remote/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,OAAO,EAAuB,KAAK,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAG3E,MAAM,MAAM,wBAAwB,GAChC,QAAQ,GACR,SAAS,GACT,SAAS,GACT,WAAW,GACX,UAAU,GACV,YAAY,GACZ,SAAS,GACT,QAAQ,GACR,SAAS,GACT,oBAAoB,GACpB,oBAAoB,CAAC;AAEzB,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,wBAAwB,CAAC;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,UAAU,CAAC;IAClD,aAAa,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IAClC,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,YAAY,CAAC,EAAE;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,SAAS,GAAG,SAAS,CAAC;QACjC,OAAO,EAAE,MAAM,CAAC;QAChB,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC;IACF,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,OAAO,CAAC,EAAE;QACR,qBAAqB,EAAE,MAAM,CAAC;QAC9B,YAAY,EAAE,MAAM,CAAC;QACrB,WAAW,EAAE,OAAO,GAAG,QAAQ,CAAC;QAChC,aAAa,EAAE,MAAM,EAAE,CAAC;QACxB,KAAK,EAAE,OAAO,CAAC;KAChB,CAAC;IACF,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,4BAA4B;IAC3C,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACjD,aAAa,CACX,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,UAAU,GAAG,SAAS,GAAG,QAAQ,CAAC,CAAC;IAC9C,GAAG,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAAC;CACpE;AAkBD,wBAAgB,sBAAsB,CACpC,SAAS,GAAE,OAAO,CAAC,4BAA4B,CAAM,GACpD,OAAO,CA+WT"}