@aopslabs/aops 0.3.31 → 0.3.33

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,1282 +1,111 @@
1
- import { createHash } from 'node:crypto';
2
- import { readFileSync } from 'node:fs';
3
- import path from 'node:path';
4
1
  import { Command } from 'commander';
5
- import { AgentAssetsError, agentAssetsFailure, agentAssetsSuccess, assertBoundedDiscoveryEnvelope, } from '../lib/agent-assets/envelope.js';
6
- import { resolveAgentAssetsMutationGuard } from '../lib/agent-assets/guards.js';
7
- import { discoverHostedSkills } from '../lib/agent-assets/hosted-discovery.js';
8
- import { inspectLegacyAopsPointers, LEGACY_POINTER_GENERATOR_CONTRACT_V1, migrateLegacyAopsPointers, removeAopsGatewayPointers, } from '../lib/agent-assets/legacy-pointer-migration.js';
9
- import { assertExpectedSkillPackageManifestV1, pullHostedSkillPackage, } from '../lib/agent-assets/hosted-package-input.js';
10
- import { validatePackageManifestStructureV1 } from '../lib/agent-assets/package-manifest.js';
11
- import { verifyAndLoadCommunityCoreReleaseInput } from '../lib/agent-assets/release-input.js';
12
- import { resolveAgentAssetsRoots } from '../lib/agent-assets/roots.js';
13
- import { inspectRuntimeGatewayBindings } from '../lib/agent-assets/runtime-binding-reader.js';
14
- import { readAgentAssetsStoreStatus, readAgentAssetsRollbackTarget, readAgentAssetsPrunePlan, readResolvedAgentAssetPackage, resolveAgentAsset, } from '../lib/agent-assets/store-reader.js';
15
- import { applyVerifiedCommunityCore, applyVerifiedHostedSkillPackage, cleanupAgentAssetsStaging, pinAgentAssetsExactVersion, pruneAgentAssets, repairAgentAssetRuntimeBindings, rollbackAgentAssets, } from '../lib/agent-assets/store-writer.js';
2
+ import path from 'node:path';
3
+ import { downloadSimpleAgentAssetsRelease, installSimpleAgentAssets, readSimpleAgentAssetsState, removeDownloadedSimpleAgentAssetsRelease, resolveSimpleAgentAssetsRoots, rollbackSimpleAgentAssets, } from '../lib/simple-agent-assets.js';
16
4
  import { resolveSetupAgentAssetsReleaseV1 } from '../lib/setup-agent-assets-release.js';
17
- import { collectAgentAssetTarget, resolveAgentAssetTargetSelection, selectAgentAssetRuntimeHomes, } from '../lib/agent-assets/runtime-targets.js';
18
- function stableRootId(kind, absolutePath) {
19
- const canonicalPath = process.platform === 'win32'
20
- ? path.normalize(absolutePath).toLowerCase()
21
- : path.normalize(absolutePath);
22
- return createHash('sha256').update(`agent-assets-${kind}\0${canonicalPath}`, 'utf8').digest('hex');
23
- }
24
- function rootContext(roots) {
25
- return Object.freeze({
26
- storeId: stableRootId('store', roots.assetRoot),
27
- runtimeHomeIds: Object.freeze({
28
- codex: stableRootId('codex', roots.runtimeHomes.codex.absolutePath),
29
- claude: stableRootId('claude', roots.runtimeHomes.claude.absolutePath),
30
- }),
31
- sources: Object.freeze({
32
- dataRoot: roots.dataRoot.source,
33
- codexHome: roots.runtimeHomes.codex.source,
34
- claudeHome: roots.runtimeHomes.claude.source,
35
- }),
5
+ function roots(options) {
6
+ return resolveSimpleAgentAssetsRoots({
7
+ dataRoot: options.dataRoot,
8
+ codexHome: options.codexHome,
9
+ claudeHome: options.claudeHome,
36
10
  });
37
11
  }
38
- function required(value, flag) {
39
- const normalized = value?.trim();
40
- if (!normalized) {
41
- throw new AgentAssetsError('schema_incompatible', `${flag} is required.`, {
42
- nextActions: [`Re-run the command with ${flag} <value>.`],
43
- });
12
+ function targets(values) {
13
+ if (!values?.length || values.includes('all')) {
14
+ if (values && values.length > 1)
15
+ throw new Error('aops_assets_target_all_must_be_used_alone');
16
+ return 'all';
44
17
  }
45
- return normalized;
46
- }
47
- function oneOf(value, flag, allowed, fallback) {
48
- const selected = value?.trim() || fallback;
49
- if (!selected || !allowed.includes(selected)) {
50
- throw new AgentAssetsError('schema_incompatible', `${flag} must be one of: ${allowed.join(', ')}.`, {
51
- nextActions: [`Re-run with ${flag} ${allowed[0]}.`],
52
- details: { allowed },
53
- });
18
+ const selected = [...new Set(values.flatMap((value) => value.split(',')).map((value) => value.trim().toLowerCase()))];
19
+ if (selected.some((value) => value !== 'codex' && value !== 'claude')) {
20
+ throw new Error('aops_assets_target_must_be_codex_claude_or_all');
54
21
  }
55
22
  return selected;
56
23
  }
57
- function positiveLimit(value) {
58
- const selected = value ?? 5;
59
- if (!Number.isInteger(selected) || selected < 1 || selected > 5) {
60
- throw new AgentAssetsError('schema_incompatible', '--limit must be an integer from 1 through 5.', {
61
- nextActions: ['Re-run with --limit 5 or lower.'],
62
- details: { minimum: 1, maximum: 5 },
63
- });
64
- }
65
- return selected;
66
- }
67
- function normalizeOptions(command, raw) {
68
- const options = { ...raw };
69
- if (options.preview && options.apply) {
70
- throw new AgentAssetsError('schema_incompatible', '--preview and --apply are mutually exclusive.', {
71
- nextActions: ['Choose preview (the default) or re-run with only --apply.'],
72
- });
73
- }
74
- switch (command) {
75
- case 'assets.status':
76
- options.verify = oneOf(options.verify, '--verify', ['quick', 'full'], 'quick');
77
- break;
78
- case 'assets.discover':
79
- options.query = required(options.query, '--query');
80
- options.limit = positiveLimit(options.limit);
81
- if (options.origin)
82
- options.origin = oneOf(options.origin, '--origin', ['bundled', 'hosted-cache', 'reserved-catalog']);
83
- break;
84
- case 'assets.resolve': {
85
- const selectors = [options.gateway, options.name, options.versionId].filter((entry) => Boolean(entry?.trim()));
86
- if (selectors.length !== 1) {
87
- throw new AgentAssetsError('ambiguous', 'Exactly one of --gateway, --name, or --version-id is required.', {
88
- nextActions: ['Re-run with exactly one resolver selector.'],
89
- });
90
- }
91
- if (options.gateway && options.gateway !== 'aops') {
92
- throw new AgentAssetsError('not_found', 'Only --gateway aops is supported in v1.', {
93
- nextActions: ['Re-run with --gateway aops or select an exact installed asset.'],
94
- });
95
- }
96
- if (Boolean(options.pinId) !== Boolean(options.pinUntil)) {
97
- throw new AgentAssetsError('schema_incompatible', '--pin-id and --pin-until must be supplied together.', {
98
- nextActions: ['Supply both pin flags, or omit both for mutation-free resolution.'],
99
- });
100
- }
101
- if (options.apply && !options.pinId) {
102
- throw new AgentAssetsError('schema_incompatible', '--apply is valid for resolve only when creating or renewing a pin.', {
103
- nextActions: ['Omit --apply, or provide both --pin-id and --pin-until.'],
104
- });
105
- }
106
- break;
107
- }
108
- case 'assets.install':
109
- case 'assets.update':
110
- case 'assets.uninstall':
111
- case 'assets.migrate.inspect':
112
- case 'assets.migrate.legacy-pointers':
113
- resolveAgentAssetTargetSelection(options.target);
114
- break;
115
- case 'assets.package.inspect':
116
- options.manifest = required(options.manifest, '--manifest');
117
- break;
118
- case 'assets.package.pull':
119
- options.versionId = required(options.versionId, '--version-id');
120
- options.expectedManifest = required(options.expectedManifest, '--expected-manifest');
121
- break;
122
- case 'assets.pin':
123
- options.versionId = required(options.versionId, '--version-id');
124
- options.leaseId = required(options.leaseId, '--lease-id');
125
- options.expiresAt = required(options.expiresAt, '--expires-at');
126
- if (!Number.isFinite(Date.parse(options.expiresAt))) {
127
- throw new AgentAssetsError('schema_incompatible', '--expires-at must be a valid ISO timestamp.', {
128
- nextActions: ['Re-run with an explicit finite ISO-8601 expiry.'],
129
- });
130
- }
131
- break;
132
- case 'assets.repair':
133
- resolveAgentAssetTargetSelection(options.target);
134
- if (options.target !== undefined && options.repairBindings !== true) {
135
- throw new AgentAssetsError('schema_incompatible', '--target is valid for repair only with --repair-bindings.', {
136
- nextActions: ['Add --repair-bindings or omit --target for non-runtime repair actions.'],
137
- });
138
- }
139
- if ([
140
- options.cleanupStaging,
141
- options.repairBindings,
142
- options.takeoverStaleLock,
143
- options.rebindMachine,
144
- ].filter(Boolean).length > 1) {
145
- throw new AgentAssetsError('ambiguous', 'Repair accepts at most one recovery action at a time.', {
146
- nextActions: ['Choose exactly one repair flag after inspecting status.'],
147
- });
148
- }
149
- break;
150
- default:
151
- break;
152
- }
153
- return Object.freeze(options);
154
- }
155
- function mutationGuard(command, options) {
156
- const mutations = new Set([
157
- 'assets.install',
158
- 'assets.update',
159
- 'assets.uninstall',
160
- 'assets.package.pull',
161
- 'assets.pin',
162
- 'assets.repair',
163
- 'assets.rollback',
164
- 'assets.prune',
165
- 'assets.migrate.legacy-pointers',
166
- ]);
167
- const resolvePin = command === 'assets.resolve' && Boolean(options.pinId);
168
- if (!mutations.has(command) && !resolvePin)
169
- return undefined;
170
- const destructive = command === 'assets.rollback'
171
- || command === 'assets.prune'
172
- || command === 'assets.uninstall'
173
- || command === 'assets.migrate.legacy-pointers'
174
- || (command === 'assets.repair' && Boolean(options.cleanupStaging || options.takeoverStaleLock || options.rebindMachine));
175
- return resolveAgentAssetsMutationGuard({
176
- action: `aops-cli ${command.replaceAll('.', ' ')}`,
177
- apply: options.apply,
178
- confirm: options.confirm,
179
- destructive,
180
- });
181
- }
182
- function readManifestReference(reference) {
183
- if (!reference.startsWith('@')) {
184
- throw new AgentAssetsError('expected_manifest_required', 'This build can inspect local @file.json manifests; immutable release-ref resolution is not wired yet.', { nextActions: ['Provide --manifest @/absolute/path/to/package-manifest.json.'] });
185
- }
186
- const filePath = path.resolve(reference.slice(1));
187
- let raw;
188
- try {
189
- raw = readFileSync(filePath, 'utf8');
190
- }
191
- catch (error) {
192
- throw new AgentAssetsError('not_found', 'The requested manifest file could not be read.', {
193
- nextActions: ['Verify the absolute @file.json path and file permissions.'],
194
- cause: error,
195
- });
196
- }
197
- if (Buffer.byteLength(raw, 'utf8') > 1_048_576) {
198
- throw new AgentAssetsError('schema_incompatible', 'Manifest input exceeds the 1 MiB inspection limit.', {
199
- nextActions: ['Inspect a bounded PackageManifestV1 JSON file.'],
200
- });
201
- }
202
- try {
203
- return JSON.parse(raw);
204
- }
205
- catch (error) {
206
- throw new AgentAssetsError('schema_incompatible', 'Manifest input is not valid JSON.', {
207
- nextActions: ['Fix the JSON syntax and retry package inspect.'],
208
- cause: error,
209
- });
210
- }
211
- }
212
- function unsupportedApply(request) {
213
- throw new AgentAssetsError('atomic_primitive_unavailable', `${request.command} apply is unavailable until the reviewed native agent-assets writer is installed.`, {
214
- nextActions: [
215
- 'Keep this preview as evidence and retry only after the native publication primitive is available.',
216
- ],
217
- details: { mutationFreeFallback: false },
218
- });
24
+ function collect(value, previous) {
25
+ return [...(previous ?? []), value];
219
26
  }
220
- export function createDefaultAgentAssetsCommandRunner(dependencies = {}) {
221
- const readStoreStatus = dependencies.readStoreStatus ?? readAgentAssetsStoreStatus;
222
- const inspectRuntimeBindings = dependencies.inspectRuntimeBindings ?? inspectRuntimeGatewayBindings;
223
- const pullHostedPackage = dependencies.pullHostedPackage ?? pullHostedSkillPackage;
224
- const readResolvedPackage = dependencies.readResolvedPackage ?? readResolvedAgentAssetPackage;
225
- const verifyCommunityRelease = dependencies.verifyCommunityRelease ?? verifyAndLoadCommunityCoreReleaseInput;
226
- const discoverHosted = dependencies.discoverHosted ?? discoverHostedSkills;
227
- const applyCommunityCore = dependencies.applyCommunityCore ?? applyVerifiedCommunityCore;
228
- const applyHostedPackage = dependencies.applyHostedPackage ?? applyVerifiedHostedSkillPackage;
229
- const repairRuntimeBindings = dependencies.repairRuntimeBindings ?? repairAgentAssetRuntimeBindings;
230
- const cleanupStaging = dependencies.cleanupStaging ?? cleanupAgentAssetsStaging;
231
- const rollback = dependencies.rollback ?? rollbackAgentAssets;
232
- const pinExactVersion = dependencies.pinExactVersion ?? pinAgentAssetsExactVersion;
233
- const prune = dependencies.prune ?? pruneAgentAssets;
234
- const inspectLegacyPointers = dependencies.inspectLegacyPointers ?? inspectLegacyAopsPointers;
235
- const migrateLegacyPointers = dependencies.migrateLegacyPointers ?? migrateLegacyAopsPointers;
236
- const removeGatewayPointers = dependencies.removeGatewayPointers ?? removeAopsGatewayPointers;
237
- const resolveRelease = dependencies.resolveRelease ?? resolveSetupAgentAssetsReleaseV1;
238
- return Object.freeze({
239
- async run(request) {
240
- const roots = rootContext(request.roots);
241
- switch (request.command) {
242
- case 'assets.status': {
243
- const store = readStoreStatus({
244
- assetRoot: request.roots.assetRoot,
245
- verify: request.options.verify === 'full' ? 'full' : 'quick',
246
- });
247
- const runtimeBindings = inspectRuntimeBindings({
248
- assetRoot: request.roots.assetRoot,
249
- runtimeHomes: {
250
- codex: request.roots.runtimeHomes.codex.absolutePath,
251
- claude: request.roots.runtimeHomes.claude.absolutePath,
252
- },
253
- });
254
- const diagnostics = [];
255
- if (store.authorityHistory?.state === 'incomplete') {
256
- diagnostics.push({
257
- code: 'authority_history_incomplete',
258
- message: 'The current authority is readable, but a referenced immutable history revision is missing.',
259
- details: { missingRevision: store.authorityHistory.missingRevision },
260
- });
261
- }
262
- if (store.nativeIdentityEvidence?.state === 'recorded-not-live-verified') {
263
- diagnostics.push({
264
- code: 'native_identity_recorded_only',
265
- message: 'Status reports signed/recorded native identity evidence; v1 has no mutation-free live native probe.',
266
- });
267
- }
268
- if ((store.recoveryReasons?.length ?? 0) > 0) {
269
- diagnostics.push({
270
- code: 'managed_recovery_state_detected',
271
- message: 'The active core remains readable, but authenticated managed staging or receipt drift requires reconciliation.',
272
- details: { recoveryReasons: store.recoveryReasons },
273
- });
274
- }
275
- return {
276
- result: {
277
- roots,
278
- store,
279
- runtimeBindings,
280
- mutationFree: true,
281
- },
282
- diagnostics,
283
- nextActions: (store.recoveryReasons?.length ?? 0) > 0
284
- ? ['Inspect this full status result and reconcile only the reported managed recovery state.']
285
- : [],
286
- };
287
- }
288
- case 'assets.discover':
289
- if (request.options.offline
290
- || (request.options.origin !== undefined && request.options.origin !== 'hosted-cache')) {
291
- return {
292
- result: {
293
- query: request.options.query,
294
- candidates: [],
295
- metadataOnly: true,
296
- networkUsed: false,
297
- },
298
- diagnostics: [{
299
- code: 'offline_core_only',
300
- message: 'Hosted discovery was not queried; resolve the installed AOPS gateway to enter the offline core.',
301
- }],
302
- };
303
- }
304
- {
305
- const discovery = await discoverHosted({
306
- query: required(request.options.query, '--query'),
307
- limit: request.options.limit ?? 5,
308
- apiBaseUrl: request.options.apiBaseUrl,
309
- });
310
- return {
311
- result: {
312
- query: discovery.query,
313
- normalizedQuery: discovery.normalizedQuery,
314
- candidates: discovery.candidates,
315
- metadataOnly: true,
316
- networkUsed: true,
317
- },
318
- diagnostics: [],
319
- nextActions: discovery.candidates.length === 0
320
- ? ['Refine the query or use `aops assets resolve --gateway aops --json` for the installed core.']
321
- : [],
322
- };
323
- }
324
- case 'assets.package.inspect': {
325
- const manifest = readManifestReference(required(request.options.manifest, '--manifest'));
326
- const validation = validatePackageManifestStructureV1(manifest);
327
- if (!validation.ok) {
328
- throw new AgentAssetsError('schema_incompatible', 'PackageManifestV1 validation failed.', {
329
- nextActions: ['Correct the reported structural issues before any package transfer or staging.'],
330
- details: { issues: validation.issues },
331
- });
332
- }
333
- return {
334
- result: {
335
- roots,
336
- valid: true,
337
- identity: {
338
- assetKind: validation.value.assetKind,
339
- name: validation.value.name,
340
- version: validation.value.version,
341
- versionId: validation.value.versionId,
342
- packageSha256: validation.value.packageSha256,
343
- },
344
- entryFile: validation.value.entryFile,
345
- fileCount: validation.value.files.length,
346
- files: validation.value.files,
347
- nativeAliasValidation: 'required-before-materialization',
348
- mutationFree: true,
349
- },
350
- };
351
- }
352
- case 'assets.package.pull': {
353
- const versionId = required(request.options.versionId, '--version-id');
354
- const expectedManifest = required(request.options.expectedManifest, '--expected-manifest');
355
- try {
356
- const cached = readResolvedPackage({
357
- assetRoot: request.roots.assetRoot,
358
- versionId,
359
- });
360
- assertExpectedSkillPackageManifestV1(expectedManifest, versionId, cached.manifest);
361
- if (request.guard?.mode === 'apply') {
362
- const applied = await applyHostedPackage({
363
- assetRoot: request.roots.assetRoot,
364
- manifest: cached.manifest,
365
- });
366
- return {
367
- result: {
368
- roots,
369
- mode: 'applied',
370
- mutationFree: false,
371
- cacheHit: true,
372
- idempotent: applied.idempotent,
373
- packageInstalled: applied.packageInstalled,
374
- identity: applied.packageRef,
375
- generation: applied.active.generation,
376
- receiptId: applied.receipt.receiptId,
377
- },
378
- diagnostics: [{
379
- code: applied.idempotent ? 'hosted_package_already_active' : 'hosted_package_activated_from_cache',
380
- message: 'The exact full-verified cached package is active in the authenticated receipt chain.',
381
- }],
382
- nextActions: ['Resolve the exact version with `aops assets resolve --version-id <id> --json`.'],
383
- };
384
- }
385
- return {
386
- result: {
387
- roots,
388
- mode: 'preview',
389
- mutationFree: true,
390
- cacheHit: true,
391
- ...cached.resolved,
392
- fileCount: cached.manifest.files.length,
393
- files: cached.manifest.files,
394
- },
395
- nextActions: request.guard?.nextActions ?? [],
396
- diagnostics: [{
397
- code: 'verified_cache_hit',
398
- message: 'The exact installed version passed full verification; no network request was made.',
399
- }],
400
- };
401
- }
402
- catch (error) {
403
- if (!(error instanceof AgentAssetsError) || error.code !== 'not_found')
404
- throw error;
405
- }
406
- const pulled = await pullHostedPackage({
407
- versionId,
408
- expectedManifest,
409
- apiBaseUrl: request.options.apiBaseUrl,
410
- });
411
- if (request.guard?.mode === 'apply') {
412
- const applied = await applyHostedPackage({
413
- assetRoot: request.roots.assetRoot,
414
- manifest: pulled.manifest,
415
- transferFiles: pulled.transferFiles,
416
- });
417
- return {
418
- result: {
419
- roots,
420
- mode: 'applied',
421
- mutationFree: false,
422
- cacheHit: false,
423
- idempotent: applied.idempotent,
424
- packageInstalled: applied.packageInstalled,
425
- identity: applied.packageRef,
426
- generation: applied.active.generation,
427
- receiptId: applied.receipt.receiptId,
428
- },
429
- diagnostics: [{
430
- code: applied.idempotent ? 'hosted_package_already_active' : 'hosted_package_pulled_and_activated',
431
- message: 'Hosted bytes matched immutable publish-time metadata and were activated through the native writer.',
432
- }],
433
- nextActions: ['Resolve the exact version with `aops assets resolve --version-id <id> --json`.'],
434
- };
435
- }
436
- return {
437
- result: {
438
- roots,
439
- mode: 'preview',
440
- mutationFree: true,
441
- identity: {
442
- name: pulled.manifest.name,
443
- version: pulled.manifest.version,
444
- versionId: pulled.manifest.versionId,
445
- packageSha256: pulled.manifest.packageSha256,
446
- origin: 'hosted-cache',
447
- trustClass: pulled.manifest.provenance.trustClass,
448
- },
449
- entryFile: pulled.manifest.entryFile,
450
- fileCount: pulled.manifest.files.length,
451
- files: pulled.manifest.files,
452
- nativeAliasValidation: pulled.validation.nativeAliasValidation,
453
- },
454
- nextActions: request.guard?.nextActions ?? [],
455
- diagnostics: [{
456
- code: 'verified_transfer_preview',
457
- message: 'Exact hosted bytes matched immutable publish-time metadata; no local store write was attempted.',
458
- }],
459
- };
460
- }
461
- case 'assets.install':
462
- case 'assets.update': {
463
- const releaseResolution = request.options.fromRelease
464
- ? Object.freeze({ fromRelease: request.options.fromRelease, source: 'explicit-override' })
465
- : await resolveRelease({});
466
- const release = await verifyCommunityRelease({
467
- releaseRoot: releaseResolution.fromRelease,
468
- verificationMode: 'offline',
469
- });
470
- const operation = request.command === 'assets.install' ? 'install' : 'update';
471
- const target = resolveAgentAssetTargetSelection(request.options.target);
472
- const runtimeHomes = selectAgentAssetRuntimeHomes(target, {
473
- codex: request.roots.runtimeHomes.codex.absolutePath,
474
- claude: request.roots.runtimeHomes.claude.absolutePath,
475
- });
476
- const classifications = inspectLegacyPointers({
477
- assetRoot: request.roots.assetRoot,
478
- runtimeHomes,
479
- });
480
- if (request.guard?.mode === 'apply') {
481
- const conflicts = classifications.filter((item) => (item.state !== 'absent'
482
- && item.state !== 'managed-ready'
483
- && item.state !== 'recognized-legacy') || (item.state === 'recognized-legacy' && !item.eligible));
484
- if (conflicts.length > 0) {
485
- throw new AgentAssetsError('binding_conflict', 'One or more selected global skill paths are unknown, unsafe, or owned by another installation.', {
486
- nextActions: [
487
- 'Run `aops assets migrate inspect --json` and reconcile only the reported conflicting paths.',
488
- 'Unknown and user-owned skill files are never overwritten.',
489
- ],
490
- details: {
491
- conflicts: conflicts.map((item) => ({ runtime: item.runtime, state: item.state, reasons: item.reasons })),
492
- },
493
- });
494
- }
495
- const legacyRuntimes = new Set(classifications
496
- .filter((item) => item.state === 'recognized-legacy')
497
- .map((item) => item.runtime));
498
- const directRuntimeHomes = Object.freeze(Object.fromEntries(target.runtimes
499
- .filter((runtime) => !legacyRuntimes.has(runtime))
500
- .map((runtime) => [runtime, runtimeHomes[runtime]])));
501
- const applied = await applyCommunityCore({
502
- assetRoot: request.roots.assetRoot,
503
- release,
504
- requestedOperation: operation,
505
- ...(request.options.idempotencyKey ? { idempotencyKey: request.options.idempotencyKey } : {}),
506
- runtimeHomes: directRuntimeHomes,
507
- });
508
- const migrated = legacyRuntimes.size > 0
509
- ? await migrateLegacyPointers({
510
- assetRoot: request.roots.assetRoot,
511
- runtimeHomes: Object.freeze(Object.fromEntries(target.runtimes
512
- .filter((runtime) => legacyRuntimes.has(runtime))
513
- .map((runtime) => [runtime, runtimeHomes[runtime]]))),
514
- })
515
- : undefined;
516
- const runtimeBindings = inspectRuntimeBindings({
517
- assetRoot: request.roots.assetRoot,
518
- runtimeHomes: {
519
- codex: request.roots.runtimeHomes.codex.absolutePath,
520
- claude: request.roots.runtimeHomes.claude.absolutePath,
521
- },
522
- });
523
- return {
524
- result: {
525
- roots,
526
- mode: 'applied',
527
- mutationFree: false,
528
- operation,
529
- target: target.selector,
530
- targets: target.runtimes,
531
- idempotent: applied.idempotent,
532
- packageInstalled: applied.packageInstalled,
533
- releaseSetSha256: release.releaseSetSha256,
534
- releaseSource: releaseResolution.source,
535
- identity: release.packageRef,
536
- store: {
537
- storeId: applied.authority.storeId,
538
- authorityRevision: applied.authority.authorityRevision,
539
- writerFenceEpoch: applied.authority.lastIssuedFenceEpoch,
540
- generation: applied.active.generation,
541
- receiptId: applied.receipt.receiptId,
542
- publicationCapability: applied.authority.publicationCapability,
543
- capabilityEvidenceSha256: applied.authority.capabilityEvidenceSha256,
544
- },
545
- runtimeBindings,
546
- legacyPointersMigrated: migrated?.migrated ?? [],
547
- },
548
- diagnostics: [{
549
- code: migrated?.migrated.length
550
- ? 'verified_install_and_legacy_migration_applied'
551
- : applied.idempotent ? 'verified_install_idempotent' : 'verified_install_applied',
552
- message: migrated?.migrated.length
553
- ? 'The verified core was installed before exact recognized legacy pointers were migrated to stable gateways.'
554
- : applied.idempotent
555
- ? 'The exact verified core and selected runtime gateways were already ready.'
556
- : 'The verified core and selected runtime gateways were published through the native writer.',
557
- }],
558
- nextActions: ['Run `aops assets status --verify full --json` to inspect the exact active chain.'],
559
- };
560
- }
561
- return {
562
- result: {
563
- roots,
564
- mode: 'preview',
565
- mutationFree: true,
566
- operation,
567
- target: target.selector,
568
- targets: target.runtimes,
569
- releaseSetSha256: release.releaseSetSha256,
570
- releaseSource: releaseResolution.source,
571
- identity: release.packageRef,
572
- entryFile: release.manifest.entryFile,
573
- fileCount: release.manifest.files.length,
574
- files: release.manifest.files,
575
- nativeAliasValidation: release.validation.nativeAliasValidation,
576
- legacyPointerClassifications: classifications,
577
- },
578
- nextActions: request.guard?.nextActions ?? [],
579
- diagnostics: [{
580
- code: 'verified_release_preview',
581
- message: 'The signed Community release and exact client core bytes passed verification; no local write was attempted.',
582
- }],
583
- };
584
- }
585
- case 'assets.migrate.inspect': {
586
- const target = resolveAgentAssetTargetSelection(request.options.target);
587
- const classifications = inspectLegacyPointers({
588
- assetRoot: request.roots.assetRoot,
589
- runtimeHomes: selectAgentAssetRuntimeHomes(target, {
590
- codex: request.roots.runtimeHomes.codex.absolutePath,
591
- claude: request.roots.runtimeHomes.claude.absolutePath,
592
- }),
593
- });
594
- return {
595
- result: {
596
- roots,
597
- target: target.selector,
598
- targets: target.runtimes,
599
- classifications,
600
- generatorContract: LEGACY_POINTER_GENERATOR_CONTRACT_V1,
601
- mutationFree: true,
602
- },
603
- diagnostics: classifications.some((entry) => entry.state === 'unknown-user-owned')
604
- ? [{
605
- code: 'legacy_pointer_user_file_preserved',
606
- message: 'One or more runtime files are unknown/user-owned and are not eligible for migration.',
607
- }]
608
- : [],
609
- };
610
- }
611
- case 'assets.uninstall': {
612
- const target = resolveAgentAssetTargetSelection(request.options.target);
613
- const runtimeHomes = selectAgentAssetRuntimeHomes(target, {
614
- codex: request.roots.runtimeHomes.codex.absolutePath,
615
- claude: request.roots.runtimeHomes.claude.absolutePath,
616
- });
617
- if (request.guard?.mode === 'apply') {
618
- const removed = removeGatewayPointers({ assetRoot: request.roots.assetRoot, runtimeHomes });
619
- return {
620
- result: {
621
- roots,
622
- mode: 'applied',
623
- mutationFree: false,
624
- target: target.selector,
625
- targets: target.runtimes,
626
- removed: removed.removed,
627
- unchanged: removed.unchanged,
628
- retainedManagedBindings: removed.retainedManagedBindings,
629
- verifiedCoreRetained: true,
630
- classifications: removed.classifications,
631
- },
632
- diagnostics: [{
633
- code: removed.removed.length > 0 ? 'gateway_pointers_removed' : 'gateway_pointers_already_absent',
634
- message: removed.removed.length > 0
635
- ? 'Only exact recognized AOPS gateway pointers were removed; the verified core and receipts were retained.'
636
- : 'The selected global AOPS gateway pointers were already absent.',
637
- }],
638
- nextActions: removed.retainedManagedBindings.length > 0
639
- ? ['Run `aops assets repair --repair-bindings --apply --json` to restore these managed pointers later.']
640
- : [],
641
- };
642
- }
643
- const classifications = inspectLegacyPointers({
644
- assetRoot: request.roots.assetRoot,
645
- runtimeHomes,
646
- });
647
- return {
648
- result: {
649
- roots,
650
- mode: 'preview',
651
- mutationFree: true,
652
- target: target.selector,
653
- targets: target.runtimes,
654
- classifications,
655
- verifiedCoreRetained: true,
656
- },
657
- diagnostics: [{
658
- code: 'gateway_pointer_removal_preview',
659
- message: 'Preview only; unknown, unsafe, and user-owned files are never removed.',
660
- }],
661
- nextActions: request.guard?.nextActions ?? [],
662
- };
663
- }
664
- case 'assets.migrate.legacy-pointers': {
665
- const target = resolveAgentAssetTargetSelection(request.options.target);
666
- const runtimeHomes = selectAgentAssetRuntimeHomes(target, {
667
- codex: request.roots.runtimeHomes.codex.absolutePath,
668
- claude: request.roots.runtimeHomes.claude.absolutePath,
669
- });
670
- if (request.guard?.mode === 'apply') {
671
- const migrated = await migrateLegacyPointers({
672
- assetRoot: request.roots.assetRoot,
673
- runtimeHomes,
674
- });
675
- return {
676
- result: {
677
- roots,
678
- mode: 'applied',
679
- mutationFree: false,
680
- target: target.selector,
681
- targets: target.runtimes,
682
- idempotent: migrated.idempotent,
683
- migrated: migrated.migrated,
684
- unchanged: migrated.unchanged,
685
- store: {
686
- storeId: migrated.authority.storeId,
687
- authorityRevision: migrated.authority.authorityRevision,
688
- writerFenceEpoch: migrated.authority.lastIssuedFenceEpoch,
689
- generation: migrated.active.generation,
690
- receiptId: migrated.receipt.receiptId,
691
- },
692
- classifications: migrated.classifications,
693
- },
694
- diagnostics: [{
695
- code: migrated.idempotent ? 'legacy_pointers_already_migrated' : 'legacy_pointers_migrated',
696
- message: migrated.idempotent
697
- ? 'Selected runtimes had no recognized legacy pointer requiring migration.'
698
- : 'Only exact recognized legacy AOPS pointers were replaced through the native writer.',
699
- }],
700
- nextActions: ['Run `aops assets status --verify full --json` to verify the stable gateway bindings.'],
701
- };
702
- }
703
- const classifications = inspectLegacyPointers({
704
- assetRoot: request.roots.assetRoot,
705
- runtimeHomes,
706
- });
707
- return {
708
- result: {
709
- roots,
710
- mode: 'preview',
711
- mutationFree: true,
712
- target: target.selector,
713
- targets: target.runtimes,
714
- classifications,
715
- },
716
- diagnostics: [{
717
- code: 'legacy_pointer_migration_preview',
718
- message: 'Preview only; exact recognized pointers are eligible and unknown/user-owned files remain untouched.',
719
- }],
720
- nextActions: request.guard?.nextActions ?? [],
721
- };
722
- }
723
- case 'assets.repair':
724
- if (request.guard?.mode === 'apply') {
725
- if (request.options.cleanupStaging === true) {
726
- const cleaned = await cleanupStaging({ assetRoot: request.roots.assetRoot });
727
- return {
728
- result: {
729
- roots,
730
- mode: 'applied',
731
- mutationFree: false,
732
- action: 'cleanup-staging',
733
- idempotent: cleaned.idempotent,
734
- removedManagedPaths: cleaned.removedManagedPaths,
735
- store: {
736
- storeId: cleaned.authority.storeId,
737
- authorityRevision: cleaned.authority.authorityRevision,
738
- writerFenceEpoch: cleaned.authority.lastIssuedFenceEpoch,
739
- generation: cleaned.active?.generation ?? null,
740
- receiptId: cleaned.receipt?.receiptId ?? null,
741
- },
742
- },
743
- diagnostics: [{
744
- code: cleaned.idempotent ? 'staging_cleanup_not_required' : 'staging_cleanup_applied',
745
- message: cleaned.idempotent
746
- ? 'No provably managed incomplete staging required cleanup.'
747
- : 'Only fully preflighted writer-owned staging trees were removed through the native writer.',
748
- }],
749
- nextActions: ['Run `aops assets status --verify full --json` to verify that staging drift is clear.'],
750
- };
751
- }
752
- if (request.options.repairBindings !== true
753
- || request.options.takeoverStaleLock
754
- || request.options.rebindMachine) {
755
- unsupportedApply(request);
756
- }
757
- const target = resolveAgentAssetTargetSelection(request.options.target);
758
- const repaired = await repairRuntimeBindings({
759
- assetRoot: request.roots.assetRoot,
760
- runtimeHomes: selectAgentAssetRuntimeHomes(target, {
761
- codex: request.roots.runtimeHomes.codex.absolutePath,
762
- claude: request.roots.runtimeHomes.claude.absolutePath,
763
- }),
764
- });
765
- return {
766
- result: {
767
- roots,
768
- mode: 'applied',
769
- mutationFree: false,
770
- action: 'repair-bindings',
771
- target: target.selector,
772
- targets: target.runtimes,
773
- idempotent: repaired.idempotent,
774
- store: {
775
- storeId: repaired.authority.storeId,
776
- authorityRevision: repaired.authority.authorityRevision,
777
- writerFenceEpoch: repaired.authority.lastIssuedFenceEpoch,
778
- generation: repaired.active.generation,
779
- receiptId: repaired.receipt.receiptId,
780
- },
781
- runtimeBindings: repaired.bindings,
782
- },
783
- diagnostics: [{
784
- code: repaired.idempotent ? 'runtime_bindings_already_ready' : 'runtime_bindings_repaired',
785
- message: repaired.idempotent
786
- ? 'The selected registered runtime gateway bindings were already ready.'
787
- : 'The selected registered runtime gateway bindings were repaired through the native writer.',
788
- }],
789
- nextActions: ['Run `aops assets status --verify full --json` to inspect the exact binding chain.'],
790
- };
791
- }
792
- const previewTarget = request.options.repairBindings
793
- ? resolveAgentAssetTargetSelection(request.options.target)
794
- : undefined;
795
- return {
796
- result: {
797
- roots,
798
- mode: 'preview',
799
- mutationFree: true,
800
- action: request.options.cleanupStaging
801
- ? 'cleanup-staging'
802
- : request.options.repairBindings
803
- ? 'repair-bindings'
804
- : 'inspect-repair-options',
805
- ...(previewTarget ? { target: previewTarget.selector, targets: previewTarget.runtimes } : {}),
806
- },
807
- nextActions: request.guard?.nextActions ?? [],
808
- diagnostics: [{
809
- code: request.options.cleanupStaging ? 'staging_cleanup_preview' : 'runtime_binding_repair_preview',
810
- message: request.options.cleanupStaging
811
- ? 'Preview only; no managed staging or store state was changed.'
812
- : 'Preview only; no runtime binding or store state was changed.',
813
- }],
814
- };
815
- case 'assets.rollback': {
816
- if (request.guard?.mode === 'apply') {
817
- const applied = await rollback({
818
- assetRoot: request.roots.assetRoot,
819
- ...(request.options.toReceipt ? { toReceiptId: request.options.toReceipt } : {}),
820
- ...(request.options.idempotencyKey ? { idempotencyKey: request.options.idempotencyKey } : {}),
821
- });
822
- return {
823
- result: {
824
- roots,
825
- mode: 'applied',
826
- mutationFree: false,
827
- idempotent: applied.idempotent,
828
- rolledBackToReceiptId: applied.rolledBackToReceiptId,
829
- store: {
830
- storeId: applied.authority.storeId,
831
- authorityRevision: applied.authority.authorityRevision,
832
- writerFenceEpoch: applied.authority.lastIssuedFenceEpoch,
833
- generation: applied.active.generation,
834
- receiptId: applied.receipt.receiptId,
835
- },
836
- },
837
- diagnostics: [{
838
- code: applied.idempotent ? 'rollback_idempotent' : 'rollback_applied',
839
- message: applied.idempotent
840
- ? 'The requested rollback operation was already active.'
841
- : 'A new activation receipt selected the prior verified package set.',
842
- }],
843
- nextActions: ['Run `aops assets status --verify full --json` to verify protected current and previous packages.'],
844
- };
845
- }
846
- const target = readAgentAssetsRollbackTarget({
847
- assetRoot: request.roots.assetRoot,
848
- ...(request.options.toReceipt ? { receiptId: request.options.toReceipt } : {}),
849
- });
850
- return {
851
- result: {
852
- roots,
853
- mode: 'preview',
854
- mutationFree: true,
855
- currentReceiptId: target.current.receiptId,
856
- targetReceiptId: target.target.receiptId,
857
- targetGeneration: target.target.generation,
858
- targetCore: target.target.core,
859
- targetAssetCount: target.target.assets.length,
860
- },
861
- nextActions: request.guard?.nextActions ?? [],
862
- diagnostics: [{
863
- code: 'verified_rollback_preview',
864
- message: 'The rollback target is in the active authenticated receipt lineage and its packages passed full verification.',
865
- }],
866
- };
867
- }
868
- case 'assets.pin': {
869
- const versionId = required(request.options.versionId, '--version-id');
870
- const resolved = readResolvedPackage({ assetRoot: request.roots.assetRoot, versionId });
871
- if (request.guard?.mode === 'apply') {
872
- const applied = await pinExactVersion({
873
- assetRoot: request.roots.assetRoot,
874
- versionId,
875
- leaseId: required(request.options.leaseId, '--lease-id'),
876
- expiresAt: required(request.options.expiresAt, '--expires-at'),
877
- });
878
- return {
879
- result: {
880
- roots,
881
- mode: 'applied',
882
- mutationFree: false,
883
- idempotent: applied.idempotent,
884
- pin: applied.pin,
885
- maintenanceReceiptId: applied.maintenanceReceipt?.receiptId ?? null,
886
- },
887
- diagnostics: [{
888
- code: applied.idempotent ? 'pin_already_current' : 'pin_applied',
889
- message: applied.idempotent
890
- ? 'The exact immutable package already has the requested lease and expiry.'
891
- : 'The exact immutable package pin and maintenance receipt were published through the native writer.',
892
- }],
893
- nextActions: ['Run `aops assets status --verify full --json` to verify the protected package set.'],
894
- };
895
- }
896
- return {
897
- result: {
898
- roots,
899
- mode: 'preview',
900
- mutationFree: true,
901
- identity: resolved.resolved,
902
- leaseId: request.options.leaseId,
903
- expiresAt: request.options.expiresAt,
904
- },
905
- nextActions: request.guard?.nextActions ?? [],
906
- diagnostics: [{ code: 'verified_pin_preview', message: 'The exact installed package passed full verification; no pin was written.' }],
907
- };
908
- }
909
- case 'assets.prune': {
910
- if (request.guard?.mode === 'apply') {
911
- const applied = await prune({ assetRoot: request.roots.assetRoot });
912
- return {
913
- result: {
914
- roots,
915
- mode: 'applied',
916
- mutationFree: false,
917
- idempotent: applied.idempotent,
918
- protectedPackageSha256s: applied.protectedPackageSha256s,
919
- removedPackageSha256s: applied.removedPackageSha256s,
920
- maintenanceReceiptId: applied.maintenanceReceipt?.receiptId ?? null,
921
- },
922
- diagnostics: [{
923
- code: applied.idempotent ? 'prune_not_required' : 'prune_applied',
924
- message: applied.idempotent
925
- ? 'No unprotected managed immutable package required removal.'
926
- : 'Only full-verified unprotected immutable packages were removed through the native writer.',
927
- }],
928
- nextActions: ['Run `aops assets status --verify full --json` to verify the protected package set.'],
929
- };
930
- }
931
- const plan = readAgentAssetsPrunePlan({ assetRoot: request.roots.assetRoot });
932
- return {
933
- result: {
934
- roots,
935
- mode: 'preview',
936
- mutationFree: true,
937
- protectedPackageSha256s: plan.protectedPackageSha256s,
938
- removablePackageSha256s: plan.removablePackageSha256s,
939
- removableManagedPaths: plan.removableManagedPaths,
940
- },
941
- diagnostics: [{
942
- code: 'verified_prune_preview',
943
- message: 'All managed immutable core directories were full-verified; no path was removed.',
944
- }],
945
- nextActions: request.guard?.nextActions ?? [],
946
- };
947
- }
948
- case 'assets.resolve': {
949
- const selector = {
950
- ...(request.options.gateway === 'aops' ? { gateway: 'aops' } : {}),
951
- ...(request.options.name ? { name: request.options.name } : {}),
952
- ...(request.options.versionId ? { versionId: request.options.versionId } : {}),
953
- };
954
- if (request.options.pinId && request.options.pinUntil) {
955
- const resolved = resolveAgentAsset({ assetRoot: request.roots.assetRoot, ...selector });
956
- if (request.guard?.mode === 'apply') {
957
- const applied = await pinExactVersion({
958
- assetRoot: request.roots.assetRoot,
959
- versionId: resolved.versionId,
960
- leaseId: request.options.pinId,
961
- expiresAt: request.options.pinUntil,
962
- });
963
- return {
964
- result: { ...resolveAgentAsset({ assetRoot: request.roots.assetRoot, versionId: resolved.versionId }), pin: applied.pin },
965
- diagnostics: [{ code: applied.idempotent ? 'pin_already_current' : 'pin_applied', message: 'Exact resolution is protected by the requested finite pin.' }],
966
- nextActions: [],
967
- };
968
- }
969
- return {
970
- result: { roots, mode: 'preview', mutationFree: true, selector, resolved },
971
- nextActions: request.guard?.nextActions ?? [],
972
- };
973
- }
974
- if (request.guard?.mode === 'preview') {
975
- return {
976
- result: { roots, mode: 'preview', mutationFree: true, selector },
977
- nextActions: request.guard.nextActions,
978
- };
979
- }
980
- return {
981
- result: resolveAgentAsset({ assetRoot: request.roots.assetRoot, ...selector }),
982
- diagnostics: [],
983
- nextActions: [],
984
- };
985
- }
986
- default:
987
- if (request.guard?.mode === 'apply')
988
- unsupportedApply(request);
989
- return {
990
- result: {
991
- roots,
992
- mode: 'preview',
993
- mutationFree: true,
994
- plannedCommand: request.command,
995
- },
996
- nextActions: request.guard?.nextActions ?? [],
997
- diagnostics: [{
998
- code: 'native_writer_not_loaded',
999
- message: 'Preview is available; no store or runtime mutation was attempted.',
1000
- }],
1001
- };
1002
- }
1003
- },
1004
- });
1005
- }
1006
- export const defaultAgentAssetsCommandRunner = createDefaultAgentAssetsCommandRunner();
1007
- function printEnvelope(envelope) {
1008
- console.log(JSON.stringify(envelope, null, 2));
1009
- }
1010
- export async function runAgentAssetsCommand(command, rawOptions, runner = defaultAgentAssetsCommandRunner) {
1011
- try {
1012
- const options = normalizeOptions(command, rawOptions);
1013
- const roots = resolveAgentAssetsRoots(options);
1014
- const guard = mutationGuard(command, options);
1015
- const output = await runner.run({ command, options, roots, ...(guard ? { guard } : {}) });
1016
- const envelope = agentAssetsSuccess({
1017
- command,
1018
- result: output.result,
1019
- diagnostics: output.diagnostics,
1020
- nextActions: output.nextActions,
1021
- });
1022
- if (command === 'assets.discover') {
1023
- const result = output.result;
1024
- assertBoundedDiscoveryEnvelope(envelope, Array.isArray(result.candidates) ? result.candidates.length : 0);
1025
- }
1026
- printEnvelope(envelope);
1027
- return envelope;
1028
- }
1029
- catch (error) {
1030
- const envelope = agentAssetsFailure(command, error);
1031
- process.exitCode = 1;
1032
- printEnvelope(envelope);
1033
- return envelope;
27
+ function print(value, json) {
28
+ if (json) {
29
+ process.stdout.write(`${JSON.stringify({ ok: true, result: value })}\n`);
30
+ return;
1034
31
  }
32
+ const result = value;
33
+ if (typeof result.version === 'string')
34
+ process.stdout.write(`AOPS assets ${result.version} ready.\n`);
35
+ else
36
+ process.stdout.write(`${JSON.stringify(value, null, 2)}\n`);
1035
37
  }
1036
- function parseInteger(value) {
1037
- return Number.parseInt(value, 10);
1038
- }
1039
- function addSharedSelectors(command) {
1040
- return command
1041
- .option('--data-root <path>', 'AOPS data-root containing agent-assets')
1042
- .option('--codex-home <path>', 'Codex runtime-home override')
1043
- .option('--claude-home <path>', 'Claude runtime-home override');
1044
- }
1045
- function addTargetSelector(command) {
1046
- return command.option('--target <runtime>', 'Registered runtime; repeat or comma-separate values, or use all (default: all)', collectAgentAssetTarget);
1047
- }
1048
- function addPreviewApply(command, applyDescription) {
38
+ function addRootOptions(command) {
1049
39
  return command
1050
- .option('--preview', 'Explicit preview alias; preview is the default')
1051
- .option('--apply', applyDescription);
1052
- }
1053
- function action(commandName, runner) {
1054
- return async (options) => {
1055
- await runAgentAssetsCommand(commandName, options, runner);
1056
- };
1057
- }
1058
- function makePackageCommand(runner) {
1059
- const command = new Command('package').description('Inspect or pull one exact package');
1060
- addSharedSelectors(command.command('inspect')
1061
- .description('Validate one exact PackageManifestV1 without writing')
1062
- .option('--manifest <ref>', 'Local @file.json PackageManifestV1')
1063
- .option('--json', 'Validation result, identity, file count, and digests'))
1064
- .addHelpText('after', `
1065
- Notes:
1066
- Inspect is read-only and does not trust a post-download self-hash as origin.
1067
- `)
1068
- .action(action('assets.package.inspect', runner));
1069
- addSharedSelectors(addPreviewApply(command.command('pull')
1070
- .description('Transfer and verify one exact hosted skill package')
1071
- .option('--version-id <id>', 'Exact hosted SkillVersion id')
1072
- .option('--expected-manifest <ref>', 'Required @file.json or immutable release ref')
1073
- .option('--api-base-url <url>', 'AOPS server URL; auth comes from the secure target store or environment')
1074
- .option('--idempotency-key <key>', 'Optional local operation key')
1075
- .option('--json', 'Stable common envelope'), 'Transfer, verify, and install immutable bytes'))
1076
- .addHelpText('after', `
1077
- Required discovery step for raw invoke debugging:
1078
- aops-cli agent schema --tool agentspace.skill-version.export-skill-package
1079
-
1080
- Notes:
1081
- The client transfers files[].content; server-local paths are rejected.
1082
- Authentication comes from the secure target store or environment; secrets
1083
- are never accepted on argv. The sugar uses the Agent Gateway and never calls
1084
- Agentspace storage directly.
1085
- `)
1086
- .action(action('assets.package.pull', runner));
1087
- return command;
1088
- }
1089
- function makeMigrateCommand(runner) {
1090
- const command = new Command('migrate').description('Inspect or explicitly migrate recognized legacy pointers');
1091
- addSharedSelectors(addTargetSelector(command.command('inspect')
1092
- .description('Classify recognized legacy pointers without changing them')
1093
- .option('--json', 'Stable common envelope')))
1094
- .action(action('assets.migrate.inspect', runner));
1095
- addSharedSelectors(addTargetSelector(command.command('legacy-pointers')
1096
- .description('Migrate exact recognized AOPS-generated pointer templates')
1097
- .option('--apply', 'Apply exact-template managed migration')
1098
- .option('--confirm', 'Confirm runtime-file ownership transition')
1099
- .option('--json', 'Stable common envelope')))
1100
- .addHelpText('after', `
1101
- Notes:
1102
- Only recognized AOPS-generated templates are eligible.
1103
- Unknown/user-owned pointers remain untouched.
1104
- `)
1105
- .action(action('assets.migrate.legacy-pointers', runner));
40
+ .option('--data-root <path>', 'AOPS data root (default: ~/.aops)')
41
+ .option('--codex-home <path>', 'Codex home (default: ~/.codex)')
42
+ .option('--claude-home <path>', 'Claude home (default: ~/.claude)')
43
+ .option('--json', 'Emit JSON');
44
+ }
45
+ function addMutationOptions(command) {
46
+ addRootOptions(command)
47
+ .option('--from-release <path>', 'Use a local aops-assets release directory')
48
+ .option('--target <runtime>', 'codex, claude, or all; repeatable', collect);
1106
49
  return command;
1107
50
  }
1108
- export function makeAssetsCommand(runner = defaultAgentAssetsCommandRunner) {
51
+ export function makeAssetsCommand() {
1109
52
  const command = new Command('assets')
1110
- .description(`Install, inspect, update, repair, remove pointers, and roll back verified AOPS client assets in
1111
- the user-local agent-assets store. This family does not choose a working method
1112
- and does not treat repository mirrors as installation truth.`)
1113
- .addHelpText('after', `
1114
- Safety:
1115
- Read-only commands never mutate the store.
1116
- Mutations preview by default and require --apply.
1117
- Destructive takeover, rebind, rollback, prune, and migration require
1118
- --apply --confirm.
1119
-
1120
- Shared selectors (available on every subcommand):
1121
- --data-root <path> AOPS data-root containing agent-assets
1122
- --codex-home <path> Codex runtime-home override
1123
- --claude-home <path> Claude runtime-home override
1124
-
1125
- Selector precedence:
1126
- explicit CLI option
1127
- > AOPS_AGENT_ASSETS_DATA_ROOT / CODEX_HOME / CLAUDE_HOME
1128
- > user aops.config.json agentAssets.dataRoot /
1129
- agentAssets.runtimeHomes.codex / agentAssets.runtimeHomes.claude
1130
- > ~/.aops / ~/.codex / ~/.claude defaults.
1131
-
1132
- All resolved roots must be absolute. Every JSON envelope reports non-secret
1133
- storeId/runtimeHomeId values. Commands that do not bind a runtime accept the
1134
- shared selectors for deterministic context but perform no runtime write.
1135
-
1136
- Canonical guide:
1137
- aops assets --help
1138
- aops-cli agent schema --tool <domain>.<operation> for raw hosted payloads
1139
- `);
1140
- addSharedSelectors(command.command('status')
1141
- .description('Inspect active state, runtime bindings, staging, and drift')
1142
- .option('--verify <mode>', 'Verification depth: quick | full (default: quick)', 'quick')
1143
- .option('--json', 'Stable agent-assets-client-v1 JSON envelope'))
1144
- .addHelpText('after', `
1145
- Notes:
1146
- quick validates schemas, receipt links, immutable binding proofs, ownership
1147
- markers, referenced paths, and every available authority-history revision.
1148
- full rehashes every active/previous/pinned immutable package file.
1149
- Both report recorded publicationCapability, capabilityEvidenceSha256,
1150
- authority-history coverage, native root/machine identity, and the
1151
- maintenance-receipt chain head. V1 status has no read-only live native probe;
1152
- mutation commands requalify the current machine, root, filesystem, helper,
1153
- and Windows crash-injection evidence before writing.
1154
- status never repairs, downloads, syncs, or rewrites runtime bindings.
1155
- `)
1156
- .action(action('assets.status', runner));
1157
- addSharedSelectors(command.command('discover')
1158
- .description('Return bounded metadata candidates without body loading')
1159
- .option('--query <text>', 'Intent, domain, CLI family, alias, or exact asset name')
1160
- .option('--limit <n>', 'Candidate limit, 1..5 (default: 5)', parseInteger, 5)
1161
- .option('--origin <origin>', 'bundled | hosted-cache | reserved-catalog')
1162
- .option('--offline', 'Do not query configured AOPS servers')
1163
- .option('--api-base-url <url>', 'Optional AOPS server for hosted metadata discovery')
1164
- .option('--json', 'Stable bounded JSON envelope'))
1165
- .addHelpText('after', `
1166
- Contract:
1167
- Before body load the complete result is <=2 KiB and contains <=5 candidates.
1168
- Results use approved raw metadata only and include matchedBy/rationale.
1169
- `)
1170
- .action(action('assets.discover', runner));
1171
- addSharedSelectors(command.command('resolve')
1172
- .description('Resolve one exact verified local entry')
1173
- .option('--gateway <name>', 'Stable runtime gateway identity; v1 supports aops')
1174
- .option('--name <name>', 'Exact asset name/current installed selection')
1175
- .option('--version-id <id>', 'Exact immutable installed version')
1176
- .option('--offline', 'Never use network discovery/package transfer')
1177
- .option('--pin-id <id>', 'Pin an exact historical version before returning it')
1178
- .option('--pin-until <iso>', 'Required with --pin-id')
1179
- .option('--apply', 'Required only when creating/renewing a pin')
1180
- .option('--json', 'ResolverEnvelopeV1 in the common command envelope'))
1181
- .addHelpText('after', `
1182
- Notes:
1183
- Exactly one of --gateway, --name, or --version-id is required.
1184
- --gateway aops resolves only the active signed client core.
1185
- Repository .aops mirrors are never implicit candidates.
1186
- Historical exact resolution requires an active/previous reference or pin.
1187
- `)
1188
- .action(action('assets.resolve', runner));
1189
- for (const [name, description, applyDescription] of [
1190
- ['install', 'Install the signed client core bundled with the official npm CLI', 'Apply verified local writes'],
1191
- ['update', 'Activate the verified client assets bundled with the official npm CLI', 'Activate the verified update'],
1192
- ]) {
1193
- addSharedSelectors(addPreviewApply(addTargetSelector(command.command(name)
1194
- .description(description)
1195
- .option('--from-release <path>', 'Advanced offline/maintainer override for the signed asset release root')
1196
- .option('--idempotency-key <key>', 'Optional replay/conflict key')
1197
- .option('--json', 'Stable common envelope')), applyDescription))
1198
- .addHelpText('after', name === 'install' ? `
1199
- Notes:
1200
- Install uses the verified Gateway assets bundled with the official npm CLI.
1201
- --from-release is an explicit offline/maintainer override, not a normal user requirement.
1202
- Signed expected digests are verified before activation.
1203
- It refuses unowned runtime files and never scans a repository for core bytes.
1204
- ` : `
1205
- Notes:
1206
- Update installs side-by-side immutable content and appends a receipt.
1207
- It never mutates the stable gateway merely because a package digest changed.
1208
- `)
1209
- .action(action(`assets.${name}`, runner));
1210
- }
1211
- command.addCommand(makePackageCommand(runner));
1212
- addSharedSelectors(addPreviewApply(command.command('pin')
1213
- .description('Protect one exact package until an explicit expiry')
1214
- .option('--version-id <id>', 'Exact installed immutable version')
1215
- .option('--lease-id <id>', 'Stable caller/session lease identity')
1216
- .option('--expires-at <iso>', 'Explicit finite expiry')
1217
- .option('--json', 'Stable common envelope'), 'Create or renew the exact-version pin'))
1218
- .addHelpText('after', `
1219
- Notes:
1220
- Pin and prune serialize through the same writer lease.
1221
- Applied pin/renewal appends MaintenanceReceiptV1 with authority revision and
1222
- fence epoch; an unrecorded mutation is not reported as applied.
1223
- V1 creates no permanent implicit pin.
1224
- `)
1225
- .action(action('assets.pin', runner));
1226
- addSharedSelectors(addPreviewApply(addTargetSelector(command.command('repair')
1227
- .description('Diagnose or repair managed incomplete/drifted state')
1228
- .option('--cleanup-staging', 'Remove only provably incomplete managed staging')
1229
- .option('--repair-bindings', 'Restore modified/missing AOPS-managed gateways')
1230
- .option('--takeover-stale-lock', 'Reserved in v1; apply fails closed')
1231
- .option('--rebind-machine', 'Reserved in v1; apply fails closed')
1232
- .option('--confirm', 'Required for takeover/rebind or destructive repair')
1233
- .option('--json', 'Stable common envelope')), 'Apply non-destructive managed repairs'))
1234
- .addHelpText('after', `
1235
- Notes:
1236
- No flag steals a live or unverifiable kernel publication guard.
1237
- --cleanup-staging requires --apply --confirm and removes only strictly
1238
- preflighted writer-owned operation trees after acquiring a native writer
1239
- guard and issuing a new CAS fence. --takeover-stale-lock and --rebind-machine
1240
- are reserved in v1 and fail closed; no lease or copied-store adoption is
1241
- claimed by this build.
1242
- User-owned files are reported but never changed.
1243
- `)
1244
- .action(action('assets.repair', runner));
1245
- addSharedSelectors(addPreviewApply(addTargetSelector(command.command('uninstall')
1246
- .description('Remove only exact recognized global AOPS Gateway pointers')
1247
- .option('--confirm', 'Confirm removal of selected recognized pointer files')
1248
- .option('--json', 'Stable common envelope')), 'Remove selected recognized global pointer files'))
1249
- .addHelpText('after', `
1250
- Notes:
1251
- The verified local core, immutable receipts, and managed binding history are
1252
- retained. An explicit repair can restore a removed managed pointer.
1253
- Unknown, unsafe, and user-owned files are never removed.
1254
- `)
1255
- .action(action('assets.uninstall', runner));
1256
- addSharedSelectors(addPreviewApply(command.command('rollback')
1257
- .description('Create a new activation from a prior verified receipt')
1258
- .option('--to-receipt <id>', 'Prior verified activation; default previous')
1259
- .option('--confirm', 'Explicit rollback confirmation')
1260
- .option('--idempotency-key <key>', 'Optional replay/conflict key')
1261
- .option('--json', 'Stable common envelope'), 'Apply a new rollback activation receipt'))
1262
- .addHelpText('after', `
1263
- Notes:
1264
- Rollback appends history and never edits/deletes an earlier receipt.
1265
- `)
1266
- .action(action('assets.rollback', runner));
1267
- addSharedSelectors(addPreviewApply(command.command('prune')
1268
- .description('Remove only unprotected managed immutable cores')
1269
- .option('--confirm', 'Explicit deletion confirmation')
1270
- .option('--json', 'Stable common envelope'), 'Apply managed cleanup'))
1271
- .addHelpText('after', `
1272
- Notes:
1273
- Active, previous, current-release, and unexpired pinned digests are protected.
1274
- Applied prune appends MaintenanceReceiptV1 with protected/removed digests and
1275
- affected managed paths before reporting success.
1276
- Unknown files, unsafe links, and unowned paths abort cleanup.
1277
- `)
1278
- .action(action('assets.prune', runner));
1279
- command.addCommand(makeMigrateCommand(runner));
53
+ .description('Install and update public AOPS skills, guides, disciplines, and roles from one simple release archive');
54
+ addRootOptions(command.command('status').description('Show locally installed AOPS asset release state'))
55
+ .action((options) => {
56
+ const resolved = roots(options);
57
+ const state = readSimpleAgentAssetsState(resolved);
58
+ const currentAssetsRoot = state.current
59
+ ? path.join(resolved.storeRoot, 'releases', state.current, 'files')
60
+ : null;
61
+ print({
62
+ ...state,
63
+ storeRoot: resolved.storeRoot,
64
+ currentAssetsRoot,
65
+ userGuidesRoot: currentAssetsRoot ? path.join(currentAssetsRoot, 'docs', 'user-guides') : null,
66
+ disciplinesRoot: currentAssetsRoot ? path.join(currentAssetsRoot, 'disciplines') : null,
67
+ rolesRoot: currentAssetsRoot ? path.join(currentAssetsRoot, 'roles') : null,
68
+ runtimeHomes: resolved.runtimeHomes,
69
+ }, options.json);
70
+ });
71
+ addMutationOptions(command.command('install').description('Install the bundled or selected AOPS asset release'))
72
+ .action(async (options) => {
73
+ const release = options.fromRelease
74
+ ? { fromRelease: options.fromRelease, source: 'local' }
75
+ : await resolveSetupAgentAssetsReleaseV1();
76
+ const result = installSimpleAgentAssets({
77
+ releaseRoot: release.fromRelease,
78
+ roots: roots(options),
79
+ target: targets(options.target),
80
+ });
81
+ print({ ...result, source: release.source }, options.json);
82
+ });
83
+ addMutationOptions(command.command('update').description('Update from a local release or the public AOPS GitHub release'))
84
+ .option('--tag <tag>', 'Install one GitHub release tag instead of latest')
85
+ .option('--timeout-ms <ms>', 'Network timeout', (value) => Number(value), 30_000)
86
+ .action(async (options) => {
87
+ const downloaded = options.fromRelease
88
+ ? undefined
89
+ : await downloadSimpleAgentAssetsRelease({ tag: options.tag, timeoutMs: options.timeoutMs });
90
+ const releaseRoot = options.fromRelease ?? downloaded;
91
+ try {
92
+ const result = installSimpleAgentAssets({
93
+ releaseRoot,
94
+ roots: roots(options),
95
+ target: targets(options.target),
96
+ });
97
+ print({ ...result, source: options.fromRelease ? 'local' : 'github' }, options.json);
98
+ }
99
+ finally {
100
+ if (downloaded)
101
+ removeDownloadedSimpleAgentAssetsRelease(downloaded);
102
+ }
103
+ });
104
+ addRootOptions(command.command('rollback').description('Restore the previous AOPS asset release and projected skills'))
105
+ .option('--target <runtime>', 'codex, claude, or all; repeatable', collect)
106
+ .action((options) => {
107
+ print(rollbackSimpleAgentAssets({ roots: roots(options), target: targets(options.target) }), options.json);
108
+ });
1280
109
  command.action(() => command.outputHelp());
1281
110
  return command;
1282
111
  }