apcore-cli 0.6.0 → 0.7.0

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.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,70 @@ All notable changes to apcore-cli (TypeScript SDK) will be documented in this fi
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.7.0] - 2026-04-25
9
+
10
+ ### Added
11
+
12
+ - **Canonical clap v4 / GNU-style help formatter** (`src/canonical-help.ts`) overriding Commander's default `formatHelp` so `--help` output is byte-stable across SDK implementations. Disables terminal-width wrapping, uppercases `<PLACEHOLDER>`s, enforces `Commands:` before `Options:`, and renders `-h, --help` / `-V, --version` last with `Print help` / `Print version` descriptions.
13
+ - **Cross-language conformance test harness** (`tests/conformance/apcli-visibility.test.ts`) now consumes the shared fixtures from the `aiperceivable/apcore-cli` spec repo (`conformance/fixtures/apcli-visibility/`). Dynamically discovers scenarios and byte-matches `--help` output against each `expected_help.txt`. Set `APCORE_CLI_SPEC_REPO` to point at a non-sibling checkout; defaults to `../apcore-cli/`.
14
+ - **CI — spec-repo checkout**: `.github/workflows/ci.yml` now checks out `aiperceivable/apcore-cli` into `.apcore-cli-spec/` and exposes it to `pnpm test` via `APCORE_CLI_SPEC_REPO`.
15
+ - **FE-13: Built-in command group (`apcli`)** — consolidates the 13 canonical built-in commands (`list`, `describe`, `exec`, `validate`, `init`, `health`, `usage`, `enable`, `disable`, `reload`, `config`, `completion`, `describe-pipeline`) under a single `apcli` sub-group. Invocation shifts from `<cli> list` to `<cli> apcli list`.
16
+ - `ApcliGroup` class + `ApcliConfig` / `ApcliMode` types, exported from `src/index.ts`.
17
+ - `RESERVED_GROUP_NAMES = new Set(["apcli"])` as the enforced collision surface (replaces the retired per-command `BUILTIN_COMMANDS` constant).
18
+ - New env var `APCORE_CLI_APCLI` — accepts `show`, `hide`, `1`, `0`, `true`, `false` (case-insensitive).
19
+ - New config keys (snake_case DEFAULTS): `apcli.mode`, `apcli.include`, `apcli.exclude`, `apcli.disable_env`.
20
+ - `ConfigResolver.resolveObject(key)` — non-leaf accessor that returns object-shaped config values without flattening.
21
+ - `createCli({ apcli })` option — accepts `boolean | object | ApcliGroup` to configure the built-in group surface.
22
+ - See [migration guide](../apcore-cli/docs/features/builtin-group.md#11-migration) for the full v0.7 → v0.8 timeline.
23
+ - **New error-code → exit-code mappings** in `src/errors.ts` and `src/main.ts`: `DEPENDENCY_NOT_FOUND` and `DEPENDENCY_VERSION_MISMATCH` both map to exit code 44. Preserves the pre-0.19.0 exit code (`MODULE_LOAD_ERROR` = 44) for missing / version-mismatched module dependencies, now that apcore-js surfaces these through dedicated error types per PROTOCOL_SPEC §5.15.2.
24
+ - **Binding-overlay tests** in `tests/display-helpers.test.ts`: a tmp binding YAML is written, `applyToolkitIntegration` is called, and `getDisplay()` is verified to return the overlay for a descriptor that has no baked-in `metadata.display`.
25
+ - **`createCli({ app })` — `APCore` unified client**: `CreateCliOptions` now accepts an `app?: APCore` field. When provided, `app.registry` and `app.executor` are extracted and used in place of explicit `registry`/`executor` fields. Passing `app` together with `registry` or `executor` throws `"app is mutually exclusive with registry/executor"`.
26
+ - `APCore` interface exported from package index. `StrategyInfo` and `StrategyStep` interfaces exported from package index.
27
+ - `Executor` interface extended with optional `describePipeline(strategyName?: string): StrategyInfo` and `strategy?: { steps: StrategyStep[] }` fields.
28
+ - **FE-12: Module Exposure Filtering** — Declarative control over which discovered modules are exposed as CLI commands.
29
+ - `ExposureFilter` class in `exposure.ts` with `isExposed(moduleId)` and `filterModules(ids)` methods.
30
+ - Three modes: `all` (default), `include` (whitelist), `exclude` (blacklist) with glob-pattern matching.
31
+ - `ExposureFilter.fromConfig(obj)` static method for loading from `apcore.yaml` `expose` section.
32
+ - `CreateCliOptions.expose` field accepting object or `ExposureFilter` instance.
33
+ - `list --exposure {exposed,hidden,all}` filter flag in discovery commands.
34
+ - `GroupedModuleGroup` integration: applies exposure filter during command registration.
35
+ - `ConfigResolver` gains `expose.*` config keys.
36
+ - 4-tier config precedence: `CreateCliOptions.expose` > `--expose-mode` CLI flag > env var > `apcore.yaml`.
37
+ - Hidden modules remain invocable via `exec <module_id>`.
38
+ - New file: `exposure.ts`.
39
+
40
+ ### Changed
41
+
42
+ - Built-in commands now live under the `apcli` sub-group. Pre-v0.7 invocations (`<cli> list`, `<cli> describe`, etc.) still work in **standalone mode** via deprecation shims that print a `WARNING` to stderr and forward to `apcli <name>`. Shims are not installed in embedded mode.
43
+ - Discovery flags (`--extensions-dir`, `--commands-dir`, `--binding`) are now gated on standalone mode — they are only registered when no `registry` is injected.
44
+ - Shell-completion generators (bash/zsh/fish) enumerate registered Commander subcommands dynamically; hardcoded command lists are gone.
45
+ - **Dependency bump**: requires `apcore-js >= 0.19.0` (was `>= 0.18.0`) and `apcore-toolkit >= 0.5.0` (was `>= 0.4.0`). Aligns with upstream releases `apcore-js 0.19.0` (dependency graph errors, async `buildStrategyFromConfig`, auto-schema adapter chain, `BindingSchemaMissingError` rename) and `apcore-toolkit 0.5.0` (`BindingLoader`, `ScannedModule.display`, `apcore-toolkit/browser` subpath).
46
+ - **Placeholder types in `src/cli.ts` realigned with real apcore-js shapes.** `PipelineTrace` / `StepTrace` / `PreflightResult` / `StrategyStep` now use camelCase (`strategyName`, `totalDurationMs`, `durationMs`, `skipReason`, `requiresApproval`, `timeoutMs`) matching the apcore-js runtime object shape. `Executor.describePipeline` is typed as `(): StrategyInfo` (zero arguments — the previous `describePipeline?(strategyName?: string)` signature declared an argument that the real apcore-js method ignores). `Executor.strategy` renamed to `Executor.currentStrategy` to match the upstream getter.
47
+ - **`--trace` output now reads the correct runtime fields.** `main.ts` previously read `trace.strategy_name` / `trace.total_duration_ms` / `s.duration_ms` / `s.skip_reason` (snake_case) from the camelCase `PipelineTrace` returned by apcore-js, so those values surfaced as `undefined` at runtime. Now reads `strategyName` / `totalDurationMs` / `durationMs` / `skipReason` correctly. JSON output keys remain snake_case to preserve the cross-language CLI output contract.
48
+ - **`formatPreflightResult` now reads `result.requiresApproval`** (was `result.requires_approval`). The JSON output key remains `requires_approval`.
49
+ - **`MAX_MODULE_ID_LENGTH` 128 → 192**: `validateModuleId()` now enforces a 192-character limit for module IDs, up from 128, to accommodate Java/.NET deep-namespace FQN-derived IDs (PROTOCOL_SPEC §2.7 spec 1.6.0-draft).
50
+ - **`Executor.describePipeline()` returns `StrategyInfo`**: `describe-pipeline` command in `strategy.ts` now calls `executor.describePipeline(strategyName)` and consumes the returned `StrategyInfo` object (`name`, `stepCount`, `stepNames`, `description`). Pipeline header format updated to `Pipeline: ${info.name} (${info.stepCount} steps)`. Step metadata (Pure/Removable/Timeout columns) sourced from `executor.strategy.steps` (`pure: boolean`, `removable: boolean`, `timeoutMs: number`). Falls back to static preset table when `describePipeline` is not available.
51
+
52
+ ### Deprecated
53
+
54
+ - Root-level v0.6 built-in commands continue to work in standalone mode but emit a `WARNING` and forward to `apcli <name>`. **Scheduled for removal in v0.8.**
55
+
56
+ ### Removed
57
+
58
+ - The per-command `BUILTIN_COMMANDS` constant and its re-export from `src/index.ts`. Replaced by `RESERVED_GROUP_NAMES`.
59
+ - Monolithic registrars `registerDiscoveryCommands`, `registerSystemCommands`, `registerShellCommands` — replaced by per-subcommand exports invoked through `ApcliGroup`.
60
+
61
+ ### Fixed
62
+
63
+ - **`describe-pipeline --strategy <name>` now works for non-current strategies.** Previously the command called `executor.describePipeline(strategyName)` — the real apcore-js signature takes no arguments and always returns info for the executor's *current* strategy, so all `--strategy` values produced identical output. `src/strategy.ts` now uses a two-step lookup: if the requested name matches the current strategy, use `describePipeline()`; otherwise fall back to the static `Executor.listStrategies()` (reached via `executor.constructor.listStrategies`) to introspect other registered strategies.
64
+ - **`--binding <path>` flag now actually applies display overlay.** `applyToolkitIntegration` previously instantiated a `DisplayResolver` and discarded it. The implementation now uses apcore-toolkit 0.5.0's `BindingLoader` + `DisplayResolver` pipeline to parse the binding YAML, resolve the sparse overlay, and populate a module-level binding display map. `display-helpers.ts#getDisplay` consults the map as a fallback when the descriptor itself has no `metadata.display`, so `cli.alias` / `cli.description` / tags from `.binding.yaml` are now honored by `list`, `describe`, and command help output. New exports: `lookupBindingDisplay(moduleId)` and `clearBindingDisplayMap()` from `src/main.ts`.
65
+
66
+ ### Breaking
67
+
68
+ - Reserved-name enforcement is now a **hard exit 2** when a module's explicit group, auto-group prefix, or top-level name/alias equals `apcli`. Previously this was warn-and-drop.
69
+
70
+ ---
71
+
8
72
  ## [0.6.0] - 2026-04-06
9
73
 
10
74
  ### Changed
package/LICENSE CHANGED
@@ -1,21 +1,17 @@
1
- MIT License
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
2
4
 
3
- Copyright (c) 2026 AI Perceivable
5
+ Copyright 2024 aiperceivable <tercel.yi@gmail.com>
4
6
 
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
7
+ Licensed under the Apache License, Version 2.0 (the "License");
8
+ you may not use this file except in compliance with the License.
9
+ You may obtain a copy of the License at
11
10
 
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
11
+ http://www.apache.org/licenses/LICENSE-2.0
14
12
 
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
13
+ Unless required by applicable law or agreed to in writing, software
14
+ distributed under the License is distributed on an "AS IS" BASIS,
15
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ See the License for the specific language governing permissions and
17
+ limitations under the License.
package/README.md CHANGED
@@ -8,7 +8,7 @@ Terminal adapter for apcore. Execute AI-Perceivable modules from the command lin
8
8
 
9
9
  [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](LICENSE)
10
10
  [![Node](https://img.shields.io/badge/node-18%2B-blue.svg)](https://nodejs.org)
11
- [![Tests](https://img.shields.io/badge/tests-183%20passed-brightgreen.svg)]()
11
+ [![Tests](https://img.shields.io/badge/tests-275%2B%20passed-brightgreen.svg)]()
12
12
 
13
13
  | | |
14
14
  |---|---|
@@ -49,7 +49,14 @@ Terminal adapter for apcore. Execute AI-Perceivable modules from the command lin
49
49
  pnpm add apcore-cli apcore-js
50
50
  ```
51
51
 
52
- Requires Node.js 18+ and `apcore-js >= 0.14.0`.
52
+ Requires Node.js 18+ and `apcore-js >= 0.19.0`.
53
+
54
+ **Optional:** install `apcore-toolkit` (>=0.5.0) to enable display overlay and registry writer integration via `applyToolkitIntegration`, `DisplayResolver`, and `RegistryWriter`.
55
+
56
+ ```bash
57
+ pnpm add apcore-cli apcore-js
58
+ pnpm add -D apcore-toolkit # optional, for display overlay / registry writer
59
+ ```
53
60
 
54
61
  ## Quick Start
55
62
 
@@ -95,21 +102,32 @@ const cli = createCli({
95
102
  cli.parse(process.argv);
96
103
  ```
97
104
 
98
- Or use the `LazyModuleGroup` directly with Commander:
105
+ Or wire the `createCli` options-object form directly with a runtime-supplied registry/executor:
99
106
 
100
107
  ```typescript
101
- import { LazyModuleGroup, buildModuleCommand } from "apcore-cli";
102
- import { Registry, Executor } from "apcore-js";
103
-
104
- const registry = new Registry("./extensions");
105
- registry.discover();
106
- const executor = new Executor(registry);
108
+ import { createCli } from "apcore-cli";
107
109
 
108
- const group = new LazyModuleGroup(registry, executor);
109
- const cmd = group.getCommand("math.add");
110
- cmd?.parse(process.argv);
110
+ async function main() {
111
+ // Obtain registry/executor from your apcore-js setup
112
+ // (e.g., via ExtensionsLoader or your framework's module discovery).
113
+ // See apcore-js docs for the exact bootstrap API.
114
+ const { registry, executor } = await bootstrapApcoreRuntime("./extensions");
115
+
116
+ const cli = createCli({
117
+ registry,
118
+ executor,
119
+ progName: "myapp",
120
+ // expose: { mode: "include", include: ["admin.*"] },
121
+ // extraCommands: [customCmd1, customCmd2],
122
+ });
123
+ cli.parse(process.argv);
124
+ }
125
+
126
+ main();
111
127
  ```
112
128
 
129
+ > **Known gap:** The `Registry`, `Executor`, and `ModuleDescriptor` types re-exported by `apcore-cli` are currently **local placeholder interfaces** pending upstream export from `apcore-js`. Direct construction (`new Registry(...)` / `new Executor(registry)`) is **not supported** at this version. Structural typing allows runtime apcore-js objects to satisfy these interfaces, so `createCli({ registry, executor })` works when you pass in objects produced by your apcore-js runtime.
130
+
113
131
  ## Integration with Existing Projects
114
132
 
115
133
  ### Typical apcore project structure
@@ -168,15 +186,66 @@ apcore-cli [OPTIONS] COMMAND [ARGS]
168
186
  | `--verbose` | | Show all options in help (including built-in apcore options) |
169
187
  | `--man` | | Output man page in roff format (use with `--help`) |
170
188
 
171
- ### Built-in Commands
189
+ ### Built-in Commands (the `apcli` group)
190
+
191
+ Starting in **v0.7.0**, all built-in commands live under an `apcli` sub-group
192
+ (see the `RESERVED_GROUP_NAMES` collision surface in `src/builtin-group.ts`).
193
+ Invocation:
194
+
195
+ ```bash
196
+ apcore-cli apcli list
197
+ apcore-cli apcli describe math.add
198
+ apcore-cli apcli exec math.add --a 5 --b 10
199
+ ```
200
+
201
+ > **Migration note (v0.7):** Root-level invocations (`apcore-cli list`, `apcore-cli describe`, …) still work in **standalone mode** but emit a deprecation
202
+ > `WARNING` and are removed in v0.8. Embedded integrations (host CLIs that
203
+ > inject a `registry`) never had root-level built-ins in the first place and
204
+ > see no warnings. See the full migration timeline in the spec repo:
205
+ > [`docs/features/builtin-group.md §11 Migration`](../apcore-cli/docs/features/builtin-group.md#11-migration).
206
+
207
+ The canonical 13 `apcli` subcommands:
208
+
209
+ **Module invocation & discovery**
210
+
211
+ | Command | Description |
212
+ |---------|-------------|
213
+ | `apcli list` | List available modules with search, status, tag/annotation filters, sort, and dependency inspection (see `registerListCommand` in `src/discovery.ts`) |
214
+ | `apcli describe <module_id>` | Show full module metadata, schemas, and annotations (see `registerDescribeCommand` in `src/discovery.ts`) |
215
+ | `apcli describe-pipeline <module_id>` | Inspect the execution pipeline for a module (strategies, hooks, middleware; see `registerPipelineCommand` in `src/strategy.ts`) |
216
+ | `apcli exec <module_id>` | Internal routing alias for module execution (see `registerExecCommand` in `src/discovery.ts`) |
217
+ | `apcli usage <module_id>` | Show usage examples and flag hints for a module (see `registerUsageCommand` in `src/system-cmd.ts`) |
218
+
219
+ **System management**
172
220
 
173
221
  | Command | Description |
174
222
  |---------|-------------|
175
- | `list` | List available modules with optional tag filtering |
176
- | `describe <module_id>` | Show full module metadata and schemas |
177
- | `exec <module_id>` | Internal routing alias for module execution |
178
- | `completion <shell>` | Generate shell completion script (bash/zsh/fish) |
179
- | `man <command>` | Generate man page in roff format |
223
+ | `apcli config` | Inspect effective configuration and precedence (see `registerConfigCommand` in `src/system-cmd.ts`) |
224
+ | `apcli health` | Run health checks on registry, executor, config, and auth (see `registerHealthCommand` in `src/system-cmd.ts`) |
225
+ | `apcli reload` | Reload registry / rediscover extensions (see `registerReloadCommand` in `src/system-cmd.ts`) |
226
+ | `apcli enable <module_id>` | Enable a disabled module (see `registerEnableCommand` in `src/system-cmd.ts`) |
227
+ | `apcli disable <module_id>` | Disable a module without removing it (see `registerDisableCommand` in `src/system-cmd.ts`) |
228
+
229
+ **Workflow**
230
+
231
+ | Command | Description |
232
+ |---------|-------------|
233
+ | `apcli init` | Scaffold a starter `apcore.yaml` / extensions layout (see `registerInitCommand` in `src/init-cmd.ts`) |
234
+ | `apcli validate` | Validate modules and configuration against JSON Schema (see `registerValidateCommand` in `src/discovery.ts`) |
235
+
236
+ **Shell integration**
237
+
238
+ | Command | Description |
239
+ |---------|-------------|
240
+ | `apcli completion <shell>` | Generate shell completion script for bash / zsh / fish (see `registerCompletionCommand` in `src/shell.ts`) |
241
+ | `man [command]` (root) | Generate a man page in roff format for a single command or the whole program (see `configureManHelp` in `src/shell.ts`). Stays at the root (meta-command). |
242
+
243
+ #### Standalone vs. embedded surfaces
244
+
245
+ | Mode | Invocation | Notes |
246
+ |------|------------|-------|
247
+ | **Standalone** (`apcore-cli`) | `apcore-cli apcli <subcommand>` | Discovery flags (`--extensions-dir`, `--commands-dir`, `--binding`) are registered. Legacy root-level built-ins are kept as deprecation shims. |
248
+ | **Embedded** (`createCli({ registry, … })`) | `<host-cli> apcli <subcommand>` | Discovery flags are gated off (injected registry already supplies modules). No legacy shims — embedded hosts are new territory. |
180
249
 
181
250
  ### Module Execution Options
182
251
 
@@ -187,11 +256,32 @@ When executing a module (e.g. `apcore-cli math.add`), these built-in options are
187
256
  | `--input -` | Read JSON input from STDIN |
188
257
  | `--yes` / `-y` | Bypass approval prompts |
189
258
  | `--large-input` | Allow STDIN input larger than 10MB |
190
- | `--format` | Output format: `json` or `table` |
259
+ | `--format <fmt>` | Output format: `json`, `table`, `csv`, `yaml`, or `jsonl` |
191
260
  | `--sandbox` | Run module in subprocess sandbox (not yet implemented — always hidden) |
261
+ | `--dry-run` | Run preflight checks (schema, ACL, approval) without executing (FE-11) |
262
+ | `--trace` | Emit execution pipeline trace (strategy, hooks, middleware timings) |
263
+ | `--stream` | Stream results line-by-line for stream-capable modules |
264
+ | `--strategy <name>` | Override execution strategy: `standard`, `internal`, `testing`, `performance`, or `minimal` |
265
+ | `--fields <csv>` | Select output fields via dot-path notation (e.g. `result.sum,meta.duration`) |
266
+ | `--approval-timeout <seconds>` | Override approval timeout (default `60`) |
267
+ | `--approval-token <token>` | Provide a pre-obtained approval token (bypasses interactive prompt) |
192
268
 
193
269
  Schema-generated flags (e.g. `--a`, `--b`) are added automatically from the module's `input_schema`.
194
270
 
271
+ #### `list` command flags (v0.6.0)
272
+
273
+ The `list` command supports enhanced filtering and inspection flags:
274
+
275
+ | Option | Description |
276
+ |--------|-------------|
277
+ | `--search <query>` | Fuzzy search across module IDs, descriptions, and annotations |
278
+ | `--status <state>` | Filter by status (e.g. `enabled`, `disabled`, `deprecated`) |
279
+ | `--annotation <key=value>` | Filter by an annotation key/value pair |
280
+ | `--sort <field>` | Sort by `name`, `status`, or other indexed fields |
281
+ | `--reverse` | Reverse sort order |
282
+ | `--deprecated` | Include deprecated modules in the output |
283
+ | `--deps` | Show dependency graph for each module |
284
+
195
285
  ### Exit Codes
196
286
 
197
287
  | Code | Meaning |
@@ -227,6 +317,9 @@ apcore-cli uses a 4-tier configuration precedence:
227
317
  | `APCORE_AUTH_API_KEY` | API key for remote registry authentication | *(unset)* |
228
318
  | `APCORE_CLI_SANDBOX` | Set to `1` to enable subprocess sandboxing | *(unset)* |
229
319
  | `APCORE_CLI_HELP_TEXT_MAX_LENGTH` | Maximum characters for CLI option help text before truncation | `1000` |
320
+ | `APCORE_CLI_APPROVAL_TIMEOUT` | Default approval prompt timeout in seconds | `60` |
321
+ | `APCORE_CLI_STRATEGY` | Default execution strategy (`standard`, `internal`, `testing`, `performance`, `minimal`) | `standard` |
322
+ | `APCORE_CLI_GROUP_DEPTH` | Maximum nesting depth when rendering grouped module command trees | `2` |
230
323
 
231
324
  ### Config File (`apcore.yaml`)
232
325
 
@@ -239,6 +332,9 @@ sandbox:
239
332
  enabled: false
240
333
  cli:
241
334
  help_text_max_length: 1000
335
+ approval_timeout: 60 # seconds
336
+ strategy: standard # standard | internal | testing | performance | minimal
337
+ group_depth: 2 # grouped-module command-tree nesting depth
242
338
  ```
243
339
 
244
340
  ## Features
@@ -251,7 +347,7 @@ cli:
251
347
  - **TTY-adaptive output** -- rich tables for terminals, JSON for pipes (configurable via `--format`)
252
348
  - **Approval gate** -- TTY-aware HITL prompts for modules with `requires_approval: true`, with `--yes` bypass and 60s timeout
253
349
  - **Schema validation** -- inputs validated against JSON Schema before execution, with `$ref`/`allOf`/`anyOf`/`oneOf` resolution
254
- - **Security** -- API key auth (keyring + AES-256-GCM), append-only audit logging, subprocess sandboxing
350
+ - **Security** -- API key auth (keyring + AES-256-GCM), append-only audit logging, subprocess sandboxing (stub — not yet runnable)
255
351
  - **Shell completions** -- `apcore-cli completion bash|zsh|fish` generates completion scripts with dynamic module ID completion
256
352
  - **Man pages** -- `apcore-cli man <command>` for single commands, or `--help --man` for a complete program man page. `configureManHelp()` provides one-line integration for downstream projects
257
353
  - **Documentation URL** -- `setDocsUrl()` adds doc links to help footers and man pages
@@ -284,7 +380,7 @@ apcore-cli (the adapter)
284
380
  +-- approval TTY-aware HITL approval
285
381
  +-- output TTY-adaptive JSON/table output
286
382
  +-- AuditLogger JSON Lines execution logging
287
- +-- Sandbox Subprocess isolation
383
+ +-- Sandbox Subprocess isolation (stub — not yet runnable)
288
384
  |
289
385
  v
290
386
  apcore Registry + Executor (your modules, unchanged)
@@ -302,14 +398,30 @@ apcore Registry + Executor (your modules, unchanged)
302
398
 
303
399
  ## Development
304
400
 
401
+ The conformance suite under `tests/conformance/` reads shared fixtures from
402
+ the **spec repo** (`aiperceivable/apcore-cli`). Clone it as a sibling of
403
+ this repo, or point `APCORE_CLI_SPEC_REPO` at an existing checkout:
404
+
305
405
  ```bash
406
+ # One-time: clone both repos side by side
407
+ git clone https://github.com/aiperceivable/apcore-cli.git
306
408
  git clone https://github.com/aiperceivable/apcore-cli-typescript.git
409
+
307
410
  cd apcore-cli-typescript
308
411
  pnpm install
309
- pnpm test # 183 tests
412
+ pnpm test # reads fixtures from ../apcore-cli/conformance/
310
413
  pnpm build # compile TypeScript
311
414
  ```
312
415
 
416
+ Alternative layout (spec repo checked out elsewhere):
417
+
418
+ ```bash
419
+ export APCORE_CLI_SPEC_REPO=/path/to/apcore-cli
420
+ pnpm test
421
+ ```
422
+
423
+ CI does this automatically — see `.github/workflows/ci.yml`.
424
+
313
425
  ## License
314
426
 
315
427
  Apache-2.0