@aihq/harness 0.5.0 → 1.0.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/README.md +57 -8
- package/dist/chunk-HPWF2YPV.js +3060 -0
- package/dist/cli.js +2 -1
- package/dist/index.d.ts +214 -6
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-75FWB266.js +0 -3046
package/README.md
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
[](https://github.com/samartomar/ai-harness/actions/workflows/ci.yml)
|
|
4
4
|
[](https://github.com/samartomar/ai-harness/actions/workflows/codeql.yml)
|
|
5
5
|
[](https://scorecard.dev/viewer/?uri=github.com/samartomar/ai-harness)
|
|
6
|
+
[](https://app.codecov.io/gh/samartomar/ai-harness)
|
|
6
7
|
[](LICENSE)
|
|
7
8
|
[](package.json)
|
|
8
9
|
|
|
@@ -14,7 +15,9 @@ A cross-platform CLI that helps prepare developer workstations and repositories
|
|
|
14
15
|
**reviewable, governed AI-assisted coding behind a corporate proxy**. It extracts
|
|
15
16
|
corporate trust, tunes local inference, adds repo guardrails, wires up
|
|
16
17
|
MCP / observability / sandboxing, and lays down a tool-agnostic context
|
|
17
|
-
architecture — all from one command surface.
|
|
18
|
+
architecture — all from one command surface. On top of that setup it runs a
|
|
19
|
+
governance loop for external agent skills — vet → approve → pack → marketplace →
|
|
20
|
+
evidence — anchored in a committed approval lock (`aih-skills.lock.json`).
|
|
18
21
|
|
|
19
22
|
> Implements the architectural blueprint *"Enterprise DevSecOps AI Bootstrapping:
|
|
20
23
|
> Cryptographic Trust, Local Performance Optimization, and Unified Observability"*
|
|
@@ -28,6 +31,12 @@ architecture — all from one command surface.
|
|
|
28
31
|
|
|
29
32
|
- **Dry-run by default.** `aih <cmd>` computes and prints a plan; nothing is
|
|
30
33
|
written until you add `--apply`. Add `--verify` to run read-only checks.
|
|
34
|
+
- **Gated writes.** `--apply` refuses a dirty git worktree unless you add
|
|
35
|
+
`--force`. Commands resolve a governance posture (`--posture vibe|team|enterprise`,
|
|
36
|
+
default `vibe`): the skill-install gate refuses unapproved skills at
|
|
37
|
+
`team`/`enterprise` and stays advisory at `vibe`; pack installs are fail-closed
|
|
38
|
+
at every posture. Once a repo is initialised, every run is recorded in the
|
|
39
|
+
local [run ledger](#run-ledger).
|
|
31
40
|
- **Never mutates a remote system.** Every unit of work is a local `write`, a
|
|
32
41
|
local `exec` (icacls/chmod/junction…), a read-only `probe`, or a `doc` (the
|
|
33
42
|
exact commands for cloud setup — SSO, gateways, Langfuse, MDM — emitted for a
|
|
@@ -89,6 +98,7 @@ aih init . --apply # apply it
|
|
|
89
98
|
| `aih trust` | Vet, pin, and gate external GitHub repos and skills before an agent acquires them. `scan <target>` grades danger (auto-exec hooks, dependency-confusion, typosquat, incoming-MCP, secrets) and emits SARIF; `allow`/`pin` record reviewed sources + pinned SHAs in org policy; `list`/`verify` audit the committed policy and trust-lock evidence. |
|
|
90
99
|
| `aih skill` | The **skill lifecycle** on top of `trust` — a complete governance loop for external agent skills. `vet <src>` runs the read-only gate pipeline (shape, license, trust scan) to a **GREEN/YELLOW/RED/UNKNOWN** verdict + a local evidence artifact (never installs). `card`/`approve --pin --owner` turn that evidence into committed governance: a skill card + a root **`aih-skills.lock.json`** entry, behind a fail-closed chain (pin → evidence → approvable verdict → license → owner; RED blocked, UNKNOWN refused, YELLOW = the manual review). The lockfile has **install-time teeth**: `workspace add` refuses promoting a skill with no committed approval *for that source's pinned commit* at `team`/`enterprise` posture (advisory at `vibe`) — a same-named skill from an unrelated source never inherits an approval, and stale approvals are refused. `inventory` joins on-disk skills against the approvals — approved / unapproved / stale-pin / quarantined, one row per physical install — and feeds a "Skill governance" panel in `report --v9`. `quarantine --name <skill>` **disables reversibly** (dir → `.aih/quarantine/`, approval kept; move it back to restore). `remove --name <skill>` retracts: archives the skill dir reversibly (`--delete` to hard-delete), drops the approval + card; refuses ambiguous duplicates, nested-skill collateral, machine-root installs, and stranding a parked copy's approval; cleans up orphaned approvals. |
|
|
91
100
|
| `aih pack` | **Curation manifests** on top of the per-skill lifecycle — a committed root `aih-packs.json` names sets of approved skills so a team installs "the docs-quality pack", not N individual approvals. The `aih-skills.lock.json` stays the **pin authority**: every manifest ref is a fail-closed cross-check against the lock entry (`pack.pin-mismatch` blocks; a disagreeing manifest is never a second pin). `status`/`validate` grade each pack on the two orthogonal axes (approval × install) — `validate` is the **CI gate** (coded findings: `pack.missing-approval`, `pack.pin-mismatch`, `pack.duplicate-name`). `add`/`remove-entry`/`init` author the manifest with refs **derived from the lock** (authoring never invents a pin; `init` seeds a pack from `skill approve --pack` tags; an emptied pack is dropped whole). `plan`/`install` drive the gated two-phase acquisition once per source — **gate ALL sources before promoting ANY**, promote only the pack's refs (subset-exact), route drifted installs back through the gate, resume idempotently — fail-closed at every posture (clean approvals required even at `vibe`; `--acknowledge` refused, acknowledgements stay per-source). `uninstall` retracts every installed member with `skill remove`'s exact per-member semantics — reversible archive (or `--delete`), approval + card dropped, loader-ref advisories, the same refusal guards, and **one blocked member refuses the whole plan**; the manifest curation stays. Installed skills' pack tags roll up in the report's Skill-governance panel. |
|
|
101
|
+
| `aih marketplace` | Package the approved skill set into a **reproducible, verifiable distribution artifact** — a directory a team can host anywhere (git repo or static host), never a registry/server. `build` reads `aih-skills.lock.json` (the **approval authority**) and emits the exact vetted skill bytes (trust-lock hash cross-checked), the committed skill cards, the content-addressed vet evidence, a `marketplace.json` manifest, and `SHA256SUMS` — byte-identical across builds from identical inputs (no wall-clock; `--stamp` is operator-supplied), and **fail-closed whole**: an approved skill that is uninstalled, drifted, ambiguous, or missing its card/evidence refuses the entire build. `validate` is the **read-only CI gate** over a built or fetched artifact (coded findings: `marketplace.manifest-parse`, `marketplace.path-traversal`, `marketplace.missing-file`, `marketplace.checksum-mismatch`, `marketplace.sums-coverage`, `marketplace.unapproved-verdict`, `marketplace.signature`), containment-checking every manifest/sums path **before** touching the filesystem with it. `publish` signs the artifact's `SHA256SUMS` (cosign or a GitHub attestation — a publish without a signer is refused; that's just a build); `validate --require-signature` then **fails rather than skips** when that signature can't be verified. Consumers stay on `aih workspace add` — the vet gate still runs at consume time. |
|
|
92
102
|
| `aih mcp` | Generate the MCP server config **for the targeted CLIs** (`--cli`/`--all-tools`, default claude): Claude/Cursor/Kiro/Kimi get their correct project file written (`.mcp.json`, `.cursor/mcp.json`, …); Codex (TOML), Copilot, OpenCode, Zed, and global-config tools get exact per-tool guidance instead of a file aih would get wrong. Scopes: local/project/remote. For locked-down orgs, `--mode offline` (vendored local-command servers) or `--mode none` (no MCP + a CLI-tool fallback) plus a `managed-mcp.json` admin template. |
|
|
93
103
|
| `aih sandbox` | Generate a devcontainer + managed sandbox settings (egress allowlist, `failIfUnavailable`). |
|
|
94
104
|
| `aih telemetry` | Inject OpenTelemetry env, a redacting Bindplane collector, and an analytics fetcher (usage + skills endpoints → `{ usage_report, skills }`). |
|
|
@@ -103,13 +113,37 @@ aih init . --apply # apply it
|
|
|
103
113
|
| `aih init` | Initialize a repo: profile + superpowers + bootstrap-ai + scaffold + secrets + guardrails + mcp + sandbox in one pass (one writer per file). ECC is a separate gated network step — run `aih ecc` when ready (it points at ECC's own installer). |
|
|
104
114
|
| `aih adopt` | Converge an **existing** AI canon onto aih's managed model **without overwriting your work** (brownfield migration) — for a repo that already has an `AGENTS.md`/`.cursor`/`ai-*` setup. `--migrate-cli` folds committed CLI-native content into the canon (copy + pointer-convert, content-verified, backed up); `--ack <paths>` marks paths as intentionally tool-native so adopt stops flagging them. |
|
|
105
115
|
| `aih workspace` | Scaffold a **multi-repo** workspace (parent-only): cross-repo architecture map (write-once) + per-repo discipline, a VS Code `.code-workspace`, combined graph/filesystem MCP spanning every child repo, and a `.aih-workspace.json` marker. |
|
|
106
|
-
| `aih bundle` | Build a deterministic **fleet bundle** — the repo contract, org policy, and managed config packaged with a checksum manifest (and an optional `gh`-attested signature) for distribution to a team or CI. `aih bundle
|
|
116
|
+
| `aih bundle` | Build a deterministic **fleet bundle** — the repo contract, org policy, and managed config packaged with a checksum manifest (and an optional `gh`-attested signature) for distribution to a team or CI. `aih verify-bundle` re-checks a bundle against its checksums + signature. |
|
|
117
|
+
| `aih policy` | Schema gates for the org policy. `validate` is the **read-only CI gate** over the committed `aih-org-policy.json` — a missing file is a friendly skip (vibe repos carry no org policy), a parse/schema failure is a coded finding (`org-policy.invalid`) — or, under `--bundle <path>`, over a distributable **policy-bundle envelope** (`org-policy.bundle-invalid`, naming which layer failed: the envelope or the embedded policy). |
|
|
118
|
+
| `aih evidence` | Package the **audit trail aih already emits** — approval lock, packs manifest, trust lock, skill cards, vet evidence, run logs, report/SARIF outputs — into one deterministic **evidence bundle** (`build`): the exact fleet-bundle layout (`files/<rel>` copies, `manifest.json`, `SHA256SUMS`, optional best-effort `--sign cosign\|gh`) plus `evidence.json`, a typed kind index. Byte-identical across builds from identical inputs (no wall-clock); absent artifact kinds are skipped silently; re-check any copy with `aih verify-bundle --bundle <out>`. |
|
|
107
119
|
| `aih doctor` | Fail-closed verification of the workstation/repo configuration (+ workspace mode: validates each child repo). Includes a **canon markdown lint** (read-only) over the scaffolded `ai-coding/` tree. |
|
|
108
120
|
| `aih status` | Read-only inventory of what the harness has configured. |
|
|
109
121
|
|
|
110
|
-
|
|
122
|
+
Shared flags: `--apply`, `--force`, `--verify`, `--json`, `--posture <vibe|team|enterprise>`, `--support-out <dir>`, `--no-log`, `--context-dir <dir>`, `--root <dir>`, `--cli <list>`, `--all-tools`, `--detect`, `--yes` (the read-only `doctor`/`status`/`verify-bundle` take the relevant subset).
|
|
111
123
|
Settings also read from `AIH_*` env vars (`AIH_APPLY`, `AIH_CONTEXT_DIR`, `AIH_LOG`, …).
|
|
112
124
|
|
|
125
|
+
### Plugins
|
|
126
|
+
|
|
127
|
+
At startup `aih` probes for exactly one optional peer package: **`@aihq/enterprise`** — the literal
|
|
128
|
+
name, never env- or config-selectable, so nothing can point the probe at other code. When installed,
|
|
129
|
+
its `aihCommands` export (a `CommandSpec[]`) registers as native subcommands through the identical
|
|
130
|
+
path as the built-ins: shared flags, posture resolution, the dirty-worktree gate, and the run ledger
|
|
131
|
+
all apply unchanged. Not installed → zero output, fully local. `AIH_NO_PLUGINS=1` disables the
|
|
132
|
+
probe. A plugin that fails to load, exports the wrong shape, or ships an invalid spec degrades to
|
|
133
|
+
local-only with a one-line `aih: plugin:` warning on stderr — and a plugin command can never shadow
|
|
134
|
+
a built-in (built-ins always win). Installing the plugin package **is** the trust decision:
|
|
135
|
+
importing it runs its code, exactly like any other dependency you install.
|
|
136
|
+
|
|
137
|
+
The probe is hardened at its seams. The package must resolve from **the install tree `aih` itself
|
|
138
|
+
runs from** (the `node_modules` chain above the aih binary), so a global or `npx`-run `aih` pointed
|
|
139
|
+
at an untrusted repo never imports a `node_modules/@aihq/enterprise` planted inside that repo.
|
|
140
|
+
Honesty note: when aih is installed *inside* the target repo, the repo already controls the binary
|
|
141
|
+
itself — the boundary is exactly "the tree aih runs from", nothing stronger. The import also races
|
|
142
|
+
a 2-second startup budget (timeout → local-only with a warning), and `aih --version` skips the
|
|
143
|
+
probe entirely. Plugin specs cannot claim shared or reserved flags (`--apply`, `--json`, `--help`,
|
|
144
|
+
…), cannot take the names `help`/`version`, and any `skipWorktreeGate` field is stripped — the
|
|
145
|
+
dirty-worktree preflight always applies to plugin commands.
|
|
146
|
+
|
|
113
147
|
### Dashboard
|
|
114
148
|
|
|
115
149
|
`aih report --open` builds a **self-contained, offline** HTML dashboard (dark by default with a
|
|
@@ -120,7 +154,11 @@ data never reads as real. When the report derives findings (see [Support tickets
|
|
|
120
154
|
a **Suggested actions** section leads with copy-to-clipboard tickets. Add `--demo` for showcase data,
|
|
121
155
|
or `--refresh <sec>` to keep it live.
|
|
122
156
|
|
|
123
|
-

|
|
158
|
+
|
|
159
|
+
*The `--v9` developer console with `--demo` showcase data: harness-wiring score, ranked
|
|
160
|
+
fix actions, and the remediation ledger. `aih report --demo --v9` opens the same dashboard
|
|
161
|
+
locally.*
|
|
124
162
|
|
|
125
163
|
### Targeting CLIs
|
|
126
164
|
|
|
@@ -312,9 +350,7 @@ aih usage --rollup ../repo-a,../repo-b
|
|
|
312
350
|
latest minor receives fixes.
|
|
313
351
|
- **Supply chain** — every release publishes via npm **Trusted Publishing** with build
|
|
314
352
|
**provenance** and ships an **SPDX SBOM** + **SHA256 checksum** on the GitHub Release.
|
|
315
|
-
Verify an install with `npm audit signatures`.
|
|
316
|
-
[#37](https://github.com/samartomar/ai-harness/issues/37); until then, install from source
|
|
317
|
-
(above).
|
|
353
|
+
Verify an install with `npm audit signatures`.
|
|
318
354
|
- **Support** — [SUPPORT.md](SUPPORT.md) · **Security** — [SECURITY.md](SECURITY.md)
|
|
319
355
|
(private reporting) · **Contributing** — [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
320
356
|
|
|
@@ -327,9 +363,22 @@ npm run lint # biome
|
|
|
327
363
|
npm run build # tsup → dist/
|
|
328
364
|
```
|
|
329
365
|
|
|
330
|
-
Stack: TypeScript (ESM) · commander · zod · vitest · biome · tsup.
|
|
366
|
+
Stack: TypeScript (ESM) · commander · zod · vitest · biome · tsup. Coverage floors
|
|
367
|
+
are enforced in [vitest.config.ts](vitest.config.ts) — set just below the achieved
|
|
368
|
+
levels so coverage only ratchets up; CI and releases fail on regression. See
|
|
331
369
|
[CONTRIBUTING.md](CONTRIBUTING.md) for the contributor workflow.
|
|
332
370
|
|
|
371
|
+
### Stability
|
|
372
|
+
|
|
373
|
+
The CLI surface and machine-readable outputs are contract-tested in
|
|
374
|
+
[tests/contract/](tests/contract/): every command and option is snapshotted against a
|
|
375
|
+
committed fixture ([command-surface.json](tests/contract/command-surface.json)), the
|
|
376
|
+
`--json` envelope is schema-pinned, and exit-code semantics are pinned. Any drift fails
|
|
377
|
+
CI and forces a reviewed decision — additive changes regenerate the fixture in the same
|
|
378
|
+
PR (label it `contract:additive`); removals or renames of anything pinned are breaking
|
|
379
|
+
and ship in majors only, per the stability policy in [STABILITY.md](STABILITY.md) —
|
|
380
|
+
renames ship with a deprecated alias of the old name until the removing major.
|
|
381
|
+
|
|
333
382
|
## License
|
|
334
383
|
|
|
335
384
|
[Apache-2.0](LICENSE).
|