@aopslabs/aops 0.3.30 → 0.3.32

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 (147) hide show
  1. package/README.md +11 -3
  2. package/aops-assets-release/aops-assets.json.gz +0 -0
  3. package/aops-assets-release/disciplines/build-review-chat/SKILL.md +33 -0
  4. package/aops-assets-release/disciplines/coordinator-loop/SKILL.md +33 -0
  5. package/aops-assets-release/disciplines/design-first-consensus/SKILL.md +30 -0
  6. package/aops-assets-release/disciplines/solo-pm-loop/SKILL.md +31 -0
  7. package/aops-assets-release/docs/user-guides/agentspace-user-guide.md +384 -0
  8. package/aops-assets-release/docs/user-guides/aops-cli-user-guide.md +2067 -0
  9. package/aops-assets-release/docs/user-guides/chatv3-user-guide.md +500 -0
  10. package/aops-assets-release/docs/user-guides/docman-user-guide.md +1009 -0
  11. package/aops-assets-release/docs/user-guides/projectman-user-guide.md +763 -0
  12. package/aops-assets-release/docs/user-guides/tasker-user-guide.md +244 -0
  13. package/aops-assets-release/release.json +6 -0
  14. package/aops-assets-release/roles/coordinator/ROLE.md +28 -0
  15. package/aops-assets-release/roles/implementer/ROLE.md +27 -0
  16. package/aops-assets-release/roles/reviewer/ROLE.md +27 -0
  17. package/aops-assets-release/skills/aops/SKILL.md +112 -0
  18. package/aops-assets-release/skills/aops-bootstrapper-authoring/SKILL.md +245 -0
  19. package/aops-assets-release/skills/aops-cli-agentspace/SKILL.md +186 -0
  20. package/aops-assets-release/skills/aops-cli-board-lifecycle/SKILL.md +64 -0
  21. package/aops-assets-release/skills/aops-cli-chat/SKILL.md +204 -0
  22. package/aops-assets-release/skills/aops-cli-collab/SKILL.md +42 -0
  23. package/aops-assets-release/skills/aops-cli-core/SKILL.md +219 -0
  24. package/aops-assets-release/skills/aops-cli-discuss/SKILL.md +172 -0
  25. package/aops-assets-release/skills/aops-cli-docman/SKILL.md +192 -0
  26. package/aops-assets-release/skills/aops-cli-fileman/SKILL.md +169 -0
  27. package/aops-assets-release/skills/aops-cli-mission/SKILL.md +128 -0
  28. package/aops-assets-release/skills/aops-cli-operator-brief/SKILL.md +67 -0
  29. package/aops-assets-release/skills/aops-cli-projectman/SKILL.md +235 -0
  30. package/aops-assets-release/skills/aops-cli-sugar-authoring/SKILL.md +188 -0
  31. package/aops-assets-release/skills/aops-cli-tasker/SKILL.md +108 -0
  32. package/aops-assets-release/skills/aops-cli-tooling-agent/SKILL.md +112 -0
  33. package/aops-assets-release/skills/aops-cli-view/SKILL.md +210 -0
  34. package/aops-assets-release/skills/aops-collaborative-work/SKILL.md +304 -0
  35. package/aops-assets-release/skills/aops-interactive/SKILL.md +70 -0
  36. package/aops-assets-release/skills/aops-loop-interactive/SKILL.md +314 -0
  37. package/aops-assets-release/skills/aops-working-disciplines/SKILL.md +310 -0
  38. package/aops-assets-release/skills/feature-retirement-flow/SKILL.md +126 -0
  39. package/assets/skills/aops-install/SKILL.md +18 -17
  40. package/dist/commands/assets.js +93 -1264
  41. package/dist/commands/community-server.js +27 -8
  42. package/dist/commands/community-setup.js +1 -2
  43. package/dist/commands/discuss.js +1 -1
  44. package/dist/commands/doc.js +88 -27
  45. package/dist/commands/docs.js +68 -0
  46. package/dist/commands/global-update.js +28 -0
  47. package/dist/commands/init.js +3 -1
  48. package/dist/commands/loop.js +6379 -0
  49. package/dist/commands/memory.js +2 -1
  50. package/dist/commands/pm/index.js +11 -9
  51. package/dist/commands/pm/projectman.js +33 -2
  52. package/dist/commands/project.js +6 -6
  53. package/dist/commands/prompt.js +1 -1
  54. package/dist/commands/repo-sync.js +92 -27
  55. package/dist/commands/runner.js +257 -0
  56. package/dist/commands/skill.js +1 -1
  57. package/dist/commands/start.js +1 -1
  58. package/dist/commands/tasker.js +361 -0
  59. package/dist/commands/view.js +53 -9
  60. package/dist/lib/commercial-setup-readiness-adapter.js +0 -1
  61. package/dist/lib/community-migration-snapshot.js +7 -9
  62. package/dist/lib/community-native-database-recovery.js +5 -14
  63. package/dist/lib/community-native-lifecycle.js +13 -0
  64. package/dist/lib/setup-agent-assets-bridge.js +28 -148
  65. package/dist/lib/setup-agent-assets-release.js +16 -44
  66. package/dist/lib/setup-init-orchestrator.js +11 -15
  67. package/dist/lib/simple-agent-assets.js +447 -0
  68. package/dist/lib/user-guide-sections.js +488 -0
  69. package/dist/main.js +10 -2
  70. package/dist/seeds/agents-md.js +3 -3
  71. package/dist/utils/agents-md.js +1 -1
  72. package/dist/utils/guide-paths.js +7 -7
  73. package/dist/utils/hosted-workspace.js +2 -1
  74. package/dist/utils/repo-first-storage.js +26 -1
  75. package/dist/utils/session-state.js +2 -7
  76. package/launchers/aops-cockpit.sh +0 -0
  77. package/launchers/aops-server.sh +0 -0
  78. package/package.json +67 -35
  79. package/THIRD_PARTY_NOTICES +0 -16169
  80. package/agent-assets-release/agent-assets/core/bc42dd7792dbe66040e99a7ef3d80b3bc788c72b369b5a065cf936aef29f53fb/files/SKILL.md +0 -47
  81. package/agent-assets-release/agent-assets/core/bc42dd7792dbe66040e99a7ef3d80b3bc788c72b369b5a065cf936aef29f53fb/files/references/agentspace/SKILL.md +0 -72
  82. package/agent-assets-release/agent-assets/core/bc42dd7792dbe66040e99a7ef3d80b3bc788c72b369b5a065cf936aef29f53fb/files/references/aops-cli-core/SKILL.md +0 -110
  83. package/agent-assets-release/agent-assets/core/bc42dd7792dbe66040e99a7ef3d80b3bc788c72b369b5a065cf936aef29f53fb/files/references/chatv3/SKILL.md +0 -59
  84. package/agent-assets-release/agent-assets/core/bc42dd7792dbe66040e99a7ef3d80b3bc788c72b369b5a065cf936aef29f53fb/files/references/collaborative-work/SKILL.md +0 -81
  85. package/agent-assets-release/agent-assets/core/bc42dd7792dbe66040e99a7ef3d80b3bc788c72b369b5a065cf936aef29f53fb/files/references/discuss/SKILL.md +0 -66
  86. package/agent-assets-release/agent-assets/core/bc42dd7792dbe66040e99a7ef3d80b3bc788c72b369b5a065cf936aef29f53fb/files/references/docman/SKILL.md +0 -75
  87. package/agent-assets-release/agent-assets/core/bc42dd7792dbe66040e99a7ef3d80b3bc788c72b369b5a065cf936aef29f53fb/files/references/projectman/SKILL.md +0 -92
  88. package/agent-assets-release/agent-assets/core/bc42dd7792dbe66040e99a7ef3d80b3bc788c72b369b5a065cf936aef29f53fb/files/references/sys/SKILL.md +0 -36
  89. package/agent-assets-release/agent-assets/core/bc42dd7792dbe66040e99a7ef3d80b3bc788c72b369b5a065cf936aef29f53fb/files/references/view/SKILL.md +0 -58
  90. package/agent-assets-release/agent-assets/core/bc42dd7792dbe66040e99a7ef3d80b3bc788c72b369b5a065cf936aef29f53fb/files/references/working-disciplines/SKILL.md +0 -66
  91. package/agent-assets-release/agent-assets/core/bc42dd7792dbe66040e99a7ef3d80b3bc788c72b369b5a065cf936aef29f53fb/files/user-guides/agent-assets.md +0 -81
  92. package/agent-assets-release/agent-assets/core/bc42dd7792dbe66040e99a7ef3d80b3bc788c72b369b5a065cf936aef29f53fb/files/user-guides/agentspace.md +0 -183
  93. package/agent-assets-release/agent-assets/core/bc42dd7792dbe66040e99a7ef3d80b3bc788c72b369b5a065cf936aef29f53fb/files/user-guides/aops-cli.md +0 -1108
  94. package/agent-assets-release/agent-assets/core/bc42dd7792dbe66040e99a7ef3d80b3bc788c72b369b5a065cf936aef29f53fb/files/user-guides/aops-system.md +0 -102
  95. package/agent-assets-release/agent-assets/core/bc42dd7792dbe66040e99a7ef3d80b3bc788c72b369b5a065cf936aef29f53fb/files/user-guides/chatv3.md +0 -113
  96. package/agent-assets-release/agent-assets/core/bc42dd7792dbe66040e99a7ef3d80b3bc788c72b369b5a065cf936aef29f53fb/files/user-guides/docman.md +0 -223
  97. package/agent-assets-release/agent-assets/core/bc42dd7792dbe66040e99a7ef3d80b3bc788c72b369b5a065cf936aef29f53fb/files/user-guides/projectman.md +0 -233
  98. package/agent-assets-release/agent-assets/core/bc42dd7792dbe66040e99a7ef3d80b3bc788c72b369b5a065cf936aef29f53fb/files/user-guides/sys.md +0 -94
  99. package/agent-assets-release/agent-assets/core/bc42dd7792dbe66040e99a7ef3d80b3bc788c72b369b5a065cf936aef29f53fb/files/user-guides/working-disciplines.md +0 -482
  100. package/agent-assets-release/agent-assets/core/bc42dd7792dbe66040e99a7ef3d80b3bc788c72b369b5a065cf936aef29f53fb/manifest.json +0 -117
  101. package/agent-assets-release/agent-assets/gateway/aops/SKILL.md +0 -14
  102. package/agent-assets-release/agent-assets/inventory.json +0 -29
  103. package/agent-assets-release/agent-assets/projection.json +0 -8
  104. package/agent-assets-release/agent-assets-release.json +0 -171
  105. package/agent-assets-release/agent-assets-release.sigstore.json +0 -67
  106. package/assets/agent-assets/core/SKILL.md +0 -47
  107. package/assets/agent-assets/core/references/agentspace/SKILL.md +0 -72
  108. package/assets/agent-assets/core/references/aops-cli-core/SKILL.md +0 -110
  109. package/assets/agent-assets/core/references/chatv3/SKILL.md +0 -59
  110. package/assets/agent-assets/core/references/collaborative-work/SKILL.md +0 -81
  111. package/assets/agent-assets/core/references/discuss/SKILL.md +0 -66
  112. package/assets/agent-assets/core/references/docman/SKILL.md +0 -75
  113. package/assets/agent-assets/core/references/projectman/SKILL.md +0 -92
  114. package/assets/agent-assets/core/references/sys/SKILL.md +0 -36
  115. package/assets/agent-assets/core/references/view/SKILL.md +0 -58
  116. package/assets/agent-assets/core/references/working-disciplines/SKILL.md +0 -66
  117. package/assets/agent-assets/core/user-guides/agent-assets.md +0 -81
  118. package/assets/agent-assets/core/user-guides/agentspace.md +0 -183
  119. package/assets/agent-assets/core/user-guides/aops-cli.md +0 -1108
  120. package/assets/agent-assets/core/user-guides/aops-system.md +0 -102
  121. package/assets/agent-assets/core/user-guides/chatv3.md +0 -113
  122. package/assets/agent-assets/core/user-guides/docman.md +0 -223
  123. package/assets/agent-assets/core/user-guides/projectman.md +0 -233
  124. package/assets/agent-assets/core/user-guides/sys.md +0 -94
  125. package/assets/agent-assets/core/user-guides/working-disciplines.md +0 -482
  126. package/assets/agent-assets/gateway/aops/SKILL.md +0 -14
  127. package/dist/lib/agent-assets/gateway.js +0 -15
  128. package/dist/lib/agent-assets/guards.js +0 -23
  129. package/dist/lib/agent-assets/hosted-discovery.js +0 -148
  130. package/dist/lib/agent-assets/hosted-package-input.js +0 -154
  131. package/dist/lib/agent-assets/legacy-pointer-migration.js +0 -677
  132. package/dist/lib/agent-assets/native-fs.js +0 -589
  133. package/dist/lib/agent-assets/roots.js +0 -45
  134. package/dist/lib/agent-assets/runtime-binding-reader.js +0 -545
  135. package/dist/lib/agent-assets/runtime-targets.js +0 -50
  136. package/dist/lib/agent-assets/store-reader.js +0 -1212
  137. package/dist/lib/agent-assets/store-writer.js +0 -1484
  138. package/native/bin/darwin-arm64/aops-agent-assets-fs +0 -0
  139. package/native/bin/darwin-x64/aops-agent-assets-fs +0 -0
  140. package/native/bin/linux-arm64/aops-agent-assets-fs +0 -0
  141. package/native/bin/linux-x64/aops-agent-assets-fs +0 -0
  142. package/native/bin/win32-x64/aops-agent-assets-fs.exe +0 -0
  143. package/native/manifest.json +0 -49
  144. package/native/qualifications/win32-x64.json +0 -23
  145. package/native/tui/darwin-arm64/aops-tui +0 -0
  146. package/native/tui/linux-x64/aops-tui +0 -0
  147. package/native/tui/win32-x64/aops-tui.exe +0 -0
@@ -1,545 +0,0 @@
1
- import { createHash } from 'node:crypto';
2
- import { closeSync, constants, existsSync, fstatSync, lstatSync, openSync, readFileSync, readdirSync, realpathSync, } from 'node:fs';
3
- import path from 'node:path';
4
- import { AgentAssetsError } from './envelope.js';
5
- import { AOPS_AGENT_ASSETS_GATEWAY, AOPS_AGENT_ASSETS_GATEWAY_RELATIVE_PATH, AOPS_AGENT_ASSETS_GATEWAY_SHA256, } from './gateway.js';
6
- import { canonicalJsonSha256V1, canonicalJsonV1, parseActivationReceiptV1, parseStoreAuthorityV1, } from './store-reader.js';
7
- const SHA256_HEX = /^[a-f0-9]{64}$/;
8
- const MAX_BINDING_BYTES = 64 * 1024;
9
- const MAX_GATEWAY_BYTES = 16 * 1024;
10
- const MAX_RECEIPT_ENTRIES = 10_000;
11
- const RUNTIME_BINDING_KEYS = [
12
- 'schemaVersion',
13
- 'storeId',
14
- 'bindingId',
15
- 'bindingGeneration',
16
- 'runtime',
17
- 'runtimeHomeId',
18
- 'runtimeRootIdentitySha256',
19
- 'gatewayName',
20
- 'relativePath',
21
- 'ownerMarkerRelativePath',
22
- 'contentSha256',
23
- 'ownerMarkerSha256',
24
- 'activationReceiptId',
25
- 'activationReceiptSha256',
26
- 'bindingReceiptId',
27
- 'bindingReceiptSha256',
28
- 'previousContentSha256',
29
- 'installedAt',
30
- 'writerFenceEpoch',
31
- 'authorityRevision',
32
- ];
33
- const RUNTIME_BINDING_RECEIPT_KEYS = RUNTIME_BINDING_KEYS.filter((key) => key !== 'bindingReceiptSha256');
34
- const OWNER_MARKER_KEYS = [
35
- 'schemaVersion',
36
- 'owner',
37
- 'storeId',
38
- 'runtime',
39
- 'bindingId',
40
- 'bindingGeneration',
41
- 'relativePath',
42
- 'contentSha256',
43
- ];
44
- function bindingError(message, details) {
45
- return new AgentAssetsError('schema_incompatible', message, {
46
- nextActions: ['Run `aops assets status --verify full --json` and inspect the binding diagnostics.'],
47
- ...(details === undefined ? {} : { details }),
48
- });
49
- }
50
- function isRecord(value) {
51
- return typeof value === 'object' && value !== null && !Array.isArray(value);
52
- }
53
- function exactRecord(value, keys, label) {
54
- if (!isRecord(value))
55
- throw bindingError(`${label} must be an object.`);
56
- const actual = Object.keys(value).sort();
57
- const expected = [...keys].sort();
58
- if (JSON.stringify(actual) !== JSON.stringify(expected)) {
59
- throw bindingError(`${label} has missing or unknown fields.`, { actual, expected });
60
- }
61
- return value;
62
- }
63
- function stringField(record, key, label, minimumLength = 1) {
64
- const value = record[key];
65
- if (typeof value !== 'string' || value.length < minimumLength) {
66
- throw bindingError(`${label}.${key} must be a non-empty string.`);
67
- }
68
- return value;
69
- }
70
- function integerField(record, key, label, minimum) {
71
- const value = record[key];
72
- if (!Number.isSafeInteger(value) || value < minimum) {
73
- throw bindingError(`${label}.${key} must be an integer greater than or equal to ${minimum}.`);
74
- }
75
- return value;
76
- }
77
- function shaField(record, key, label) {
78
- const value = stringField(record, key, label);
79
- if (!SHA256_HEX.test(value))
80
- throw bindingError(`${label}.${key} must be lowercase SHA-256.`);
81
- return value;
82
- }
83
- function exactString(record, key, expected, label) {
84
- if (record[key] !== expected)
85
- throw bindingError(`${label}.${key} must equal ${expected}.`);
86
- return expected;
87
- }
88
- function runtimeField(record, key, label) {
89
- const value = record[key];
90
- if (value !== 'codex' && value !== 'claude')
91
- throw bindingError(`${label}.${key} must be codex or claude.`);
92
- return value;
93
- }
94
- function dateField(record, key, label) {
95
- const value = stringField(record, key, label);
96
- if (!Number.isFinite(Date.parse(value)))
97
- throw bindingError(`${label}.${key} must be an ISO date-time.`);
98
- return value;
99
- }
100
- function parseRuntimeBindingRecord(value, receipt) {
101
- const label = receipt ? 'RuntimeBindingReceiptV1' : 'RuntimeBindingV1';
102
- const allKeys = receipt ? RUNTIME_BINDING_RECEIPT_KEYS : RUNTIME_BINDING_KEYS;
103
- const actualRecord = isRecord(value) ? value : undefined;
104
- const keys = actualRecord && !Object.hasOwn(actualRecord, 'previousContentSha256')
105
- ? allKeys.filter((key) => key !== 'previousContentSha256')
106
- : allKeys;
107
- const record = exactRecord(value, keys, label);
108
- if (record.schemaVersion !== 1)
109
- throw bindingError(`${label}.schemaVersion must equal 1.`);
110
- const hasPreviousContentSha256 = Object.hasOwn(record, 'previousContentSha256');
111
- const previousContentSha256 = hasPreviousContentSha256
112
- ? record.previousContentSha256 === null
113
- ? null
114
- : shaField(record, 'previousContentSha256', label)
115
- : undefined;
116
- const common = {
117
- schemaVersion: 1,
118
- storeId: stringField(record, 'storeId', label, 16),
119
- bindingId: stringField(record, 'bindingId', label),
120
- bindingGeneration: integerField(record, 'bindingGeneration', label, 1),
121
- runtime: runtimeField(record, 'runtime', label),
122
- runtimeHomeId: shaField(record, 'runtimeHomeId', label),
123
- runtimeRootIdentitySha256: shaField(record, 'runtimeRootIdentitySha256', label),
124
- gatewayName: exactString(record, 'gatewayName', 'aops', label),
125
- relativePath: exactString(record, 'relativePath', 'skills/aops/SKILL.md', label),
126
- ownerMarkerRelativePath: exactString(record, 'ownerMarkerRelativePath', 'skills/aops/.aops-gateway-owner.json', label),
127
- contentSha256: shaField(record, 'contentSha256', label),
128
- ownerMarkerSha256: shaField(record, 'ownerMarkerSha256', label),
129
- activationReceiptId: stringField(record, 'activationReceiptId', label),
130
- activationReceiptSha256: shaField(record, 'activationReceiptSha256', label),
131
- bindingReceiptId: stringField(record, 'bindingReceiptId', label),
132
- ...(hasPreviousContentSha256 ? { previousContentSha256 } : {}),
133
- installedAt: dateField(record, 'installedAt', label),
134
- writerFenceEpoch: integerField(record, 'writerFenceEpoch', label, 1),
135
- authorityRevision: integerField(record, 'authorityRevision', label, 1),
136
- };
137
- if (receipt)
138
- return common;
139
- return { ...common, bindingReceiptSha256: shaField(record, 'bindingReceiptSha256', label) };
140
- }
141
- export function parseRuntimeBindingV1(value) {
142
- return parseRuntimeBindingRecord(value, false);
143
- }
144
- export function parseRuntimeBindingReceiptV1(value) {
145
- return parseRuntimeBindingRecord(value, true);
146
- }
147
- export function parseRuntimeGatewayOwnerMarkerV1(value) {
148
- const label = 'RuntimeGatewayOwnerMarkerV1';
149
- const record = exactRecord(value, OWNER_MARKER_KEYS, label);
150
- if (record.schemaVersion !== 1)
151
- throw bindingError(`${label}.schemaVersion must equal 1.`);
152
- return {
153
- schemaVersion: 1,
154
- owner: exactString(record, 'owner', 'aops-cli-agent-assets', label),
155
- storeId: stringField(record, 'storeId', label, 16),
156
- runtime: runtimeField(record, 'runtime', label),
157
- bindingId: stringField(record, 'bindingId', label),
158
- bindingGeneration: integerField(record, 'bindingGeneration', label, 1),
159
- relativePath: exactString(record, 'relativePath', 'skills/aops/SKILL.md', label),
160
- contentSha256: shaField(record, 'contentSha256', label),
161
- };
162
- }
163
- function sha256Bytes(bytes) {
164
- return createHash('sha256').update(bytes).digest('hex');
165
- }
166
- export function agentAssetsRuntimeHomeId(runtime, runtimeHome) {
167
- if (!path.isAbsolute(runtimeHome))
168
- throw bindingError('The runtime home must be absolute.');
169
- const canonicalPath = process.platform === 'win32'
170
- ? path.normalize(runtimeHome).toLowerCase()
171
- : path.normalize(runtimeHome);
172
- return createHash('sha256').update(`agent-assets-${runtime}\0${canonicalPath}`, 'utf8').digest('hex');
173
- }
174
- function isSameFile(before, after) {
175
- return before.dev === after.dev && before.ino === after.ino && before.size === after.size;
176
- }
177
- function realPathIsWithin(realRoot, candidate) {
178
- const relative = path.relative(realRoot, candidate);
179
- return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative));
180
- }
181
- function linkedExistingAncestor(absolutePath) {
182
- const normalized = path.normalize(absolutePath);
183
- const parsed = path.parse(normalized);
184
- let cursor = parsed.root;
185
- const relative = normalized.slice(parsed.root.length);
186
- for (const segment of relative.split(path.sep).filter(Boolean)) {
187
- cursor = path.join(cursor, segment);
188
- if (!existsSync(cursor))
189
- break;
190
- if (lstatSync(cursor).isSymbolicLink())
191
- return true;
192
- }
193
- return false;
194
- }
195
- function safeReadBoundedFile(rootPath, segments, maximumBytes) {
196
- if (!path.isAbsolute(rootPath))
197
- return { state: 'unsafe-path', reason: 'root-not-absolute' };
198
- const root = path.normalize(rootPath);
199
- if (linkedExistingAncestor(root))
200
- return { state: 'unsafe-path', reason: 'root-or-parent-link' };
201
- if (!existsSync(root))
202
- return { state: 'absent' };
203
- try {
204
- const rootStat = lstatSync(root);
205
- if (rootStat.isSymbolicLink() || !rootStat.isDirectory()) {
206
- return { state: 'unsafe-path', reason: 'root-link-or-special' };
207
- }
208
- const realRoot = realpathSync.native(root);
209
- let cursor = root;
210
- for (const segment of segments.slice(0, -1)) {
211
- if (!segment || segment === '.' || segment === '..' || segment.includes('/') || segment.includes('\\')) {
212
- return { state: 'unsafe-path', reason: 'unsafe-segment' };
213
- }
214
- cursor = path.join(cursor, segment);
215
- if (!existsSync(cursor))
216
- return { state: 'absent' };
217
- const stat = lstatSync(cursor);
218
- if (stat.isSymbolicLink() || !stat.isDirectory()) {
219
- return { state: 'unsafe-path', reason: 'ancestor-link-or-special' };
220
- }
221
- if (!realPathIsWithin(realRoot, realpathSync.native(cursor))) {
222
- return { state: 'unsafe-path', reason: 'ancestor-escaped-root' };
223
- }
224
- }
225
- const finalSegment = segments.at(-1);
226
- if (!finalSegment || finalSegment === '.' || finalSegment === '..' || finalSegment.includes('/') || finalSegment.includes('\\')) {
227
- return { state: 'unsafe-path', reason: 'unsafe-segment' };
228
- }
229
- const filePath = path.join(cursor, finalSegment);
230
- if (!existsSync(filePath))
231
- return { state: 'absent' };
232
- const before = lstatSync(filePath);
233
- if (before.isSymbolicLink() || !before.isFile() || before.size < 1 || before.size > maximumBytes) {
234
- return { state: 'unsafe-path', reason: 'file-link-special-or-unbounded' };
235
- }
236
- if (!realPathIsWithin(realRoot, realpathSync.native(filePath))) {
237
- return { state: 'unsafe-path', reason: 'file-escaped-root' };
238
- }
239
- const noFollow = process.platform === 'win32' ? 0 : (constants.O_NOFOLLOW ?? 0);
240
- const fd = openSync(filePath, constants.O_RDONLY | noFollow);
241
- try {
242
- const opened = fstatSync(fd);
243
- if (!opened.isFile() || !isSameFile(before, opened)) {
244
- return { state: 'unsafe-path', reason: 'file-changed-during-open' };
245
- }
246
- const bytes = readFileSync(fd);
247
- const after = lstatSync(filePath);
248
- if (!isSameFile(opened, after) || after.isSymbolicLink()) {
249
- return { state: 'unsafe-path', reason: 'file-changed-during-read' };
250
- }
251
- if (!realPathIsWithin(realRoot, realpathSync.native(filePath))) {
252
- return { state: 'unsafe-path', reason: 'file-escaped-after-read' };
253
- }
254
- return { state: 'ready', bytes };
255
- }
256
- finally {
257
- closeSync(fd);
258
- }
259
- }
260
- catch (error) {
261
- return { state: 'unsafe-path', reason: error instanceof Error ? error.name : 'read-failed' };
262
- }
263
- }
264
- function safeDirectoryEntries(rootPath, segments) {
265
- if (!path.isAbsolute(rootPath))
266
- return { state: 'unsafe-path', reason: 'root-not-absolute' };
267
- const root = path.normalize(rootPath);
268
- if (linkedExistingAncestor(root))
269
- return { state: 'unsafe-path', reason: 'root-or-parent-link' };
270
- if (!existsSync(root))
271
- return { state: 'absent' };
272
- try {
273
- const rootStat = lstatSync(root);
274
- if (rootStat.isSymbolicLink() || !rootStat.isDirectory()) {
275
- return { state: 'unsafe-path', reason: 'root-link-or-special' };
276
- }
277
- const realRoot = realpathSync.native(root);
278
- let cursor = root;
279
- for (const segment of segments) {
280
- if (!segment || segment === '.' || segment === '..' || segment.includes('/') || segment.includes('\\')) {
281
- return { state: 'unsafe-path', reason: 'unsafe-segment' };
282
- }
283
- cursor = path.join(cursor, segment);
284
- if (!existsSync(cursor))
285
- return { state: 'absent' };
286
- const stat = lstatSync(cursor);
287
- if (stat.isSymbolicLink() || !stat.isDirectory()) {
288
- return { state: 'unsafe-path', reason: 'directory-link-or-special' };
289
- }
290
- if (!realPathIsWithin(realRoot, realpathSync.native(cursor))) {
291
- return { state: 'unsafe-path', reason: 'directory-escaped-root' };
292
- }
293
- }
294
- const names = readdirSync(cursor);
295
- if (names.length > MAX_RECEIPT_ENTRIES)
296
- return { state: 'unsafe-path', reason: 'directory-unbounded' };
297
- return { state: 'ready', names };
298
- }
299
- catch (error) {
300
- return { state: 'unsafe-path', reason: error instanceof Error ? error.name : 'directory-read-failed' };
301
- }
302
- }
303
- function parseJson(bytes, label) {
304
- try {
305
- return JSON.parse(bytes.toString('utf8'));
306
- }
307
- catch {
308
- throw bindingError(`${label} is not valid JSON.`);
309
- }
310
- }
311
- function bindingReceiptBody(binding) {
312
- const { bindingReceiptSha256: _bindingReceiptSha256, ...receipt } = binding;
313
- return receipt;
314
- }
315
- function assertBindingReceiptMatches(binding, receipt, value) {
316
- if (canonicalJsonSha256V1(value) !== binding.bindingReceiptSha256) {
317
- throw bindingError('Runtime binding receipt digest does not match the current pointer.');
318
- }
319
- if (canonicalJsonV1(receipt) !== canonicalJsonV1(bindingReceiptBody(binding))) {
320
- throw bindingError('Runtime binding current pointer and immutable receipt disagree.');
321
- }
322
- }
323
- function readActivationReceipt(assetRoot, binding) {
324
- const listed = safeDirectoryEntries(assetRoot, ['state', 'receipts']);
325
- if (listed.state !== 'ready') {
326
- if (listed.state === 'absent')
327
- throw bindingError('Activation receipt directory is missing.');
328
- throw new AgentAssetsError('link_unsafe_path', 'Activation receipt directory is link-unsafe.', {
329
- nextActions: ['Do not repair or overwrite the runtime binding until the unsafe path is resolved.'],
330
- });
331
- }
332
- let found;
333
- for (const name of listed.names) {
334
- if (!name.endsWith('.json'))
335
- throw bindingError('Activation receipt directory contains an unknown entry.');
336
- const loaded = safeReadBoundedFile(assetRoot, ['state', 'receipts', name], MAX_BINDING_BYTES);
337
- if (loaded.state !== 'ready') {
338
- if (loaded.state === 'unsafe-path') {
339
- throw new AgentAssetsError('link_unsafe_path', 'Activation receipt path is link-unsafe.', {
340
- nextActions: ['Do not repair or overwrite the runtime binding until the unsafe path is resolved.'],
341
- });
342
- }
343
- throw bindingError('Activation receipt disappeared during inspection.');
344
- }
345
- const value = parseJson(loaded.bytes, 'ActivationReceiptV1');
346
- const receipt = parseActivationReceiptV1(value);
347
- if (receipt.receiptId !== binding.activationReceiptId)
348
- continue;
349
- if (canonicalJsonSha256V1(value) !== binding.activationReceiptSha256) {
350
- throw bindingError('Runtime binding activation receipt digest does not match.');
351
- }
352
- if (found)
353
- throw bindingError('Multiple activation receipts claim the runtime binding activation id.');
354
- found = receipt;
355
- }
356
- if (!found)
357
- throw bindingError('Runtime binding activation receipt was not found.');
358
- return found;
359
- }
360
- function readStoreBinding(options) {
361
- const current = safeReadBoundedFile(options.assetRoot, ['state', 'bindings', `${options.runtime}.json`], MAX_BINDING_BYTES);
362
- if (current.state !== 'ready')
363
- return current;
364
- try {
365
- const binding = parseRuntimeBindingV1(parseJson(current.bytes, 'RuntimeBindingV1'));
366
- const receiptFile = `${binding.bindingGeneration}-${binding.bindingReceiptId}.json`;
367
- const receiptRead = safeReadBoundedFile(options.assetRoot, ['state', 'bindings', 'receipts', options.runtime, receiptFile], MAX_BINDING_BYTES);
368
- if (receiptRead.state === 'unsafe-path')
369
- return receiptRead;
370
- if (receiptRead.state === 'absent')
371
- throw bindingError('Immutable runtime binding receipt is missing.');
372
- const receiptValue = parseJson(receiptRead.bytes, 'RuntimeBindingReceiptV1');
373
- const receipt = parseRuntimeBindingReceiptV1(receiptValue);
374
- assertBindingReceiptMatches(binding, receipt, receiptValue);
375
- const authorityRead = safeReadBoundedFile(options.assetRoot, ['state', 'store-authority.json'], MAX_BINDING_BYTES);
376
- if (authorityRead.state === 'unsafe-path')
377
- return authorityRead;
378
- if (authorityRead.state === 'absent')
379
- throw bindingError('Store authority is missing for a runtime binding.');
380
- const authority = parseStoreAuthorityV1(parseJson(authorityRead.bytes, 'StoreAuthorityV1'));
381
- if (options.authority && canonicalJsonV1(options.authority) !== canonicalJsonV1(authority)) {
382
- throw bindingError('Supplied authority context disagrees with the on-disk store authority.');
383
- }
384
- if (binding.storeId !== authority.storeId)
385
- throw bindingError('Runtime binding belongs to another store.');
386
- if (binding.authorityRevision > authority.authorityRevision
387
- || binding.writerFenceEpoch > authority.lastIssuedFenceEpoch) {
388
- throw bindingError('Runtime binding claims a future authority or writer fence.');
389
- }
390
- const activation = readActivationReceipt(options.assetRoot, binding);
391
- if (activation.storeId !== authority.storeId)
392
- throw bindingError('Runtime binding activation receipt belongs to another store.');
393
- if (activation.authorityRevision > authority.authorityRevision
394
- || activation.writerFenceEpoch > authority.lastIssuedFenceEpoch) {
395
- throw bindingError('Runtime binding activation receipt claims a future authority or writer fence.');
396
- }
397
- return { state: 'ready', binding };
398
- }
399
- catch (error) {
400
- if (error instanceof AgentAssetsError && error.code === 'link_unsafe_path') {
401
- return { state: 'unsafe-path', reason: error.message };
402
- }
403
- return { state: 'invalid', reason: error instanceof Error ? error.message : 'invalid-binding' };
404
- }
405
- }
406
- function markerMatchesBinding(marker, binding) {
407
- return marker.storeId === binding.storeId
408
- && marker.runtime === binding.runtime
409
- && marker.bindingId === binding.bindingId
410
- && marker.bindingGeneration === binding.bindingGeneration
411
- && marker.relativePath === binding.relativePath
412
- && marker.contentSha256 === binding.contentSha256;
413
- }
414
- export function inspectRuntimeGatewayBinding(options) {
415
- const runtimeHomeId = agentAssetsRuntimeHomeId(options.runtime, options.runtimeHome);
416
- const store = readStoreBinding(options);
417
- const markerRead = safeReadBoundedFile(options.runtimeHome, ['skills', 'aops', '.aops-gateway-owner.json'], MAX_BINDING_BYTES);
418
- const gatewayRead = safeReadBoundedFile(options.runtimeHome, ['skills', 'aops', 'SKILL.md'], MAX_GATEWAY_BYTES);
419
- let marker;
420
- let ownerMarker;
421
- if (markerRead.state === 'ready') {
422
- try {
423
- marker = parseRuntimeGatewayOwnerMarkerV1(parseJson(markerRead.bytes, 'RuntimeGatewayOwnerMarkerV1'));
424
- ownerMarker = 'ready';
425
- }
426
- catch {
427
- ownerMarker = 'invalid';
428
- }
429
- }
430
- else {
431
- ownerMarker = markerRead.state;
432
- }
433
- const gatewayContentSha256 = gatewayRead.state === 'ready' ? sha256Bytes(gatewayRead.bytes) : undefined;
434
- const gateway = gatewayRead.state === 'ready'
435
- ? gatewayRead.bytes.equals(Buffer.from(AOPS_AGENT_ASSETS_GATEWAY, 'utf8'))
436
- && gatewayContentSha256 === AOPS_AGENT_ASSETS_GATEWAY_SHA256
437
- ? 'canonical'
438
- : 'tampered'
439
- : gatewayRead.state;
440
- const reasons = [];
441
- if (store.state !== 'ready')
442
- reasons.push(`store-binding-${store.state === 'unsafe-path' ? 'unsafe' : store.state}`);
443
- if (ownerMarker !== 'ready')
444
- reasons.push(`owner-marker-${ownerMarker === 'unsafe-path' ? 'unsafe' : ownerMarker}`);
445
- if (gateway !== 'canonical')
446
- reasons.push(`gateway-${gateway === 'unsafe-path' ? 'unsafe' : gateway}`);
447
- let bindingProof = store.state === 'ready' ? 'verified' : store.state;
448
- let runtimeRootIdentityEvidence = 'unavailable';
449
- const bindingUsesCurrentGateway = store.state === 'ready'
450
- && store.binding.contentSha256 === AOPS_AGENT_ASSETS_GATEWAY_SHA256;
451
- if (store.state === 'ready' && !bindingUsesCurrentGateway)
452
- reasons.push('binding-content-outdated');
453
- if (store.state === 'ready') {
454
- const binding = store.binding;
455
- const contextMatches = binding.runtime === options.runtime
456
- && binding.runtimeHomeId === runtimeHomeId;
457
- if (!contextMatches) {
458
- bindingProof = 'invalid';
459
- reasons.push('binding-context-mismatch');
460
- }
461
- if (options.expectedRuntimeRootIdentitySha256 === undefined) {
462
- runtimeRootIdentityEvidence = 'recorded-not-live-verified';
463
- }
464
- else if (binding.runtimeRootIdentitySha256 === options.expectedRuntimeRootIdentitySha256) {
465
- runtimeRootIdentityEvidence = 'native-qualified-match';
466
- }
467
- else {
468
- runtimeRootIdentityEvidence = 'native-qualified-mismatch';
469
- bindingProof = 'invalid';
470
- reasons.push('binding-context-mismatch');
471
- }
472
- }
473
- let ownerMarkerProof;
474
- if (ownerMarker === 'absent')
475
- ownerMarkerProof = 'absent';
476
- else if (ownerMarker === 'unsafe-path')
477
- ownerMarkerProof = 'unsafe-path';
478
- else if (ownerMarker === 'invalid')
479
- ownerMarkerProof = 'mismatch';
480
- else if (store.state !== 'ready' || bindingProof !== 'verified' || !marker || markerRead.state !== 'ready') {
481
- ownerMarkerProof = 'unavailable';
482
- }
483
- else if (sha256Bytes(markerRead.bytes) === store.binding.ownerMarkerSha256
484
- && markerMatchesBinding(marker, store.binding)) {
485
- ownerMarkerProof = 'verified';
486
- }
487
- else {
488
- ownerMarkerProof = 'mismatch';
489
- }
490
- if (ownerMarker === 'ready' && ownerMarkerProof !== 'verified')
491
- reasons.push('binding-marker-mismatch');
492
- const coherent = bindingProof === 'verified'
493
- && ownerMarkerProof === 'verified'
494
- && bindingUsesCurrentGateway
495
- && gateway === 'canonical';
496
- const unsafe = store.state === 'unsafe-path' || ownerMarker === 'unsafe-path' || gateway === 'unsafe-path';
497
- const immutableManagedDrift = bindingProof === 'verified' && ((ownerMarkerProof === 'verified'
498
- && (gateway === 'absent' || gateway === 'tampered' || !bindingUsesCurrentGateway))
499
- || (ownerMarkerProof === 'absent' && (gateway === 'absent' || gateway === 'canonical')));
500
- let state;
501
- if (unsafe) {
502
- state = 'unsafe-path';
503
- }
504
- else if (coherent) {
505
- state = 'ready';
506
- }
507
- else if (immutableManagedDrift) {
508
- state = 'managed-drift';
509
- }
510
- else if (store.state === 'absent' && ownerMarker === 'absent' && gateway === 'absent') {
511
- state = 'absent';
512
- }
513
- else {
514
- state = 'ownership-conflict';
515
- }
516
- return Object.freeze({
517
- schemaVersion: 1,
518
- runtime: options.runtime,
519
- state,
520
- managed: state === 'ready' || state === 'managed-drift',
521
- runtimeHomeId,
522
- gatewayRelativePath: AOPS_AGENT_ASSETS_GATEWAY_RELATIVE_PATH,
523
- ownerMarkerRelativePath: 'skills/aops/.aops-gateway-owner.json',
524
- storeBinding: store.state,
525
- bindingProof,
526
- ownerMarker,
527
- ownerMarkerProof,
528
- gateway,
529
- ...(gatewayContentSha256 ? { gatewayContentSha256 } : {}),
530
- runtimeRootIdentityEvidence,
531
- reasons: Object.freeze([...new Set(reasons)]),
532
- });
533
- }
534
- export function inspectRuntimeGatewayBindings(options) {
535
- const inspect = (runtime) => inspectRuntimeGatewayBinding({
536
- assetRoot: options.assetRoot,
537
- runtime,
538
- runtimeHome: options.runtimeHomes[runtime],
539
- ...(options.expectedRuntimeRootIdentitySha256?.[runtime]
540
- ? { expectedRuntimeRootIdentitySha256: options.expectedRuntimeRootIdentitySha256[runtime] }
541
- : {}),
542
- ...(options.authority ? { authority: options.authority } : {}),
543
- });
544
- return Object.freeze({ codex: inspect('codex'), claude: inspect('claude') });
545
- }
@@ -1,50 +0,0 @@
1
- import { AgentAssetsError } from './envelope.js';
2
- const RUNTIME_DEFINITIONS = [
3
- { id: 'codex', label: 'Codex' },
4
- { id: 'claude', label: 'Claude' },
5
- ];
6
- export const AGENT_ASSET_RUNTIME_REGISTRY = Object.freeze(RUNTIME_DEFINITIONS.map((runtime) => Object.freeze({ ...runtime })));
7
- export const AGENT_ASSET_RUNTIME_IDS = Object.freeze(RUNTIME_DEFINITIONS.map((runtime) => runtime.id));
8
- function selectorError(message, input) {
9
- throw new AgentAssetsError('schema_incompatible', message, {
10
- nextActions: [
11
- `Use --target all or select registered runtimes: ${AGENT_ASSET_RUNTIME_IDS.join(', ')}.`,
12
- ],
13
- details: {
14
- input: input ?? null,
15
- registeredRuntimes: AGENT_ASSET_RUNTIME_IDS,
16
- selectors: ['all', '<runtime>', '<runtime>,<runtime>', 'repeat --target'],
17
- },
18
- });
19
- }
20
- export function resolveAgentAssetTargetSelection(input) {
21
- const values = input === undefined
22
- ? []
23
- : Array.isArray(input) ? [...input] : [input];
24
- if (values.length === 0) {
25
- return Object.freeze({ selector: 'all', runtimes: AGENT_ASSET_RUNTIME_IDS });
26
- }
27
- const tokens = values.flatMap((value) => String(value).split(',').map((token) => token.trim().toLowerCase()));
28
- if (tokens.some((token) => token.length === 0)) {
29
- selectorError('--target contains an empty runtime selector.', input);
30
- }
31
- if (tokens.includes('all')) {
32
- if (tokens.length !== 1)
33
- selectorError('--target all cannot be combined with another runtime selector.', input);
34
- return Object.freeze({ selector: 'all', runtimes: AGENT_ASSET_RUNTIME_IDS });
35
- }
36
- const registered = new Set(AGENT_ASSET_RUNTIME_IDS);
37
- const unknown = tokens.filter((token) => !registered.has(token));
38
- if (unknown.length > 0) {
39
- selectorError(`--target contains unregistered runtime selectors: ${[...new Set(unknown)].join(', ')}.`, input);
40
- }
41
- const selected = new Set(tokens);
42
- const runtimes = Object.freeze(AGENT_ASSET_RUNTIME_IDS.filter((runtime) => selected.has(runtime)));
43
- return Object.freeze({ selector: runtimes.join(','), runtimes });
44
- }
45
- export function collectAgentAssetTarget(value, previous) {
46
- return [...(previous ?? []), value];
47
- }
48
- export function selectAgentAssetRuntimeHomes(selection, homes) {
49
- return Object.freeze(Object.fromEntries(selection.runtimes.map((runtime) => [runtime, homes[runtime]])));
50
- }