@momentiq/dark-factory-cli 0.1.0-alpha.4 → 0.1.0-alpha.6
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 +138 -10
- package/dist/adapters/critic-result-schema.d.ts +18 -18
- package/dist/cli.js +530 -23
- package/dist/cli.js.map +1 -1
- package/dist/doctor.d.ts +12 -0
- package/dist/doctor.d.ts.map +1 -0
- package/dist/doctor.js +329 -0
- package/dist/doctor.js.map +1 -0
- package/dist/doppler-bootstrap.d.ts +18 -0
- package/dist/doppler-bootstrap.d.ts.map +1 -0
- package/dist/doppler-bootstrap.js +206 -0
- package/dist/doppler-bootstrap.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -45,11 +45,11 @@ critic / aggregator logic lands in Phase F.
|
|
|
45
45
|
|
|
46
46
|
## Status
|
|
47
47
|
|
|
48
|
-
`0.1.0-alpha.
|
|
49
|
-
`scripts/ci/` per cycle 331.1 Phases B
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
48
|
+
`0.1.0-alpha.6` — extracted from `momentiq-ai/sage3c:tools/agent-review/` +
|
|
49
|
+
`scripts/ci/` per cycle 331.1 Phases B–F-LOCAL. Library API is stable;
|
|
50
|
+
binary subcommands cover the full hook-facing surface (review, gate-push,
|
|
51
|
+
doctor, gates, stats) under the subscription cost model. The Phase F
|
|
52
|
+
`df critic` subcommand is the CI cold-path API-key version.
|
|
53
53
|
|
|
54
54
|
## Install
|
|
55
55
|
|
|
@@ -98,6 +98,14 @@ df attribute-pr # env-driven; needs PR_NUMBER, PR_NODE_ID, PR_BODY_FILE, PROJEC
|
|
|
98
98
|
df audit stats --path .git/agent-reviews/_runs.ndjson
|
|
99
99
|
df admit-pr --files-stdin # newline-separated file paths on stdin
|
|
100
100
|
df admit-pr --files docs/roadmap/cycles/cycle331.md,packages/cli/src/cli.ts
|
|
101
|
+
|
|
102
|
+
# Phase F-LOCAL hook-facing subcommands (subscription cost model).
|
|
103
|
+
df review --commit HEAD --profile local --foreground
|
|
104
|
+
df gate-push # local pre-push, reads stdin
|
|
105
|
+
df gate-push --commit HEAD --ci # CI replay
|
|
106
|
+
df doctor --profile local # env + per-adapter auth check
|
|
107
|
+
df gates # static gates, no LLM
|
|
108
|
+
df stats # alias for `df audit stats`
|
|
101
109
|
```
|
|
102
110
|
|
|
103
111
|
> **Note on `--use-bundled-default-spec`**: the bundled `spec-default.yaml`
|
|
@@ -109,11 +117,131 @@ df admit-pr --files docs/roadmap/cycles/cycle331.md,packages/cli/src/cli.ts
|
|
|
109
117
|
> against an arbitrary repo will surface drift against contexts that
|
|
110
118
|
> don't exist there.
|
|
111
119
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
120
|
+
## For consumer repos — hook wiring + subscription cost model
|
|
121
|
+
|
|
122
|
+
The Phase F-LOCAL subcommands (`review`, `gate-push`, `doctor`, `gates`,
|
|
123
|
+
`stats`) are designed to power consumer repos' `.husky/post-commit` and
|
|
124
|
+
`.husky/pre-push` hooks. The **cost model** is critical: per-commit critic
|
|
125
|
+
invocations from API tokens cost $1000s/week on a busy repo, while
|
|
126
|
+
subscription-auth invocations (using the developer's existing Cursor /
|
|
127
|
+
Codex / Claude CLI logins) are flat-rate.
|
|
128
|
+
|
|
129
|
+
### Subscription auth — what runs on each git push
|
|
130
|
+
|
|
131
|
+
| Subcommand | Hook | Cost model |
|
|
132
|
+
| --- | --- | --- |
|
|
133
|
+
| `df review` | `.husky/post-commit` (background) | **Subscription** — consumes Cursor / Codex / Claude CLI logins via the active profile's `auth` pins. No API spend by default. |
|
|
134
|
+
| `df gate-push` | `.husky/pre-push` | Free — reads pre-existing artifacts, no LLM calls. |
|
|
135
|
+
| `df doctor` | None (operator-run) | Free. Validates that per-adapter auth source is reachable. |
|
|
136
|
+
| `df gates` | None (operator-run) | Free. Runs static quality gates per `validation.requiredQualityGates`. |
|
|
137
|
+
| `df stats` | None (operator-run) | Free. Reads `.git/agent-reviews/_runs.ndjson`. |
|
|
138
|
+
|
|
139
|
+
CI cold-path (the 4 vendor API keys: `CURSOR_API_KEY`, `CODEX_API_KEY`,
|
|
140
|
+
`GEMINI_API_KEY`, `XAI_API_KEY`) is intentionally the fallback only —
|
|
141
|
+
used when:
|
|
142
|
+
|
|
143
|
+
- The first PR on a fresh repo runs critic before any developer has run
|
|
144
|
+
hooks locally.
|
|
145
|
+
- A hook bypass landed and the CI gate needs to re-evaluate.
|
|
146
|
+
- The developer hasn't logged in to a vendor CLI yet
|
|
147
|
+
(`cursor login` / `codex login` / Claude desktop OAuth).
|
|
148
|
+
|
|
149
|
+
### `.agent-review/config.json` — the profile that pins subscription auth
|
|
150
|
+
|
|
151
|
+
```json
|
|
152
|
+
{
|
|
153
|
+
"version": 2,
|
|
154
|
+
"critics": [
|
|
155
|
+
{ "id": "cursor-local-chief-engineer", "adapter": "cursor-sdk", ... },
|
|
156
|
+
{ "id": "codex-local-chief-engineer", "adapter": "codex-sdk", ... }
|
|
157
|
+
],
|
|
158
|
+
"profiles": {
|
|
159
|
+
"local": {
|
|
160
|
+
"criticIds": ["cursor-local-chief-engineer", "codex-local-chief-engineer"],
|
|
161
|
+
"quorum": 1,
|
|
162
|
+
"auth": {
|
|
163
|
+
"codex-local-chief-engineer": "chatgpt"
|
|
164
|
+
}
|
|
165
|
+
},
|
|
166
|
+
"cloud": {
|
|
167
|
+
"criticIds": ["cursor-local-chief-engineer", "codex-local-chief-engineer"],
|
|
168
|
+
"quorum": 2,
|
|
169
|
+
"auth": {
|
|
170
|
+
"codex-local-chief-engineer": "api"
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
The `local` profile pins `codex` to `"chatgpt"` — the Codex SDK will use
|
|
178
|
+
`~/.codex/auth.json` (from `codex login`) and **NOT** fall back to
|
|
179
|
+
`CODEX_API_KEY` even if it's set in env. This is the firewall against
|
|
180
|
+
accidental API-token billing.
|
|
181
|
+
|
|
182
|
+
`df doctor --profile local` validates the configured subscription source
|
|
183
|
+
is reachable. Run it after first-time setup.
|
|
184
|
+
|
|
185
|
+
### Sample `.husky/post-commit`
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
#!/usr/bin/env bash
|
|
189
|
+
set -euo pipefail
|
|
190
|
+
if [[ "${AGENT_REVIEW_SKIP:-}" == "1" ]]; then
|
|
191
|
+
echo "df: skipped by AGENT_REVIEW_SKIP=1"
|
|
192
|
+
exit 0
|
|
193
|
+
fi
|
|
194
|
+
SHA="$(git rev-parse HEAD)"
|
|
195
|
+
COMMON_DIR="$(git rev-parse --git-common-dir 2>/dev/null || echo .git)"
|
|
196
|
+
mkdir -p "${COMMON_DIR}/agent-reviews"
|
|
197
|
+
LOG_FILE="${COMMON_DIR}/agent-reviews/post-commit.log"
|
|
198
|
+
# Detached background invocation — does not block the commit.
|
|
199
|
+
AGENT_REVIEW_PROFILE=local nohup npx df review --commit "${SHA}" \
|
|
200
|
+
>"${LOG_FILE}" 2>&1 </dev/null &
|
|
201
|
+
disown || true
|
|
202
|
+
echo "df: review started for ${SHA:0:12} (log: ${LOG_FILE})"
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### Sample `.husky/pre-push`
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
#!/usr/bin/env bash
|
|
209
|
+
set -euo pipefail
|
|
210
|
+
if [[ -n "${AGENT_REVIEW_BYPASS:-}" ]]; then
|
|
211
|
+
echo "df: pre-push gate BYPASSED — reason: ${AGENT_REVIEW_BYPASS}" >&2
|
|
212
|
+
exit 0
|
|
213
|
+
fi
|
|
214
|
+
npx df gate-push --profile local
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Doppler bootstrap (optional)
|
|
218
|
+
|
|
219
|
+
For repos that use Doppler to manage `DOPPLER_TOKEN`, place it in
|
|
220
|
+
`<main-checkout>/.env` and the bootstrap loader will hoist it from any
|
|
221
|
+
worktree:
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
echo 'DOPPLER_TOKEN=dp.st.dev.…' > <main-checkout>/.env
|
|
225
|
+
chmod 600 <main-checkout>/.env
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
The default allowlist is **just `DOPPLER_TOKEN`**. Consumers that use
|
|
229
|
+
project-scoped service-token vars (e.g. `DOPPLER_SERVICE_TOKEN_ACME`) can
|
|
230
|
+
pass a custom allowlist to `loadDopplerBootstrapEnv()` via the library
|
|
231
|
+
API — see `packages/cli/src/doppler-bootstrap.ts` for the
|
|
232
|
+
`serviceTokenAlias` parameter that bridges to `DOPPLER_TOKEN`.
|
|
233
|
+
|
|
234
|
+
### First-time setup checklist
|
|
235
|
+
|
|
236
|
+
1. `npm install --ignore-scripts @momentiq/dark-factory-cli`
|
|
237
|
+
2. Add `.agent-review/config.json` with the `local` profile (above).
|
|
238
|
+
3. Add `.husky/post-commit` + `.husky/pre-push` (samples above).
|
|
239
|
+
4. `git config --local core.hooksPath .husky`
|
|
240
|
+
5. `cursor login` / `codex login` (or Claude desktop OAuth) on the workstation.
|
|
241
|
+
6. Run `df doctor --profile local` — should report all OK.
|
|
242
|
+
7. Commit something — observe `.git/agent-reviews/<sha>.json` arrives.
|
|
243
|
+
8. (Optional) Set up CI with `CURSOR_API_KEY` / `CODEX_API_KEY` /
|
|
244
|
+
`GEMINI_API_KEY` / `XAI_API_KEY` as repo secrets for the cold path.
|
|
117
245
|
|
|
118
246
|
## System requirements
|
|
119
247
|
|
|
@@ -51,30 +51,30 @@ export declare const CriticResultZodSchema: z.ZodObject<{
|
|
|
51
51
|
routeId: z.ZodOptional<z.ZodString>;
|
|
52
52
|
justification: z.ZodOptional<z.ZodString>;
|
|
53
53
|
}, "strip", z.ZodTypeAny, {
|
|
54
|
+
evidence: string;
|
|
54
55
|
severity: string;
|
|
55
56
|
category: string;
|
|
56
|
-
evidence: string;
|
|
57
57
|
impact: string;
|
|
58
58
|
requiredFix: string;
|
|
59
59
|
symbol?: string | undefined;
|
|
60
|
+
routeId?: string | undefined;
|
|
60
61
|
file?: string | undefined;
|
|
61
62
|
line?: number | undefined;
|
|
62
63
|
manifestoSection?: string | undefined;
|
|
63
64
|
evidencePath?: string | undefined;
|
|
64
|
-
routeId?: string | undefined;
|
|
65
65
|
justification?: string | undefined;
|
|
66
66
|
}, {
|
|
67
|
+
evidence: string;
|
|
67
68
|
severity: string;
|
|
68
69
|
category: string;
|
|
69
|
-
evidence: string;
|
|
70
70
|
impact: string;
|
|
71
71
|
requiredFix: string;
|
|
72
72
|
symbol?: string | undefined;
|
|
73
|
+
routeId?: string | undefined;
|
|
73
74
|
file?: string | undefined;
|
|
74
75
|
line?: number | undefined;
|
|
75
76
|
manifestoSection?: string | undefined;
|
|
76
77
|
evidencePath?: string | undefined;
|
|
77
|
-
routeId?: string | undefined;
|
|
78
78
|
justification?: string | undefined;
|
|
79
79
|
}>, "many">;
|
|
80
80
|
validation: z.ZodObject<{
|
|
@@ -89,16 +89,16 @@ export declare const CriticResultZodSchema: z.ZodObject<{
|
|
|
89
89
|
}, "strip", z.ZodTypeAny, {
|
|
90
90
|
exitCode: number;
|
|
91
91
|
command: string;
|
|
92
|
-
durationMs: number;
|
|
93
92
|
logExcerpt: string;
|
|
93
|
+
durationMs: number;
|
|
94
94
|
startedAt: string;
|
|
95
95
|
finishedAt: string;
|
|
96
96
|
routeId?: string | undefined;
|
|
97
97
|
}, {
|
|
98
98
|
exitCode: number;
|
|
99
99
|
command: string;
|
|
100
|
-
durationMs: number;
|
|
101
100
|
logExcerpt: string;
|
|
101
|
+
durationMs: number;
|
|
102
102
|
startedAt: string;
|
|
103
103
|
finishedAt: string;
|
|
104
104
|
routeId?: string | undefined;
|
|
@@ -108,8 +108,8 @@ export declare const CriticResultZodSchema: z.ZodObject<{
|
|
|
108
108
|
qualityGateResults: {
|
|
109
109
|
exitCode: number;
|
|
110
110
|
command: string;
|
|
111
|
-
durationMs: number;
|
|
112
111
|
logExcerpt: string;
|
|
112
|
+
durationMs: number;
|
|
113
113
|
startedAt: string;
|
|
114
114
|
finishedAt: string;
|
|
115
115
|
routeId?: string | undefined;
|
|
@@ -119,8 +119,8 @@ export declare const CriticResultZodSchema: z.ZodObject<{
|
|
|
119
119
|
qualityGateResults: {
|
|
120
120
|
exitCode: number;
|
|
121
121
|
command: string;
|
|
122
|
-
durationMs: number;
|
|
123
122
|
logExcerpt: string;
|
|
123
|
+
durationMs: number;
|
|
124
124
|
startedAt: string;
|
|
125
125
|
finishedAt: string;
|
|
126
126
|
routeId?: string | undefined;
|
|
@@ -133,65 +133,65 @@ export declare const CriticResultZodSchema: z.ZodObject<{
|
|
|
133
133
|
qualityGateResults: {
|
|
134
134
|
exitCode: number;
|
|
135
135
|
command: string;
|
|
136
|
-
durationMs: number;
|
|
137
136
|
logExcerpt: string;
|
|
137
|
+
durationMs: number;
|
|
138
138
|
startedAt: string;
|
|
139
139
|
finishedAt: string;
|
|
140
140
|
routeId?: string | undefined;
|
|
141
141
|
}[];
|
|
142
142
|
qualityGatesMissing: string[];
|
|
143
143
|
};
|
|
144
|
-
verdict: string;
|
|
145
144
|
status: string;
|
|
146
145
|
requiresHumanJudgment: boolean;
|
|
147
146
|
summary: string;
|
|
147
|
+
confidence: string;
|
|
148
|
+
verdict: string;
|
|
148
149
|
findings: {
|
|
150
|
+
evidence: string;
|
|
149
151
|
severity: string;
|
|
150
152
|
category: string;
|
|
151
|
-
evidence: string;
|
|
152
153
|
impact: string;
|
|
153
154
|
requiredFix: string;
|
|
154
155
|
symbol?: string | undefined;
|
|
156
|
+
routeId?: string | undefined;
|
|
155
157
|
file?: string | undefined;
|
|
156
158
|
line?: number | undefined;
|
|
157
159
|
manifestoSection?: string | undefined;
|
|
158
160
|
evidencePath?: string | undefined;
|
|
159
|
-
routeId?: string | undefined;
|
|
160
161
|
justification?: string | undefined;
|
|
161
162
|
}[];
|
|
162
|
-
confidence: string;
|
|
163
163
|
}, {
|
|
164
164
|
validation: {
|
|
165
165
|
qualityGateResults: {
|
|
166
166
|
exitCode: number;
|
|
167
167
|
command: string;
|
|
168
|
-
durationMs: number;
|
|
169
168
|
logExcerpt: string;
|
|
169
|
+
durationMs: number;
|
|
170
170
|
startedAt: string;
|
|
171
171
|
finishedAt: string;
|
|
172
172
|
routeId?: string | undefined;
|
|
173
173
|
}[];
|
|
174
174
|
qualityGatesMissing: string[];
|
|
175
175
|
};
|
|
176
|
-
verdict: string;
|
|
177
176
|
status: string;
|
|
178
177
|
requiresHumanJudgment: boolean;
|
|
179
178
|
summary: string;
|
|
179
|
+
confidence: string;
|
|
180
|
+
verdict: string;
|
|
180
181
|
findings: {
|
|
182
|
+
evidence: string;
|
|
181
183
|
severity: string;
|
|
182
184
|
category: string;
|
|
183
|
-
evidence: string;
|
|
184
185
|
impact: string;
|
|
185
186
|
requiredFix: string;
|
|
186
187
|
symbol?: string | undefined;
|
|
188
|
+
routeId?: string | undefined;
|
|
187
189
|
file?: string | undefined;
|
|
188
190
|
line?: number | undefined;
|
|
189
191
|
manifestoSection?: string | undefined;
|
|
190
192
|
evidencePath?: string | undefined;
|
|
191
|
-
routeId?: string | undefined;
|
|
192
193
|
justification?: string | undefined;
|
|
193
194
|
}[];
|
|
194
|
-
confidence: string;
|
|
195
195
|
}>;
|
|
196
196
|
export type CriticResultModelEnvelope = z.infer<typeof CriticResultZodSchema>;
|
|
197
197
|
/**
|