@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,380 @@
1
+ import { readFile, readdir } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ import { RemoteBindingMetadataSchema, RemoteBindingStateSchema, RemoteOperationRecordSchema, assertRecordIdMatchesFilename, } from './schema.js';
4
+ const REMOTE_CONTEXT_FIELDS = [
5
+ 'host',
6
+ 'owner',
7
+ 'repositoryId',
8
+ 'workspaceId',
9
+ 'teamId',
10
+ 'cloudId',
11
+ 'siteId',
12
+ 'projectId',
13
+ ];
14
+ export async function runRemoteDoctorChecks(input) {
15
+ const [metadataFiles, stateFiles, operationFiles] = await Promise.all([
16
+ loadRecords(input.portableBindingsDir, RemoteBindingMetadataSchema),
17
+ loadRecords(input.operationalBindingsDir, RemoteBindingStateSchema),
18
+ loadRecords(input.operationsDir, RemoteOperationRecordSchema),
19
+ ]);
20
+ const adopted = metadataFiles.length > 0 ||
21
+ stateFiles.length > 0 ||
22
+ operationFiles.length > 0 ||
23
+ (input.associatedBindingIds?.length ?? 0) > 0 ||
24
+ input.policy !== undefined ||
25
+ (input.retentionBreaches?.length ?? 0) > 0 ||
26
+ (input.hostCapabilityAvailability?.length ?? 0) > 0;
27
+ if (!adopted)
28
+ return [];
29
+ const schemaFindings = collectSchemaFindings(metadataFiles, stateFiles, operationFiles);
30
+ const metadata = metadataFiles.flatMap((file) => file.parsed ? [file.parsed] : []);
31
+ const states = stateFiles.flatMap((file) => file.parsed ? [file.parsed] : []);
32
+ const operations = operationFiles.flatMap((file) => file.parsed ? [file.parsed] : []);
33
+ const identityFindings = collectIdentityFindings(metadata, states, input.associatedBindingIds ?? []);
34
+ const metadataStateFindings = collectMetadataStateFindings(metadata, states);
35
+ const forbiddenContent = metadataFiles
36
+ .filter((file) => containsForbiddenPortableKey(file.raw))
37
+ .map((file) => file.filename);
38
+ const policyFindings = collectRemotePolicyFindings(input.policy);
39
+ const concurrentBindings = collectConcurrentBindings(operations);
40
+ const operationalFindings = collectOperationalFindings(operations, input);
41
+ const retentionFindings = [...(input.retentionBreaches ?? [])].sort();
42
+ const unavailableCapabilities = (input.hostCapabilityAvailability ?? [])
43
+ .filter((entry) => !entry.available)
44
+ .map((entry) => entry.bindingId)
45
+ .sort();
46
+ if (input.evidenceAvailability?.associations === false) {
47
+ identityFindings.push('association-evidence-unavailable');
48
+ }
49
+ if (input.evidenceAvailability?.retention === false) {
50
+ retentionFindings.push('retention-evidence-unavailable');
51
+ }
52
+ if (input.evidenceAvailability?.hostCapabilities === false) {
53
+ unavailableCapabilities.push('host-capability-evidence-unavailable');
54
+ }
55
+ return [
56
+ findingCheck('pjm:remote_schema', 'Remote record schema and filename identity', schemaFindings),
57
+ findingCheck('pjm:remote_binding_ids', 'Remote binding references and stable identities', identityFindings),
58
+ findingCheck('pjm:remote_metadata_state', 'Portable metadata and operational state agreement', metadataStateFindings),
59
+ findingCheck('pjm:remote_storage_content', 'Portable metadata excludes operational or sensitive content', forbiddenContent),
60
+ {
61
+ name: 'pjm:remote_policy',
62
+ description: 'Remote repository policy is valid and fail-closed',
63
+ status: policyFindings.length === 0 ? 'pass' : 'fail',
64
+ message: policyFindings.length === 0
65
+ ? 'Remote policy is valid or not configured.'
66
+ : `Remote policy contains invalid or unknown fields: ${policyFindings.join(', ')}.`,
67
+ fix: policyFindings.length === 0
68
+ ? undefined
69
+ : 'Repair pjm.remote policy in shared .oat/config.json before any remote mutation.',
70
+ },
71
+ findingCheck('pjm:remote_concurrent_intents', 'Concurrent active remote operation intents', concurrentBindings),
72
+ findingCheck('pjm:remote_operations', 'Remote operation freshness, terminal state, and verification evidence', operationalFindings),
73
+ findingCheck('pjm:remote_retention', 'Remote operational-state retention boundary', retentionFindings),
74
+ findingCheck('pjm:remote_host_capability', 'Current host semantic capability availability', unavailableCapabilities),
75
+ ];
76
+ }
77
+ function collectOperationalFindings(operations, input) {
78
+ const findings = [];
79
+ const visibleStates = new Set([
80
+ 'pending',
81
+ 'partial',
82
+ 'uncertain',
83
+ 'attempt-started',
84
+ 'verification-pending',
85
+ ]);
86
+ const now = input.now ? Date.parse(input.now) : Number.NaN;
87
+ const staleAfterMs = input.staleAfterMs ?? Number.POSITIVE_INFINITY;
88
+ for (const operation of operations) {
89
+ if (visibleStates.has(operation.state)) {
90
+ findings.push(`${operation.operationId}:${operation.state}`);
91
+ }
92
+ const age = now - Date.parse(operation.updatedAt);
93
+ if (Number.isFinite(age) && age > staleAfterMs) {
94
+ findings.push(`${operation.operationId}:stale`);
95
+ }
96
+ if (operation.state === 'verified' && operation.verification.length === 0) {
97
+ findings.push(`${operation.operationId}:missing-verification`);
98
+ }
99
+ }
100
+ return [...new Set(findings)].sort();
101
+ }
102
+ async function loadRecords(directory, schema) {
103
+ let filenames;
104
+ try {
105
+ filenames = (await readdir(directory)).filter((name) => name.endsWith('.json'));
106
+ }
107
+ catch (error) {
108
+ if (isFilesystemError(error, 'ENOENT'))
109
+ return [];
110
+ throw error;
111
+ }
112
+ const records = [];
113
+ for (const filename of filenames.sort()) {
114
+ let raw = null;
115
+ try {
116
+ raw = JSON.parse(await readFile(join(directory, filename), 'utf8'));
117
+ }
118
+ catch {
119
+ records.push({ filename, raw: null, parsed: null });
120
+ continue;
121
+ }
122
+ const result = schema.safeParse(raw);
123
+ records.push({
124
+ filename,
125
+ raw,
126
+ parsed: result.success ? result.data : null,
127
+ });
128
+ }
129
+ return records;
130
+ }
131
+ function collectSchemaFindings(metadata, states, operations) {
132
+ const findings = [];
133
+ for (const [files, idFor] of [
134
+ [metadata, (record) => record.bindingId],
135
+ [states, (record) => record.bindingId],
136
+ [operations, (record) => record.operationId],
137
+ ]) {
138
+ for (const file of files) {
139
+ if (!file.parsed) {
140
+ findings.push(file.filename);
141
+ continue;
142
+ }
143
+ try {
144
+ assertRecordIdMatchesFilename(file.filename, idFor(file.parsed));
145
+ }
146
+ catch {
147
+ findings.push(file.filename);
148
+ }
149
+ }
150
+ }
151
+ return findings;
152
+ }
153
+ function collectIdentityFindings(metadata, states, associatedBindingIds) {
154
+ const findings = [];
155
+ const known = new Set(metadata.map((record) => record.bindingId));
156
+ for (const bindingId of associatedBindingIds) {
157
+ if (!known.has(bindingId))
158
+ findings.push(`dangling:${bindingId}`);
159
+ }
160
+ for (const state of states) {
161
+ if (!known.has(state.bindingId))
162
+ findings.push(`dangling-state:${state.bindingId}`);
163
+ }
164
+ const byIdentity = new Map();
165
+ for (const record of metadata) {
166
+ const key = `${record.provider}:${record.remoteIdentity.stableId}`;
167
+ const ids = byIdentity.get(key) ?? [];
168
+ ids.push(record.bindingId);
169
+ byIdentity.set(key, ids);
170
+ }
171
+ for (const ids of byIdentity.values()) {
172
+ if (ids.length > 1)
173
+ findings.push(`duplicate:${ids.join(',')}`);
174
+ }
175
+ return findings;
176
+ }
177
+ function collectMetadataStateFindings(metadata, states) {
178
+ const metadataById = new Map(metadata.map((record) => [record.bindingId, record]));
179
+ const statesById = new Map(states.map((record) => [record.bindingId, record]));
180
+ const findings = [];
181
+ for (const record of metadata) {
182
+ const state = statesById.get(record.bindingId);
183
+ if (!state)
184
+ continue;
185
+ if (state.metadataUpdatedAt !== record.updatedAt) {
186
+ findings.push(`${record.bindingId}:metadata-timestamp`);
187
+ }
188
+ if (state.provider !== record.provider) {
189
+ findings.push(`${record.bindingId}:provider`);
190
+ }
191
+ if (state.snapshot) {
192
+ if (state.snapshot.identity.stableId !== record.remoteIdentity.stableId) {
193
+ findings.push(`${record.bindingId}:identity`);
194
+ }
195
+ if (!remoteContextsMatch(state.snapshot.identity.context, record.remoteIdentity.context)) {
196
+ findings.push(`${record.bindingId}:identity-context`);
197
+ }
198
+ }
199
+ if (state.capability &&
200
+ !remoteContextsMatch(state.capability.context, record.remoteIdentity.context)) {
201
+ findings.push(`${record.bindingId}:capability-context`);
202
+ }
203
+ }
204
+ for (const state of states) {
205
+ if (!metadataById.has(state.bindingId))
206
+ findings.push(state.bindingId);
207
+ }
208
+ return [...new Set(findings)];
209
+ }
210
+ function remoteContextsMatch(left, right) {
211
+ return REMOTE_CONTEXT_FIELDS.every((field) => left[field] === right[field]);
212
+ }
213
+ function containsForbiddenPortableKey(value, path = []) {
214
+ if (Array.isArray(value)) {
215
+ return value.some((entry) => containsForbiddenPortableKey(entry, path));
216
+ }
217
+ if (!isRecord(value))
218
+ return false;
219
+ const forbidden = new Set([
220
+ 'snapshot',
221
+ 'baseline',
222
+ 'attempts',
223
+ 'receipt',
224
+ 'rawPayload',
225
+ 'credential',
226
+ 'authorization',
227
+ ]);
228
+ return Object.entries(value).some(([key, child]) => forbidden.has(key) ||
229
+ (key === 'description' && path.length === 0) ||
230
+ containsForbiddenPortableKey(child, [...path, key]));
231
+ }
232
+ function collectRemotePolicyFindings(value) {
233
+ if (value === undefined)
234
+ return [];
235
+ const findings = [];
236
+ if (!isRecord(value))
237
+ return ['pjm.remote'];
238
+ collectUnknownKeys(value, ['schemaVersion', 'storage', 'policy'], 'pjm.remote', findings);
239
+ if (value.schemaVersion !== 1)
240
+ findings.push('pjm.remote.schemaVersion');
241
+ if ('storage' in value) {
242
+ if (!isRecord(value.storage)) {
243
+ findings.push('pjm.remote.storage');
244
+ }
245
+ else {
246
+ collectUnknownKeys(value.storage, ['state'], 'pjm.remote.storage', findings);
247
+ if (!['local', 'shared'].includes(String(value.storage.state))) {
248
+ findings.push('pjm.remote.storage.state');
249
+ }
250
+ }
251
+ }
252
+ if (!isRecord(value.policy)) {
253
+ findings.push('pjm.remote.policy');
254
+ return [...new Set(findings)];
255
+ }
256
+ collectUnknownKeys(value.policy, ['description', 'authority', 'providers'], 'pjm.remote.policy', findings);
257
+ if (!isDescriptionMode(value.policy.description)) {
258
+ findings.push('pjm.remote.policy.description');
259
+ }
260
+ collectAuthorityFindings(value.policy.authority, 'pjm.remote.policy.authority', findings, true);
261
+ if ('providers' in value.policy) {
262
+ if (!isRecord(value.policy.providers)) {
263
+ findings.push('pjm.remote.policy.providers');
264
+ }
265
+ else {
266
+ const providers = new Set(['github', 'linear', 'jira']);
267
+ for (const [provider, providerPolicy] of Object.entries(value.policy.providers)) {
268
+ const path = `pjm.remote.policy.providers.${provider}`;
269
+ if (!providers.has(provider) || !isRecord(providerPolicy)) {
270
+ findings.push(path);
271
+ continue;
272
+ }
273
+ collectUnknownKeys(providerPolicy, ['description', 'authority'], path, findings);
274
+ if ('description' in providerPolicy &&
275
+ !isDescriptionMode(providerPolicy.description)) {
276
+ findings.push(`${path}.description`);
277
+ }
278
+ if ('authority' in providerPolicy) {
279
+ collectAuthorityFindings(providerPolicy.authority, `${path}.authority`, findings, false);
280
+ }
281
+ }
282
+ }
283
+ }
284
+ return [...new Set(findings)].sort();
285
+ }
286
+ function collectAuthorityFindings(value, path, findings, requireDefault) {
287
+ if (!isRecord(value)) {
288
+ findings.push(path);
289
+ return;
290
+ }
291
+ collectUnknownKeys(value, ['default', 'operations'], path, findings);
292
+ if (requireDefault && !('default' in value))
293
+ findings.push(`${path}.default`);
294
+ if ('default' in value && !isAuthority(value.default)) {
295
+ findings.push(`${path}.default`);
296
+ }
297
+ if ('operations' in value) {
298
+ if (!isRecord(value.operations)) {
299
+ findings.push(`${path}.operations`);
300
+ return;
301
+ }
302
+ const operations = new Set([
303
+ 'create',
304
+ 'update-fields',
305
+ 'transition',
306
+ 'annotate',
307
+ 'delete',
308
+ 'relink',
309
+ 'detach',
310
+ 'recreate',
311
+ ]);
312
+ for (const [operation, authority] of Object.entries(value.operations)) {
313
+ const operationPath = `${path}.operations.${operation}`;
314
+ if (!operations.has(operation) || !isAuthority(authority)) {
315
+ findings.push(operationPath);
316
+ }
317
+ }
318
+ }
319
+ }
320
+ function collectUnknownKeys(value, allowed, path, findings) {
321
+ const keys = new Set(allowed);
322
+ for (const key of Object.keys(value)) {
323
+ if (!keys.has(key))
324
+ findings.push(`${path}.${key}`);
325
+ }
326
+ }
327
+ function isDescriptionMode(value) {
328
+ return ['none', 'managed-section', 'replace'].includes(String(value));
329
+ }
330
+ function isAuthority(value) {
331
+ return [
332
+ 'read-only',
333
+ 'user-approved',
334
+ 'user-authorized',
335
+ 'autonomous',
336
+ ].includes(String(value));
337
+ }
338
+ function collectConcurrentBindings(operations) {
339
+ const counts = new Map();
340
+ const active = new Set([
341
+ 'planned',
342
+ 'pending',
343
+ 'authorized',
344
+ 'attempt-started',
345
+ 'verification-pending',
346
+ 'partial',
347
+ 'uncertain',
348
+ ]);
349
+ for (const operation of operations) {
350
+ if (active.has(operation.state)) {
351
+ counts.set(operation.bindingId, (counts.get(operation.bindingId) ?? 0) + 1);
352
+ }
353
+ }
354
+ return [...counts.entries()]
355
+ .filter(([, count]) => count > 1)
356
+ .map(([bindingId]) => bindingId)
357
+ .sort();
358
+ }
359
+ function findingCheck(name, description, findings) {
360
+ return {
361
+ name,
362
+ description,
363
+ status: findings.length === 0 ? 'pass' : 'fail',
364
+ message: findings.length === 0
365
+ ? `${description} passed.`
366
+ : `${description} findings: ${findings.join(', ')}`,
367
+ fix: findings.length === 0
368
+ ? undefined
369
+ : 'Inspect the named local record identifiers and reconcile them before remote mutation.',
370
+ };
371
+ }
372
+ function isRecord(value) {
373
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
374
+ }
375
+ function isFilesystemError(error, code) {
376
+ return (typeof error === 'object' &&
377
+ error !== null &&
378
+ 'code' in error &&
379
+ error.code === code);
380
+ }
@@ -0,0 +1,208 @@
1
+ import { z } from 'zod';
2
+ import { type OutboundProjection, type OutboundProjectionSafetyResult } from './outbound-projection-safety.js';
3
+ import { RemoteAccountContextSchema } from './schema.js';
4
+ declare const SuppressedFieldReferenceSchema: z.ZodDiscriminatedUnion<"kind", [z.ZodObject<{
5
+ kind: z.ZodLiteral<"core">;
6
+ name: z.ZodEnum<["title", "description", "priority", "status"]>;
7
+ }, "strict", z.ZodTypeAny, {
8
+ kind: "core";
9
+ name: "description" | "priority" | "status" | "title";
10
+ }, {
11
+ kind: "core";
12
+ name: "description" | "priority" | "status" | "title";
13
+ }>, z.ZodObject<{
14
+ kind: z.ZodLiteral<"extension">;
15
+ key: z.ZodString;
16
+ }, "strict", z.ZodTypeAny, {
17
+ kind: "extension";
18
+ key: string;
19
+ }, {
20
+ kind: "extension";
21
+ key: string;
22
+ }>]>;
23
+ declare const SemanticOperationSchema: z.ZodEnum<["read", "read-discussion", "search-duplicates", "create", "update", "transition", "annotate"]>;
24
+ export declare const ExternalObservationEnvelopeSchema: z.ZodObject<{
25
+ schemaVersion: z.ZodLiteral<1>;
26
+ operationId: z.ZodString;
27
+ stepId: z.ZodString;
28
+ actionDigest: z.ZodString;
29
+ observedAt: z.ZodString;
30
+ surfaceKind: z.ZodEnum<["connector", "configured-cli"]>;
31
+ capabilityEvidenceDigest: z.ZodString;
32
+ provider: z.ZodEnum<["github", "linear", "jira"]>;
33
+ context: z.ZodObject<{
34
+ host: z.ZodOptional<z.ZodString>;
35
+ owner: z.ZodOptional<z.ZodString>;
36
+ repositoryId: z.ZodOptional<z.ZodString>;
37
+ workspaceId: z.ZodOptional<z.ZodString>;
38
+ teamId: z.ZodOptional<z.ZodString>;
39
+ cloudId: z.ZodOptional<z.ZodString>;
40
+ siteId: z.ZodOptional<z.ZodString>;
41
+ projectId: z.ZodOptional<z.ZodString>;
42
+ }, "strict", z.ZodTypeAny, {
43
+ host?: string | undefined;
44
+ owner?: string | undefined;
45
+ repositoryId?: string | undefined;
46
+ workspaceId?: string | undefined;
47
+ teamId?: string | undefined;
48
+ cloudId?: string | undefined;
49
+ siteId?: string | undefined;
50
+ projectId?: string | undefined;
51
+ }, {
52
+ host?: string | undefined;
53
+ owner?: string | undefined;
54
+ repositoryId?: string | undefined;
55
+ workspaceId?: string | undefined;
56
+ teamId?: string | undefined;
57
+ cloudId?: string | undefined;
58
+ siteId?: string | undefined;
59
+ projectId?: string | undefined;
60
+ }>;
61
+ outcome: z.ZodObject<{
62
+ classification: z.ZodEnum<["observed", "not-committed", "unknown", "rejected"]>;
63
+ identity: z.ZodNullable<z.ZodObject<{
64
+ stableId: z.ZodString;
65
+ aliases: z.ZodArray<z.ZodString, "many">;
66
+ }, "strict", z.ZodTypeAny, {
67
+ stableId: string;
68
+ aliases: string[];
69
+ }, {
70
+ stableId: string;
71
+ aliases: string[];
72
+ }>>;
73
+ fields: z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>>;
74
+ extensions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>>>;
75
+ revisionDigest: z.ZodNullable<z.ZodString>;
76
+ diagnosticCode: z.ZodNullable<z.ZodString>;
77
+ }, "strict", z.ZodTypeAny, {
78
+ classification: "not-committed" | "observed" | "rejected" | "unknown";
79
+ identity: {
80
+ stableId: string;
81
+ aliases: string[];
82
+ } | null;
83
+ fields: Record<string, string | number | boolean | null>;
84
+ extensions?: Record<string, string | number | boolean | null> | undefined;
85
+ revisionDigest: string | null;
86
+ diagnosticCode: string | null;
87
+ }, {
88
+ classification: "not-committed" | "observed" | "rejected" | "unknown";
89
+ identity: {
90
+ stableId: string;
91
+ aliases: string[];
92
+ } | null;
93
+ fields: Record<string, string | number | boolean | null>;
94
+ extensions?: Record<string, string | number | boolean | null> | undefined;
95
+ revisionDigest: string | null;
96
+ diagnosticCode: string | null;
97
+ }>;
98
+ }, "strict", z.ZodTypeAny, {
99
+ schemaVersion: 1;
100
+ operationId: string;
101
+ stepId: string;
102
+ actionDigest: string;
103
+ observedAt: string;
104
+ surfaceKind: "configured-cli" | "connector";
105
+ capabilityEvidenceDigest: string;
106
+ provider: "github" | "jira" | "linear";
107
+ context: {
108
+ host?: string | undefined;
109
+ owner?: string | undefined;
110
+ repositoryId?: string | undefined;
111
+ workspaceId?: string | undefined;
112
+ teamId?: string | undefined;
113
+ cloudId?: string | undefined;
114
+ siteId?: string | undefined;
115
+ projectId?: string | undefined;
116
+ };
117
+ outcome: {
118
+ classification: "not-committed" | "observed" | "rejected" | "unknown";
119
+ identity: {
120
+ stableId: string;
121
+ aliases: string[];
122
+ } | null;
123
+ fields: Record<string, string | number | boolean | null>;
124
+ extensions?: Record<string, string | number | boolean | null> | undefined;
125
+ revisionDigest: string | null;
126
+ diagnosticCode: string | null;
127
+ };
128
+ }, {
129
+ schemaVersion: 1;
130
+ operationId: string;
131
+ stepId: string;
132
+ actionDigest: string;
133
+ observedAt: string;
134
+ surfaceKind: "configured-cli" | "connector";
135
+ capabilityEvidenceDigest: string;
136
+ provider: "github" | "jira" | "linear";
137
+ context: {
138
+ host?: string | undefined;
139
+ owner?: string | undefined;
140
+ repositoryId?: string | undefined;
141
+ workspaceId?: string | undefined;
142
+ teamId?: string | undefined;
143
+ cloudId?: string | undefined;
144
+ siteId?: string | undefined;
145
+ projectId?: string | undefined;
146
+ };
147
+ outcome: {
148
+ classification: "not-committed" | "observed" | "rejected" | "unknown";
149
+ identity: {
150
+ stableId: string;
151
+ aliases: string[];
152
+ } | null;
153
+ fields: Record<string, string | number | boolean | null>;
154
+ extensions?: Record<string, string | number | boolean | null> | undefined;
155
+ revisionDigest: string | null;
156
+ diagnosticCode: string | null;
157
+ };
158
+ }>;
159
+ export interface ExternalActionEnvelope {
160
+ schemaVersion: 1;
161
+ operationId: string;
162
+ stepId: string;
163
+ actionDigest: string;
164
+ provider: 'github' | 'linear' | 'jira';
165
+ semanticOperation: z.infer<typeof SemanticOperationSchema>;
166
+ context: z.infer<typeof RemoteAccountContextSchema>;
167
+ intent: Record<string, unknown>;
168
+ expectedObservation: {
169
+ fields: string[];
170
+ extensionFields?: string[];
171
+ requireIdentity: boolean;
172
+ stableId: string | null;
173
+ capabilityEvidenceDigest: string;
174
+ };
175
+ outboundSafety: {
176
+ projectionDigest: string;
177
+ resultDigest: string;
178
+ } | null;
179
+ }
180
+ export type ExternalObservationEnvelope = z.infer<typeof ExternalObservationEnvelopeSchema>;
181
+ export declare function parseExternalAction(value: unknown): ExternalActionEnvelope;
182
+ export declare function buildExternalAction(input: {
183
+ operationId: string;
184
+ stepId: string;
185
+ provider: ExternalActionEnvelope['provider'];
186
+ semanticOperation: ExternalActionEnvelope['semanticOperation'];
187
+ context: ExternalActionEnvelope['context'];
188
+ intent: Record<string, unknown>;
189
+ expectedObservation: ExternalActionEnvelope['expectedObservation'];
190
+ persistedPreview: {
191
+ projectionDigest?: string | null;
192
+ safetyResultDigest?: string | null;
193
+ };
194
+ projection?: OutboundProjection;
195
+ outboundSafety?: OutboundProjectionSafetyResult | null;
196
+ }): ExternalActionEnvelope;
197
+ export declare function acceptExternalObservation(input: {
198
+ action: ExternalActionEnvelope;
199
+ observation: unknown;
200
+ acceptedStepDigests?: ReadonlySet<string>;
201
+ }): AcceptedExternalObservationEnvelope;
202
+ export interface AcceptedExternalObservationEnvelope extends ExternalObservationEnvelope {
203
+ outcome: ExternalObservationEnvelope['outcome'] & {
204
+ suppressedFields: Array<z.infer<typeof SuppressedFieldReferenceSchema>>;
205
+ };
206
+ }
207
+ export {};
208
+ //# sourceMappingURL=external-action.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"external-action.d.ts","sourceRoot":"","sources":["../../../../src/commands/pjm/remote/external-action.ts"],"names":[],"mappings":"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"}