xgauntlet 0.1.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 +286 -0
- package/bin/xgauntlet.js +191 -0
- package/package.json +42 -0
package/README.md
ADDED
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<a href="#-hurtig-start--installation"><b>🚀 Hurtig Start & Installation</b></a> •
|
|
3
|
+
<a href="#-pipeline-og-gates-sådan-virker-det"><b>🧠Pipeline & Gates</b></a> •
|
|
4
|
+
<a href="#-arkitektur--designprincipper"><b>🎯 Arkitektur</b></a> •
|
|
5
|
+
<a href="#️-mappestruktur-package-by-feature"><b>🏗️ Mappestruktur</b></a> •
|
|
6
|
+
<a href="#️-fuld-cli-reference"><b>🛠️ CLI Reference</b></a> •
|
|
7
|
+
<a href="#-rust-api"><b>🦀 Rust API</b></a> •
|
|
8
|
+
<a href="#️-arkitektur-adrs"><b>🏛️ ADRs</b></a>
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
<p align="center">
|
|
14
|
+
<h1 align="center">xGauntlet 🛡️</h1>
|
|
15
|
+
</p>
|
|
16
|
+
|
|
17
|
+
<p align="center">
|
|
18
|
+
<em>Universel multi-stack verifikations- og actionable diagnostics motor bygget pĂĄ Robert C. Martin ("Uncle Bob") TDD, Clean Craftsmanship & Zero-Daemon WebAssembly</em>
|
|
19
|
+
</p>
|
|
20
|
+
|
|
21
|
+
<p align="center">
|
|
22
|
+
<a href="https://www.npmjs.com/package/xgauntlet"><img src="https://img.shields.io/npm/v/xgauntlet.svg?color=blue" alt="NPM Version" /></a>
|
|
23
|
+
<a href="https://github.com/rolfmadsen/xGauntlet/actions/workflows/ci.yml"><img src="https://github.com/rolfmadsen/xGauntlet/actions/workflows/ci.yml/badge.svg?branch=main" alt="CI" /></a>
|
|
24
|
+
<a href="docs/adr/0005-two-tier-verification-and-attestation-model.md"><img src="https://img.shields.io/badge/evidence-Two--Tier%20Trust%20Model-blue.svg" alt="Evidence Model" /></a>
|
|
25
|
+
<a href="wit/gauntlet_policy.wit"><img src="https://img.shields.io/badge/WASM-Zero%20Ambient%20Authority-purple.svg" alt="WASM Policy" /></a>
|
|
26
|
+
<a href="Cargo.toml"><img src="https://img.shields.io/badge/rust-2021%20edition-orange.svg" alt="Rust Version" /></a>
|
|
27
|
+
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT" /></a>
|
|
28
|
+
</p>
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
**Dokumentation**: [Makro-Spec](spec.md) • [Domæne-Glossary](CONTEXT.md) • [Kodestandarder](CODING_STANDARDS.md) • [Arkitektur (ADRs)](docs/adr/)
|
|
33
|
+
|
|
34
|
+
**Kildekode & Pakker**: [GitHub](https://github.com/rolfmadsen/xGauntlet) • [NPM Pakke](packages/cli)
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
**xGauntlet** omgiver AI-genereret kode med et kompromisløst verifikations-gauntlet (Linters, Type-checkere, Unit tests, Invariant-tests og Mutationsafprøvning), håndhæver en deterministisk **Zero Ambient Authority WebAssembly policy-kerne** (`wit/gauntlet_policy.wit`) og oversætter rå fejludskrifter til **Actionable Diagnostics** i et feedback-loop, som AI-agenter kan handle direkte på.
|
|
39
|
+
|
|
40
|
+
Bygget i **Rust** for lynhurtig sub-3ms koldstart uden baggrundsdæmoner, og distribueret via **NPX** for øjeblikkelig brug på tværs af **Linux**, **macOS** og **Windows 11**.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## 🚀 Hurtig Start & Installation
|
|
45
|
+
|
|
46
|
+
Kom i gang pĂĄ under 10 sekunder uden forudgĂĄende installation via NPX:
|
|
47
|
+
|
|
48
|
+
### 1. Initialiser dit projekt
|
|
49
|
+
Stil dig i rodmappen på dit projekt (Rust, TypeScript, Python eller polyglot) og kør:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
# Ă…bn dit projektkatalog
|
|
53
|
+
cd ~/sti/til/dit-projekt
|
|
54
|
+
|
|
55
|
+
# Scaffold samtlige in-repo styringsfiler direkte via NPX
|
|
56
|
+
npx xgauntlet init
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
#### 📦 Hvad `xgauntlet init` opretter lokalt i projektet (In-Repo Single Source of Truth):
|
|
60
|
+
| Fil / Mappe | FormĂĄl |
|
|
61
|
+
|---|---|
|
|
62
|
+
| [`gauntlet.toml`](gauntlet.toml) | Deklarativ konfiguration af lintere, typer, tests og verifikationslag |
|
|
63
|
+
| [`CONTEXT.md`](CONTEXT.md) | Domæne-glossary for projektet (Aristoteles' *definitio per genus et differentiam*) |
|
|
64
|
+
| [`CODING_STANDARDS.md`](CODING_STANDARDS.md) | Multi-stack kodestandarder og arkitekturinvarianter |
|
|
65
|
+
| [`spec.md`](spec.md) | Makro-specifikation og system-invarianter |
|
|
66
|
+
| [`tasks/001-bootstrap.md`](tasks/) | Opgavemappe til håndhævelse af task-kontrakter & acceptkriterier |
|
|
67
|
+
| [`docs/adr/`](docs/adr/) | Architecture Decision Records (ADR) til projekt-specifikke beslutninger |
|
|
68
|
+
| [`.agents/AGENTS.md`](.agents/AGENTS.md) | Retningslinjer for AI-agenter, Response HUD og task-management |
|
|
69
|
+
| [`.agents/hooks.json`](.agents/hooks.json) | Pre-Invocation Hook til gatekeeperen |
|
|
70
|
+
| [`CLAUDE.md`](CLAUDE.md) | Retningslinjer og sikkerhedsinvarianter for Claude Code |
|
|
71
|
+
|
|
72
|
+
> [!TIP]
|
|
73
|
+
> **🛡️ Ikke-destruktiv Garanti (Safety First):**
|
|
74
|
+
> `xgauntlet init` overskriver **aldrig** eksisterende filer i dit projekt, medmindre du udtrykkeligt angiver `--force`.
|
|
75
|
+
|
|
76
|
+
### 2. Kør Verifikation & Tjek Evidens
|
|
77
|
+
NĂĄr du eller agenten arbejder pĂĄ en opgave i projektet, afvikles gauntlettet direkte:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
# Kør gauntlet og forseg evidens for en opgave:
|
|
81
|
+
npx xgauntlet verify --task-id 001-bootstrap
|
|
82
|
+
|
|
83
|
+
# Valider kildetræets integritet mod rapporten (drift-kontrol):
|
|
84
|
+
npx xgauntlet check-evidence
|
|
85
|
+
|
|
86
|
+
# Valider opgavespecifikation og CONTEXT.md definitionsformat:
|
|
87
|
+
npx xgauntlet check-spec
|
|
88
|
+
|
|
89
|
+
# Kør miljø- og toolchain-diagnostik:
|
|
90
|
+
npx xgauntlet doctor
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
> [!IMPORTANT]
|
|
94
|
+
> **🚪 Zero Lock-in & Ren Afinstallation:**
|
|
95
|
+
> Alt ligger lokalt i dit Git-træ. xGauntlet efterlader ingen globale dæmoner, baggrundsprocesser eller systemændringer på din maskine.
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## đź§ Pipeline og Gates: SĂĄdan virker det
|
|
100
|
+
|
|
101
|
+
`xGauntlet` arbejder pĂĄ to adskilte niveauer:
|
|
102
|
+
1. **Metodiske retningslinjer (Agent Skills)**: Proceskrav (såsom sokratisk grilling, TDD-disciplin og arkitektur-review), som agenten instrueres i at følge (`grill-me`, `old-coder`, `code-review`).
|
|
103
|
+
2. **Håndhævede software-gates (CLI & In-Memory WASM)**: Deterministiske kontrolpunkter i Rust-koden (`check-spec`, pre-invocation WASM hook, `verify`, `check-evidence` og `check-release`), der fysisk blokerer uautoriserede handlinger med exit-koder og multi-digest integritetskontrol.
|
|
104
|
+
|
|
105
|
+
### Oversigt over udviklingsflowet
|
|
106
|
+
|
|
107
|
+
```text
|
|
108
|
+
[ 1. IDÉAFKLARING ] ──► Metodisk skill (grill-me / grill-with-docs)
|
|
109
|
+
│ (Opdaterer CONTEXT.md & docs/adr/)
|
|
110
|
+
â–Ľ
|
|
111
|
+
[ 2. SPECIFIKATION ] ──► HÅRD GATE: xgauntlet check-spec
|
|
112
|
+
│ (OKF metadata, formål, kriterier, Must NOT, Aristoteles-glossar)
|
|
113
|
+
â–Ľ
|
|
114
|
+
[ 3. TDD & KODNING ] ──► HÅRD GATE: Zero-Ambient-Authority WASM Policy Hook
|
|
115
|
+
│ (Kræver aktiv task for beskyttede stier, forhindrer git push)
|
|
116
|
+
â–Ľ
|
|
117
|
+
[ 4. FLERLAGS VERIFIKATION ] ──► HÅRD GATE: xgauntlet verify
|
|
118
|
+
│ (Kører linters, typer, tests; matematisk pre/post manifestkontrol)
|
|
119
|
+
â–Ľ
|
|
120
|
+
[ 5. KODESTANDARD-REVIEW ] ──► Hybrid skill: code-review & udvikleraccept
|
|
121
|
+
│ (Audit mod CODING_STANDARDS.md)
|
|
122
|
+
â–Ľ
|
|
123
|
+
[ 6. DRIFT-KONTROL ] ──► HÅRD GATE: xgauntlet check-evidence
|
|
124
|
+
│ (Verificerer at workspace matcher rapporten via Git OID hash)
|
|
125
|
+
â–Ľ
|
|
126
|
+
[ 7. RELEASE READINESS ] ──► HÅRD GATE: xgauntlet check-release
|
|
127
|
+
(Versionssynkronisering, CHANGELOG.md og ADR-krydsreferencer)
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### 👥 De 4 AI-roller & Session Handoff
|
|
131
|
+
|
|
132
|
+
For at undgå uendelige review-loops (*bikeshedding*) og bevare et skarpt kontekstvindue, udleder `xGauntlet` automatisk den næste ingeniør-rolle:
|
|
133
|
+
|
|
134
|
+
1. **`Senior Software Engineer (System Architecture & Requirements)`**:
|
|
135
|
+
* Aktiveres ved nye eller `DRAFT`-opgaver. Udfordrer antagelser, definerer negative invarianter (`## đźš« Must NOT`) og eksekverbare kriterier via `xgauntlet check-spec`.
|
|
136
|
+
2. **`Senior Software Engineer (Feature Implementation & Testing)`**:
|
|
137
|
+
* Aktiveres ved `ACTIVE`-opgaver. Driver TDD-cyklussen (`RED` $\to$ `GREEN` $\to$ `REFACTOR`) og forsegler evidens via `xgauntlet verify`.
|
|
138
|
+
3. **`Senior Software Engineer (Independent Code Review & Audit)`**:
|
|
139
|
+
* Tager over i en frisk session. Udfører to-akset granskning langs **Akse A (Standarder)** jf. `CODING_STANDARDS.md` og **Akse B (Krav)** jf. `spec.md`/`tasks/`.
|
|
140
|
+
4. **`Release & Operations Engineer (Release Attestation & Deployment)`**:
|
|
141
|
+
* Tager over når alle opgaver og audits er godkendt. Kører `xgauntlet check-release`, synkroniserer versioner og klargør release.
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## 🎯 Arkitektur & Designprincipper
|
|
146
|
+
|
|
147
|
+
1. **Uncle Bob Clean Architecture & TDD:**
|
|
148
|
+
* Forankret i de 3 Love for TDD, Transformation Priority Premise (TPP) og Single Responsibility Principle (SRP).
|
|
149
|
+
2. **Package-by-Feature Struktur (Screaming Architecture):**
|
|
150
|
+
* Hver komponent er isoleret i en feature-underpakke under `crates/xgauntlet-core/src/features/` med høj sammenhørighed og lav kobling ([ADR 0001](docs/adr/0001-package-by-feature-architecture.md)).
|
|
151
|
+
3. **Zero-Daemon & Sub-3ms Koldstart:**
|
|
152
|
+
* Pure native **Rust** eksekverbar binær. Ingen baggrundsdæmoner, ingen `systemd`/`launchd` services, ingen socket-nedbrud. Hver kommando udføres lynhurtigt in-process.
|
|
153
|
+
4. **Nul Ambient Authority WebAssembly Policy Kerne ([ADR 0007](docs/adr/0007-local-transparent-supervisor-and-wasm-verifier.md)):**
|
|
154
|
+
* Policy-evaluering kompileres fra `wit/gauntlet_policy.wit` til `gauntlet_policy.wasm`.
|
|
155
|
+
* Eksekveres in-memory via indlejret **Wasmtime** med absolut nul adgang til filsystem, netværk, system-ur eller tilfældighedskilder.
|
|
156
|
+
5. **Matematisk Anti-Tamper Manifest (Self-Mutation Invariant):**
|
|
157
|
+
* Pre- og post-test beregning af Git-tree/blob OID digests (immune over for Windows LF/CRLF konverteringer).
|
|
158
|
+
* Hvis kildekode eller testassertions muteres undervejs i testkørslen, afvises verifikationen øjeblikkeligt.
|
|
159
|
+
6. **Two-Tier Evidens & Tillidsmodel ([ADR 0005](docs/adr/0005-two-tier-verification-and-attestation-model.md)):**
|
|
160
|
+
* `LOCAL_UNSUPERVISED`: Lokal deterministisk verifikationsrapport for hurtig feedback og matematisk drift-kontrol (`xgauntlet check-evidence`).
|
|
161
|
+
* `CI_ATTESTED`: Autoritativ, uafviselig Sigstore OIDC / in-toto attestation udstedt i et isoleret CI-miljø.
|
|
162
|
+
7. **Multi-Harness Native Support ([ADR 0004](docs/adr/0004-harness-adapter-slices.md)):**
|
|
163
|
+
* Autonome vertikale slices for **Google Antigravity IDE**, **Claude Code** og **OpenAI Codex**.
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## 🏗️ Mappestruktur (`Package-by-Feature`)
|
|
168
|
+
|
|
169
|
+
```text
|
|
170
|
+
xGauntlet/
|
|
171
|
+
├── tasks/ # Aktive og afsluttede opgavepakker (OKF v0.2)
|
|
172
|
+
├── docs/adr/ # Arkitekturbeslutninger (ADRs 0001-0007)
|
|
173
|
+
├── CONTEXT.md # Domæne-glossary (Aristoteles' genus et differentiam)
|
|
174
|
+
├── CODING_STANDARDS.md # Multi-stack kodestandarder (Rust, TypeScript, Python)
|
|
175
|
+
├── spec.md # Makro-specifikation & system-invarianter
|
|
176
|
+
├── gauntlet.toml # Deklarativ multi-stack konfiguration
|
|
177
|
+
├── wit/ # WebAssembly Interface Types (gauntlet_policy.wit)
|
|
178
|
+
├── Cargo.toml # Cargo Workspace root
|
|
179
|
+
├── package.json # NPM Workspace root
|
|
180
|
+
│
|
|
181
|
+
├── crates/
|
|
182
|
+
│ ├── gauntlet-policy-engine/ # Pure WASM component (wasm32-wasip1/wasip2)
|
|
183
|
+
│ ├── xgauntlet-core/ # Portabel domænemotor (Package-by-Feature)
|
|
184
|
+
│ │ └── src/features/
|
|
185
|
+
│ │ ├── wasm/ # Embedded Wasmtime host integration
|
|
186
|
+
│ │ ├── policy/ # Capability requests & trusted context
|
|
187
|
+
│ │ ├── evidence/ # Git OID SHA-256 manifest & verification-report
|
|
188
|
+
│ │ ├── gauntlet/ # Multi-layer runner, processtyring, timeouts
|
|
189
|
+
│ │ ├── diagnostics/ # Actionable diagnostics parser
|
|
190
|
+
│ │ ├── tasks/ # OKF v0.2 parser & check-spec
|
|
191
|
+
│ │ ├── adapters/ # Vertikale harness-slices (Antigravity, Claude, Codex)
|
|
192
|
+
│ │ ├── config/ # gauntlet.toml loader & schema
|
|
193
|
+
│ │ ├── scaffold/ # Ikke-destruktiv init-motor
|
|
194
|
+
│ │ └── doctor/ # Miljø- og toolchain-diagnostik
|
|
195
|
+
│ │
|
|
196
|
+
│ └── xgauntlet-cli/ # Native CLI executable (xgauntlet)
|
|
197
|
+
│
|
|
198
|
+
└── packages/
|
|
199
|
+
└── cli/ # NPM distributionspakke (xgauntlet)
|
|
200
|
+
└── bin/xgauntlet.js # Zero-dependency platform bootstrapper
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## 🛠️ Fuld CLI Reference
|
|
206
|
+
|
|
207
|
+
### 1. Initialiser Workspace (`init`)
|
|
208
|
+
```bash
|
|
209
|
+
# Standard auto-detektering af stack
|
|
210
|
+
xgauntlet init
|
|
211
|
+
|
|
212
|
+
# Tving overskrivning af eksisterende skabeloner
|
|
213
|
+
xgauntlet init --force
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### 2. Kør Verifikations-Gauntlet (`verify`)
|
|
217
|
+
Kør alle konfigurerede lag, udtræk actionable diagnostics og generer `verification-report.json` og `evidence.md`:
|
|
218
|
+
```bash
|
|
219
|
+
# Standard kørsel bundet til en opgave
|
|
220
|
+
xgauntlet verify --task-id 001-bootstrap
|
|
221
|
+
|
|
222
|
+
# Returner struktureret JSON med actionable diagnostics til LLM / AI-agenter
|
|
223
|
+
xgauntlet verify --diagnostics-json
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### 3. Validering af Evidens & Drift-kontrol (`check-evidence`)
|
|
227
|
+
Verificerer at det aktuelle kildetræ matcher den lokale verifikationsrapport via Git-tree/blob OID digest:
|
|
228
|
+
```bash
|
|
229
|
+
xgauntlet check-evidence
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### 4. Early-Phase Spec & Business Rules Gatekeeper (`check-spec`)
|
|
233
|
+
Mekanisk validering af at opgavespecifikationer indeholder forretningsinvarianter (`Must NOT`), eksekverbare acceptkriterier og overholder [CONTEXT.md](CONTEXT.md) formatet:
|
|
234
|
+
```bash
|
|
235
|
+
xgauntlet check-spec
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### 5. Release Readiness (`check-release`)
|
|
239
|
+
Validerer at versioner matcher på tværs af manifests (`Cargo.toml`, `package.json`), `CHANGELOG.md` og ADR-krydsreferencer:
|
|
240
|
+
```bash
|
|
241
|
+
xgauntlet check-release
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### 6. Workspace Diagnostik (`doctor`)
|
|
245
|
+
Undersøg workspace-konfiguration, stakke og miljøforudsætninger på tværs af Linux, macOS og Windows:
|
|
246
|
+
```bash
|
|
247
|
+
xgauntlet doctor
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
## 🦀 Rust API
|
|
253
|
+
|
|
254
|
+
Du kan integrere `xgauntlet-core` direkte i dine egne Rust test-runners eller agent-værktøjer:
|
|
255
|
+
|
|
256
|
+
```rust
|
|
257
|
+
use std::path::Path;
|
|
258
|
+
use xgauntlet_core::features::evidence::compute_workspace_manifest;
|
|
259
|
+
|
|
260
|
+
// Beregn deterministisk kildemanifest (Git OID SHA-256 multi-digest)
|
|
261
|
+
let manifest = compute_workspace_manifest(Path::new("."))?;
|
|
262
|
+
println!("Source manifest digest: {}", &manifest.source_manifest_digest[..16]);
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## 🏛️ Arkitektur (ADRs)
|
|
268
|
+
|
|
269
|
+
Projektets invariante tekniske valg og designprincipper er dokumenteret i [`docs/adr/`](docs/adr/):
|
|
270
|
+
- 🏛️ **[ADR 0001](docs/adr/0001-package-by-feature-architecture.md)**: Package-by-Feature / Screaming Architecture
|
|
271
|
+
- 🏛️ **[ADR 0002](docs/adr/0002-cryptographic-evidence-authority.md)**: Cryptographic Evidence Authority (Superseded by ADR 0005)
|
|
272
|
+
- 🏛️ **[ADR 0003](docs/adr/0003-surgical-gatekeeper-and-no-remote-push.md)**: Surgical Gatekeeper and No Remote Push
|
|
273
|
+
- 🏛️ **[ADR 0004](docs/adr/0004-harness-adapter-slices.md)**: Vertical Slice Harness Adapters
|
|
274
|
+
- 🏛️ **[ADR 0005](docs/adr/0005-two-tier-verification-and-attestation-model.md)**: Two-Tier Verification and Attestation Model
|
|
275
|
+
- 🏛️ **[ADR 0006](docs/adr/0006-multi-harness-policy-adapter-contract.md)**: Multi-Harness Policy Adapter Contract
|
|
276
|
+
- 🏛️ **[ADR 0007](docs/adr/0007-local-transparent-supervisor-and-wasm-verifier.md)**: Zero-Daemon WASM Policy Verifier
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
## 🙏 Anerkendelse & Inspiration (Credits)
|
|
281
|
+
|
|
282
|
+
`xGauntlet` bygger videre på idéer og pionerarbejde inden for stringent verifikation:
|
|
283
|
+
- **[Robert C. Martin ("Uncle Bob")](https://x.com/unclebobmartin/status/2080257779395154409)**: For TDD, Clean Craftsmanship og idéen om at omgive koden med en uomgængelig *gauntlet*.
|
|
284
|
+
- **[amazingang (old-coder)](https://github.com/amazingang/old-coder)**: For formuleringen af Evidence-First filosofien (*"Trust moves from inspection to constraints"*).
|
|
285
|
+
- **[Matt Pocock](https://github.com/mattpocock)**: For sokratiske workflow-skills (`grill-me`, `grill-with-docs`, `code-review`).
|
|
286
|
+
- **[Bytecode Alliance](https://bytecodealliance.org/)**: For Wasmtime og WebAssembly Component Model med formel Zero Ambient Authority.
|
package/bin/xgauntlet.js
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* xgauntlet - Universal cross-platform verification gauntlet for AI coding agents.
|
|
4
|
+
* Bootstrapper that resolves, caches, or downloads the native Rust engine binary.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { spawnSync, spawn, execFileSync } from 'node:child_process';
|
|
8
|
+
import path from 'node:path';
|
|
9
|
+
import fs from 'node:fs';
|
|
10
|
+
import os from 'node:os';
|
|
11
|
+
import { fileURLToPath } from 'node:url';
|
|
12
|
+
|
|
13
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
14
|
+
const __dirname = path.dirname(__filename);
|
|
15
|
+
const pkgJsonPath = path.resolve(__dirname, '../package.json');
|
|
16
|
+
const pkg = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf8'));
|
|
17
|
+
const VERSION = pkg.version;
|
|
18
|
+
const REPO = 'rolfmadsen/xGauntlet';
|
|
19
|
+
|
|
20
|
+
function getPlatformInfo() {
|
|
21
|
+
const platform = os.platform();
|
|
22
|
+
const arch = os.arch();
|
|
23
|
+
const isWindows = platform === 'win32';
|
|
24
|
+
const binName = isWindows ? 'xgauntlet.exe' : 'xgauntlet';
|
|
25
|
+
|
|
26
|
+
let archiveName = null;
|
|
27
|
+
if (platform === 'linux' && arch === 'x64') {
|
|
28
|
+
archiveName = 'xgauntlet-linux-x64.tar.gz';
|
|
29
|
+
} else if (platform === 'linux' && arch === 'arm64') {
|
|
30
|
+
archiveName = 'xgauntlet-linux-arm64.tar.gz';
|
|
31
|
+
} else if (platform === 'darwin' && arch === 'arm64') {
|
|
32
|
+
archiveName = 'xgauntlet-darwin-arm64.tar.gz';
|
|
33
|
+
} else if (platform === 'darwin' && arch === 'x64') {
|
|
34
|
+
archiveName = 'xgauntlet-darwin-x64.tar.gz';
|
|
35
|
+
} else if (platform === 'win32' && arch === 'x64') {
|
|
36
|
+
archiveName = 'xgauntlet-win32-x64.zip';
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return { platform, arch, isWindows, binName, archiveName };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function getCacheDir() {
|
|
43
|
+
const { isWindows } = getPlatformInfo();
|
|
44
|
+
if (isWindows) {
|
|
45
|
+
const base = process.env.LOCALAPPDATA || path.join(os.homedir(), 'AppData', 'Local');
|
|
46
|
+
return path.join(base, 'xgauntlet', `v${VERSION}`);
|
|
47
|
+
}
|
|
48
|
+
const base = process.env.XDG_CACHE_HOME || path.join(os.homedir(), '.cache');
|
|
49
|
+
return path.join(base, 'xgauntlet', `v${VERSION}`);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function findLocalBinary() {
|
|
53
|
+
const { isWindows, binName } = getPlatformInfo();
|
|
54
|
+
|
|
55
|
+
// 1. Check Cargo target directory in local workspace
|
|
56
|
+
const devCandidates = [
|
|
57
|
+
path.resolve(__dirname, `../../../target/release/${binName}`),
|
|
58
|
+
path.resolve(__dirname, `../../../target/debug/${binName}`),
|
|
59
|
+
];
|
|
60
|
+
|
|
61
|
+
for (const candidate of devCandidates) {
|
|
62
|
+
if (fs.existsSync(candidate)) {
|
|
63
|
+
return candidate;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// 2. Check cached binary in ~/.cache/xgauntlet/vX.Y.Z/
|
|
68
|
+
const cacheDir = getCacheDir();
|
|
69
|
+
const cachedBin = path.join(cacheDir, binName);
|
|
70
|
+
if (fs.existsSync(cachedBin)) {
|
|
71
|
+
return cachedBin;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// 3. Check system PATH (making sure it's not this launcher)
|
|
75
|
+
try {
|
|
76
|
+
const checkCmd = isWindows ? 'where' : 'which';
|
|
77
|
+
const result = spawnSync(checkCmd, ['xgauntlet'], { encoding: 'utf8' });
|
|
78
|
+
if (result.status === 0 && result.stdout) {
|
|
79
|
+
const firstLine = result.stdout.trim().split(/\r?\n/)[0];
|
|
80
|
+
if (firstLine && fs.existsSync(firstLine)) {
|
|
81
|
+
const real = fs.realpathSync(firstLine);
|
|
82
|
+
if (real !== fs.realpathSync(__filename)) {
|
|
83
|
+
return firstLine;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
} catch {
|
|
88
|
+
// Ignore error
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async function downloadAndCacheBinary() {
|
|
95
|
+
const { platform, arch, isWindows, binName, archiveName } = getPlatformInfo();
|
|
96
|
+
|
|
97
|
+
if (!archiveName) {
|
|
98
|
+
throw new Error(`Unsupported platform or architecture: ${platform}-${arch}`);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const cacheDir = getCacheDir();
|
|
102
|
+
const targetBin = path.join(cacheDir, binName);
|
|
103
|
+
|
|
104
|
+
if (fs.existsSync(targetBin)) {
|
|
105
|
+
return targetBin;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const downloadUrl = `https://github.com/${REPO}/releases/download/v${VERSION}/${archiveName}`;
|
|
109
|
+
process.stderr.write(`[xgauntlet] Fetching native engine v${VERSION} for ${platform}-${arch}...\n`);
|
|
110
|
+
|
|
111
|
+
fs.mkdirSync(cacheDir, { recursive: true });
|
|
112
|
+
const tempArchive = path.join(cacheDir, `temp-${Date.now()}-${archiveName}`);
|
|
113
|
+
|
|
114
|
+
try {
|
|
115
|
+
const res = await fetch(downloadUrl, { redirect: 'follow' });
|
|
116
|
+
if (!res.ok) {
|
|
117
|
+
throw new Error(`HTTP ${res.status}: ${res.statusText}`);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const buffer = Buffer.from(await res.arrayBuffer());
|
|
121
|
+
fs.writeFileSync(tempArchive, buffer);
|
|
122
|
+
|
|
123
|
+
if (archiveName.endsWith('.tar.gz')) {
|
|
124
|
+
execFileSync('tar', ['-xzf', tempArchive, '-C', cacheDir], { stdio: 'pipe' });
|
|
125
|
+
} else if (archiveName.endsWith('.zip')) {
|
|
126
|
+
try {
|
|
127
|
+
execFileSync('tar', ['-xf', tempArchive, '-C', cacheDir], { stdio: 'pipe' });
|
|
128
|
+
} catch {
|
|
129
|
+
execFileSync('powershell', ['-NoProfile', '-Command', `Expand-Archive -Path '${tempArchive}' -DestinationPath '${cacheDir}' -Force`], { stdio: 'pipe' });
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (fs.existsSync(tempArchive)) {
|
|
134
|
+
fs.unlinkSync(tempArchive);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (!isWindows && fs.existsSync(targetBin)) {
|
|
138
|
+
fs.chmodSync(targetBin, 0o755);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (fs.existsSync(targetBin)) {
|
|
142
|
+
process.stderr.write(`[xgauntlet] Native engine v${VERSION} ready.\n`);
|
|
143
|
+
return targetBin;
|
|
144
|
+
} else {
|
|
145
|
+
throw new Error(`Extracted archive did not contain expected binary: ${binName}`);
|
|
146
|
+
}
|
|
147
|
+
} catch (err) {
|
|
148
|
+
if (fs.existsSync(tempArchive)) {
|
|
149
|
+
try { fs.unlinkSync(tempArchive); } catch {}
|
|
150
|
+
}
|
|
151
|
+
throw err;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
async function main() {
|
|
156
|
+
const args = process.argv.slice(2);
|
|
157
|
+
let bin = findLocalBinary();
|
|
158
|
+
|
|
159
|
+
if (!bin) {
|
|
160
|
+
try {
|
|
161
|
+
bin = await downloadAndCacheBinary();
|
|
162
|
+
} catch (err) {
|
|
163
|
+
const { platform, arch } = getPlatformInfo();
|
|
164
|
+
if (args[0] === 'status' || args[0] === 'doctor') {
|
|
165
|
+
console.log('[xgauntlet] JavaScript Bootstrapper:');
|
|
166
|
+
console.log(` Platform: ${platform} (${arch})`);
|
|
167
|
+
console.log(` Version: v${VERSION}`);
|
|
168
|
+
console.log(` Engine: NOT_FOUND (${err.message})`);
|
|
169
|
+
console.log(' Notice: Run `cargo build --release` in xGauntlet repo or download v0.1.0 release.');
|
|
170
|
+
process.exit(0);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
console.error(`\x1b[31m[xgauntlet] Error: Could not resolve native engine binary for ${platform}-${arch}.\x1b[0m`);
|
|
174
|
+
console.error(` Details: ${err.message}`);
|
|
175
|
+
console.error(` Tip: You can build it locally with: cargo build --release`);
|
|
176
|
+
console.error(` Or install directly via Cargo: cargo install --path crates/xgauntlet-cli`);
|
|
177
|
+
process.exit(1);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const child = spawn(bin, args, { stdio: 'inherit' });
|
|
182
|
+
child.on('exit', (code, signal) => {
|
|
183
|
+
if (signal) {
|
|
184
|
+
process.kill(process.pid, signal);
|
|
185
|
+
} else {
|
|
186
|
+
process.exit(code ?? 0);
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
main();
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "xgauntlet",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Universal cross-platform verification gauntlet & tamper-proof policy sidecar for AI coding agents",
|
|
5
|
+
"bin": {
|
|
6
|
+
"xgauntlet": "bin/xgauntlet.js",
|
|
7
|
+
"xg": "bin/xgauntlet.js"
|
|
8
|
+
},
|
|
9
|
+
"type": "module",
|
|
10
|
+
"files": [
|
|
11
|
+
"bin",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
14
|
+
"publishConfig": {
|
|
15
|
+
"access": "public"
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"test": "node --test"
|
|
19
|
+
},
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/rolfmadsen/xGauntlet.git",
|
|
23
|
+
"directory": "packages/cli"
|
|
24
|
+
},
|
|
25
|
+
"bugs": {
|
|
26
|
+
"url": "https://github.com/rolfmadsen/xGauntlet/issues"
|
|
27
|
+
},
|
|
28
|
+
"homepage": "https://github.com/rolfmadsen/xGauntlet#readme",
|
|
29
|
+
"keywords": [
|
|
30
|
+
"ai-agent",
|
|
31
|
+
"verification",
|
|
32
|
+
"gauntlet",
|
|
33
|
+
"clean-craftsmanship",
|
|
34
|
+
"cross-platform",
|
|
35
|
+
"evidence"
|
|
36
|
+
],
|
|
37
|
+
"author": "Antigravity Team",
|
|
38
|
+
"license": "MIT",
|
|
39
|
+
"engines": {
|
|
40
|
+
"node": ">=18.0.0"
|
|
41
|
+
}
|
|
42
|
+
}
|