Files
callstack__agent-device/scripts/explain-command.ts
devin-ai-integration[bot] 952bc3704a refactor: keep command and daemon-route owner-file claims tooling-only (#1178) (#1192)
* refactor(command-descriptor): keep owner-file claims tooling-only

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* refactor(daemon): keep daemon-route owner-file claims tooling-only

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* test(daemon): guard against re-adding owner-file paths to the production route chain

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* refactor(command-descriptor): derive owner-file projection from colocated RAW_COMMAND_DESCRIPTORS

- Keep ownerFiles on each RAW_COMMAND_DESCRIPTORS entry as the source of truth.
- Add tooling-only __OWNER_FILES__ build flag so production bundles omit the
  ownerFiles properties entirely.
- Derive COMMAND_OWNER_FILES from RAW_COMMAND_DESCRIPTORS instead of a
  hand-maintained parallel table.
- Guard command-explain tests against leaking ownerFiles into production
  descriptor objects.
- Enable treeshake.propertyReadSideEffects: false in tsdown to help drop the
  dead ownerFiles branch from production bundles.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* chore: apply oxfmt formatting

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* test(build): guard tooling metadata exclusion

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* refactor(command-descriptor): drop global treeshake option and add bundle guard

- Remove treeshake.propertyReadSideEffects from tsdown.config.ts; the
  __OWNER_FILES__ define + conditional spread already keeps owner files out
  of the bundle, so the global DCE lever is unnecessary and scope-creeping.
- Add a comment on the __OWNER_FILES__ global declaration explaining the
  deliberate type-versus-runtime mismatch.
- Add test/output-economy/owner-files-no-leak.test.ts to build dist and
  assert that no command or daemon-route owner-file path appears in the
  emitted JS.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(build): remove owner metadata property reads

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(command-descriptor): enforce owner claim totality

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

---------

Co-authored-by: Michał Pierzchała <thymikee@gmail.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-07-11 07:46:00 +02:00

34 lines
1.3 KiB
TypeScript

import fs from 'node:fs';
import path from 'node:path';
import { explainCommand, formatCommandExplanation } from '../src/commands/command-explain.ts';
import { getDaemonRouteOwnerFiles } from '../src/daemon/route-owner-files.ts';
const repoRoot = path.resolve(import.meta.dirname, '..');
const args = process.argv.slice(2);
const json = args.includes('--json');
const full = args.includes('--full');
const query = args.find((arg) => arg !== '--json' && arg !== '--full');
if (!query) {
process.stderr.write('Usage: pnpm explain:command <command-or-catalog-key> [--json] [--full]\n');
process.exitCode = 1;
} else {
const daemonRouteOwnerFiles = getDaemonRouteOwnerFiles();
const result = explainCommand(query, {
fileExists: (file) => fs.existsSync(path.join(repoRoot, file)),
daemonRouteOwnerFiles,
});
if (!result.found) {
const suffix =
result.suggestions.length === 0 ? '' : ` Did you mean: ${result.suggestions.join(', ')}?`;
process.stderr.write(`Unknown command "${result.query}".${suffix}\n`);
process.exitCode = 1;
} else {
process.stdout.write(
json
? `${JSON.stringify(result.explanation, null, 2)}\n`
: `${formatCommandExplanation(result.explanation, { detail: full ? 'full' : 'compact' })}\n`,
);
}
}