@open-agent-toolkit/cli 0.2.48 → 0.2.50

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 (34) hide show
  1. package/assets/bundle-metadata.json +1 -1
  2. package/assets/docs/cli-utilities/tool-packs.md +35 -24
  3. package/assets/docs/cli-utilities/workflow-gates.md +19 -0
  4. package/assets/docs/contributing/skills.md +6 -4
  5. package/assets/docs/reference/cli-reference.md +1 -1
  6. package/assets/docs/reference/troubleshooting.md +22 -4
  7. package/assets/public-package-versions.json +4 -4
  8. package/assets/skills/oat-project-design/SKILL.md +13 -6
  9. package/assets/skills/oat-project-discover/SKILL.md +13 -6
  10. package/assets/skills/oat-project-import-plan/SKILL.md +8 -2
  11. package/assets/skills/oat-project-plan/SKILL.md +8 -2
  12. package/assets/skills/oat-project-quick-start/SKILL.md +8 -2
  13. package/dist/commands/doctor/index.d.ts +7 -0
  14. package/dist/commands/doctor/index.d.ts.map +1 -1
  15. package/dist/commands/doctor/index.js +44 -23
  16. package/dist/commands/gate/__fixtures__/fake-runtime.mjs +10 -0
  17. package/dist/commands/gate/configured-command.d.ts +12 -0
  18. package/dist/commands/gate/configured-command.d.ts.map +1 -0
  19. package/dist/commands/gate/configured-command.js +120 -0
  20. package/dist/commands/gate/index.d.ts.map +1 -1
  21. package/dist/commands/gate/index.js +51 -0
  22. package/dist/commands/pjm/index.d.ts +0 -2
  23. package/dist/commands/pjm/index.d.ts.map +1 -1
  24. package/dist/commands/pjm/index.js +5 -4
  25. package/dist/commands/pjm/migrate.d.ts +2 -1
  26. package/dist/commands/pjm/migrate.d.ts.map +1 -1
  27. package/dist/commands/pjm/migrate.js +23 -17
  28. package/dist/commands/status/index.d.ts +3 -1
  29. package/dist/commands/status/index.d.ts.map +1 -1
  30. package/dist/commands/status/index.js +77 -10
  31. package/dist/commands/tools/shared/pack-inventory.d.ts +10 -0
  32. package/dist/commands/tools/shared/pack-inventory.d.ts.map +1 -1
  33. package/dist/commands/tools/shared/pack-inventory.js +71 -21
  34. package/package.json +2 -2
@@ -6,7 +6,7 @@ import { readOatConfig } from '../../../config/oat-config.js';
6
6
  import { resolveManagedScopeRoots, validateManagedPath, validateRealPathWithinScope, } from '../../../fs/paths.js';
7
7
  import { USER_SCOPE_MANAGED_AGENT_FILES, } from '../../../shared/types.js';
8
8
  import { digestDirectory, digestFile } from './content-digest.js';
9
- import { getPackDefinition } from './pack-manifest.js';
9
+ import { getPackDefinition, PACK_NAMES } from './pack-manifest.js';
10
10
  import { readScopedPackIntent, } from './scoped-pack-intent.js';
11
11
  async function pathExists(path) {
12
12
  try {
@@ -172,27 +172,29 @@ function intentDiagnostic(diagnostic) {
172
172
  return { ...diagnostic };
173
173
  }
174
174
  /**
175
- * User-scope canonical agents are installed into `~/.agents/agents/` but no
176
- * provider view is generated for them: `SCOPE_CONTENT_TYPES.user` enumerates
177
- * skills only, and the sole user-scope agent materialization is the bundled
178
- * managed role file set (`USER_SCOPE_MANAGED_AGENT_FILES`). Completeness alone
179
- * therefore reports such a pack as complete while the declared agent surface is
180
- * unreachable, so the gap is named here instead of staying silent.
175
+ * User-scope canonical agents are installed into `~/.agents/agents/`, while
176
+ * native provider-role materialization is caller-resolved from the active
177
+ * config-aware adapter set. When that capability is active, only the bundled
178
+ * managed role file set (`USER_SCOPE_MANAGED_AGENT_FILES`) is supplied to the
179
+ * extension. Completeness alone therefore cannot describe native
180
+ * materialization, so the remaining gap is named here instead of staying
181
+ * silent. Canonical instruction-read availability is a separate contract.
181
182
  */
182
- function userAgentMaterializationDiagnostics(pack, scope, assets) {
183
+ function userAgentMaterializationDiagnostics(pack, scope, assets, managedRoleMaterialization) {
183
184
  if (scope !== 'user')
184
185
  return [];
185
186
  const bundledRoleFiles = new Set(USER_SCOPE_MANAGED_AGENT_FILES);
186
187
  const unmaterialized = assets.filter(({ definition, status }) => definition.kind === 'agent' &&
187
188
  definition.ownership.user === 'managed' &&
188
189
  status !== 'missing' &&
189
- !bundledRoleFiles.has(definition.destination.split('/').at(-1) ?? ''));
190
+ (!managedRoleMaterialization ||
191
+ !bundledRoleFiles.has(definition.destination.split('/').at(-1) ?? '')));
190
192
  if (unmaterialized.length === 0)
191
193
  return [];
192
194
  return [
193
195
  {
194
196
  code: 'user-agent-unmaterialized',
195
- message: `Pack ${pack} installs user-scope canonical agents that no provider view materializes; user-scope agent materialization is limited to the bundled managed role files (${USER_SCOPE_MANAGED_AGENT_FILES.join(', ')}). Install this pack at project scope to make these agents available to providers.`,
197
+ message: `Pack ${pack} installs user-scope canonical agents without native provider-role materialization for the active provider set; canonical instruction reads are unaffected. Active Codex or Cursor materialization supplies only the bundled managed role files (${USER_SCOPE_MANAGED_AGENT_FILES.join(', ')}). Install this pack at project scope to materialize the affected agents.`,
196
198
  paths: unmaterialized.map(({ path }) => path),
197
199
  },
198
200
  ];
@@ -210,7 +212,7 @@ export async function inventoryScopedPack(input) {
210
212
  ]);
211
213
  const diagnostics = [
212
214
  ...intent.diagnostics.map(intentDiagnostic),
213
- ...userAgentMaterializationDiagnostics(input.pack, input.scope, assets),
215
+ ...userAgentMaterializationDiagnostics(input.pack, input.scope, assets, input.managedRoleMaterialization ?? false),
214
216
  ];
215
217
  return {
216
218
  pack: input.pack,
@@ -227,6 +229,61 @@ export function hasScopedPackPlacementEvidence(inventory) {
227
229
  definition.ownership[inventory.scope] === 'managed' &&
228
230
  status !== 'missing'));
229
231
  }
232
+ /**
233
+ * Attribute each present shared asset only after every candidate pack has been
234
+ * inventoried. Shared presence cannot establish placement, so applicable
235
+ * owners are limited to packs with independent intent or non-shared managed
236
+ * assets. The observation is attached once to the first applicable owner in
237
+ * canonical pack order while naming the complete applicable owner set.
238
+ */
239
+ export function attributeSharedOwnerDiagnostics(inventories) {
240
+ const attributed = inventories.map((inventory) => ({
241
+ ...inventory,
242
+ scopes: inventory.scopes.map((scoped) => ({
243
+ ...scoped,
244
+ diagnostics: scoped.diagnostics.filter(({ code }) => code !== 'shared-owner-observation'),
245
+ })),
246
+ diagnostics: inventory.diagnostics.filter(({ code }) => code !== 'shared-owner-observation'),
247
+ }));
248
+ const groups = new Map();
249
+ for (const inventory of attributed) {
250
+ for (const scoped of inventory.scopes) {
251
+ for (const asset of scoped.assets) {
252
+ const owner = asset.definition.sharedOwner;
253
+ if (!owner || asset.status === 'missing')
254
+ continue;
255
+ const key = `${scoped.scope}:${owner}:${asset.definition.destination}`;
256
+ const group = groups.get(key) ?? {
257
+ owner,
258
+ destination: asset.definition.destination,
259
+ scope: scoped.scope,
260
+ candidates: [],
261
+ paths: new Set(),
262
+ };
263
+ group.candidates.push({ pack: inventory.pack, scoped });
264
+ group.paths.add(asset.path);
265
+ groups.set(key, group);
266
+ }
267
+ }
268
+ }
269
+ const packOrder = new Map(PACK_NAMES.map((pack, index) => [pack, index]));
270
+ for (const group of groups.values()) {
271
+ const applicable = group.candidates
272
+ .filter(({ scoped }) => hasScopedPackPlacementEvidence(scoped))
273
+ .sort((left, right) => packOrder.get(left.pack) - packOrder.get(right.pack));
274
+ if (applicable.length === 0)
275
+ continue;
276
+ const applicableOwners = applicable.map(({ pack }) => pack);
277
+ const diagnostic = {
278
+ code: 'shared-owner-observation',
279
+ message: `Shared managed asset ${group.destination} (${group.owner}) at ${group.scope} scope applies to installed or intended pack owner(s): ${applicableOwners.join(', ')}`,
280
+ paths: [...group.paths].sort(),
281
+ };
282
+ const selected = applicable[0];
283
+ selected.scoped.diagnostics.push(diagnostic);
284
+ }
285
+ return attributed;
286
+ }
230
287
  export async function inventoryPack(input) {
231
288
  const definition = getPackDefinition(input.pack);
232
289
  const roots = {
@@ -242,6 +299,9 @@ export async function inventoryPack(input) {
242
299
  scope,
243
300
  scopeRoot,
244
301
  assetsRoot: input.assetsRoot,
302
+ managedRoleMaterialization: scope === 'user'
303
+ ? (input.userManagedRoleMaterialization ?? false)
304
+ : false,
245
305
  }),
246
306
  ]
247
307
  : [];
@@ -255,16 +315,6 @@ export async function inventoryPack(input) {
255
315
  ? 'user'
256
316
  : 'unavailable';
257
317
  const diagnostics = scopes.flatMap(({ diagnostics: values }) => values);
258
- for (const scoped of scopes) {
259
- const shared = scoped.assets.filter(({ definition: asset, status }) => asset.sharedOwner !== undefined && status !== 'missing');
260
- if (shared.length > 0 && !hasScopedPackPlacementEvidence(scoped)) {
261
- diagnostics.push({
262
- code: 'shared-owner-observation',
263
- message: `Pack ${input.pack} has shared managed assets at ${scoped.scope} scope without pack ownership evidence`,
264
- paths: shared.map(({ path }) => path),
265
- });
266
- }
267
- }
268
318
  if (placement === 'both') {
269
319
  const assets = active.flatMap(({ assets: values }) => values.filter(({ status }) => status !== 'missing'));
270
320
  diagnostics.push({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-agent-toolkit/cli",
3
- "version": "0.2.48",
3
+ "version": "0.2.50",
4
4
  "private": false,
5
5
  "description": "Open Agent Toolkit CLI",
6
6
  "homepage": "https://github.com/voxmedia/open-agent-toolkit/tree/main/packages/cli",
@@ -34,7 +34,7 @@
34
34
  "ora": "^9.0.0",
35
35
  "yaml": "2.8.2",
36
36
  "zod": "^3.25.76",
37
- "@open-agent-toolkit/control-plane": "0.2.48"
37
+ "@open-agent-toolkit/control-plane": "0.2.50"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@types/node": "^22.10.0",