@haystackeditor/cli 0.15.31 → 0.16.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 +111 -60
- package/dist/assets/hooks/scripts/commit-msg.sh +3 -0
- package/dist/assets/hooks/scripts/post-commit.sh +3 -0
- package/dist/assets/hooks/scripts/pre-commit.sh +11 -6
- package/dist/assets/hooks/scripts/pre-push.sh +3 -0
- package/dist/assets/hooks/scripts/prepare-commit-msg.sh +3 -0
- package/dist/commands/case-batch-contract.js +608 -0
- package/dist/commands/case-batch.js +713 -0
- package/dist/commands/cloud-verifier-identity-census.js +5 -2
- package/dist/commands/combination-search-hook.js +139 -0
- package/dist/commands/dismiss.js +2 -1
- package/dist/commands/hooks.js +66 -7
- package/dist/commands/install-session-hooks.js +131 -44
- package/dist/commands/policy.js +32 -45
- package/dist/commands/precompute-delivery.js +6 -1
- package/dist/commands/scaffold-provisional-universe.js +8 -10
- package/dist/commands/setup.js +32 -10
- package/dist/commands/submit.js +7 -2
- package/dist/commands/telemetry.js +17 -2
- package/dist/commands/triage.js +2 -1
- package/dist/commands/verify-explore.js +1 -0
- package/dist/commands/verify-hosted-mcp.js +3 -12
- package/dist/commands/verify-hosted-reproducibility.js +49 -547
- package/dist/commands/verify-hosted.js +66 -168
- package/dist/commands/verify-precompute.js +57 -10
- package/dist/commands/verify.js +51 -139
- package/dist/index.js +238 -350
- package/dist/lazy.js +8 -0
- package/dist/schema.js +1 -0
- package/dist/tools/detect.js +3 -24
- package/dist/triage/prompts.js +46 -45
- package/dist/triage/runner.js +119 -33
- package/dist/types.js +3 -3
- package/dist/utils/auth.js +14 -2
- package/dist/utils/git.js +60 -29
- package/dist/utils/github-api.js +14 -1
- package/dist/utils/haystack-api.js +26 -7
- package/dist/utils/hooks.js +43 -6
- package/dist/utils/prompter.js +25 -10
- package/dist/utils/safe-write.js +31 -0
- package/dist/utils/secret-paths.js +115 -0
- package/dist/utils/secrets.js +0 -1
- package/dist/utils/telemetry.js +34 -14
- package/dist/utils/update-check.js +151 -0
- package/package.json +18 -14
- package/schemas/case-batch.v1.json +184 -0
- package/schemas/cloud-verifier.v1.json +55 -100
- package/dist/commands/ask.d.ts +0 -14
- package/dist/commands/cloud-verifier-behaviors.d.ts +0 -27
- package/dist/commands/cloud-verifier-data-store-census.d.ts +0 -47
- package/dist/commands/cloud-verifier-data-store-drift.d.ts +0 -42
- package/dist/commands/cloud-verifier-identity-census.d.ts +0 -88
- package/dist/commands/cloud-verifier-materialization.d.ts +0 -16
- package/dist/commands/cloud-verifier-pascal-selector-census.d.ts +0 -29
- package/dist/commands/cloud-verifier-python-manifest-selector-census.d.ts +0 -27
- package/dist/commands/cloud-verifier-specialized-operational-census.d.ts +0 -51
- package/dist/commands/cloud-verifier-universe.d.ts +0 -31
- package/dist/commands/config.d.ts +0 -46
- package/dist/commands/design-verify.d.ts +0 -33
- package/dist/commands/dismiss.d.ts +0 -29
- package/dist/commands/hooks.d.ts +0 -13
- package/dist/commands/inbox.d.ts +0 -65
- package/dist/commands/init.d.ts +0 -10
- package/dist/commands/install-session-hooks.d.ts +0 -17
- package/dist/commands/login.d.ts +0 -8
- package/dist/commands/mcp.d.ts +0 -1
- package/dist/commands/policy.d.ts +0 -31
- package/dist/commands/pr-status.d.ts +0 -144
- package/dist/commands/pr.d.ts +0 -40
- package/dist/commands/precompute-delivery-contract.d.ts +0 -68
- package/dist/commands/precompute-delivery.d.ts +0 -20
- package/dist/commands/prepare-universe-review.d.ts +0 -115
- package/dist/commands/production-source-deny-policy.d.ts +0 -15
- package/dist/commands/request-review.d.ts +0 -26
- package/dist/commands/review.d.ts +0 -25
- package/dist/commands/rules.d.ts +0 -4
- package/dist/commands/scaffold-provisional-universe.d.ts +0 -468
- package/dist/commands/schema-cmd.d.ts +0 -2
- package/dist/commands/setup.d.ts +0 -28
- package/dist/commands/skills.d.ts +0 -8
- package/dist/commands/status.d.ts +0 -4
- package/dist/commands/submit.d.ts +0 -30
- package/dist/commands/system-map.d.ts +0 -42
- package/dist/commands/telemetry.d.ts +0 -53
- package/dist/commands/tokens.d.ts +0 -14
- package/dist/commands/triage.d.ts +0 -35
- package/dist/commands/verify-core.d.ts +0 -449
- package/dist/commands/verify-core.js +0 -789
- package/dist/commands/verify-explore.d.ts +0 -14
- package/dist/commands/verify-history.d.ts +0 -14
- package/dist/commands/verify-hosted-mcp.d.ts +0 -12
- package/dist/commands/verify-hosted-reproducibility.d.ts +0 -90
- package/dist/commands/verify-hosted.d.ts +0 -92
- package/dist/commands/verify-mcp.d.ts +0 -8
- package/dist/commands/verify-mcp.js +0 -517
- package/dist/commands/verify-ops.d.ts +0 -158
- package/dist/commands/verify-ops.js +0 -1148
- package/dist/commands/verify-precompute.d.ts +0 -30
- package/dist/commands/verify-reproducibility.d.ts +0 -85
- package/dist/commands/verify-reproducibility.js +0 -494
- package/dist/commands/verify-reseal.d.ts +0 -9
- package/dist/commands/verify-reseal.js +0 -148
- package/dist/commands/verify-sandboxes.d.ts +0 -95
- package/dist/commands/verify-sandboxes.js +0 -352
- package/dist/commands/verify.d.ts +0 -28
- package/dist/commands/webhooks.d.ts +0 -30
- package/dist/index.d.ts +0 -22
- package/dist/schema.d.ts +0 -28
- package/dist/states.d.ts +0 -29
- package/dist/tools/detect.d.ts +0 -50
- package/dist/triage/prompts.d.ts +0 -24
- package/dist/triage/runner.d.ts +0 -34
- package/dist/triage/types.d.ts +0 -42
- package/dist/types/verify-history.d.ts +0 -38
- package/dist/types.d.ts +0 -1684
- package/dist/utils/action-output.d.ts +0 -24
- package/dist/utils/analysis-api.d.ts +0 -187
- package/dist/utils/auth.d.ts +0 -79
- package/dist/utils/config.d.ts +0 -24
- package/dist/utils/design-verifier-api.d.ts +0 -208
- package/dist/utils/design-verifier-history.d.ts +0 -46
- package/dist/utils/design-verifier-result.d.ts +0 -74
- package/dist/utils/detect.d.ts +0 -43
- package/dist/utils/git.d.ts +0 -135
- package/dist/utils/github-api.d.ts +0 -104
- package/dist/utils/haystack-api.d.ts +0 -37
- package/dist/utils/hooks.d.ts +0 -12
- package/dist/utils/pending-state.d.ts +0 -40
- package/dist/utils/pr-ref.d.ts +0 -27
- package/dist/utils/prompter.d.ts +0 -85
- package/dist/utils/secrets.d.ts +0 -47
- package/dist/utils/telemetry.d.ts +0 -19
- /package/dist/commands/{precompute-delivery-worker.d.ts → combination-search-hook-contract.js} +0 -0
package/dist/commands/verify.js
CHANGED
|
@@ -1,152 +1,64 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
import chalk from 'chalk';
|
|
5
|
-
import { setVerifyToken, verifyAuthHeaders } from './verify-core.js';
|
|
6
|
-
const DEFAULT_CONTROL_PLANE = 'http://127.0.0.1:3000';
|
|
7
|
-
export const VERIFY_SPECIMENS = new Set(['all', 'posthog-js-478', 'analytics-js-255']);
|
|
8
|
-
export function parseStartRunResponse(raw) {
|
|
9
|
-
let parsed;
|
|
1
|
+
import { execFileSync } from 'node:child_process';
|
|
2
|
+
import { parseHostedRepository, verifyHostedStartCommand } from './verify-hosted.js';
|
|
3
|
+
function git(args, message) {
|
|
10
4
|
try {
|
|
11
|
-
|
|
5
|
+
return execFileSync('git', args, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] }).trim();
|
|
12
6
|
}
|
|
13
7
|
catch {
|
|
14
|
-
throw new Error(
|
|
8
|
+
throw new Error(message);
|
|
15
9
|
}
|
|
16
|
-
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
17
|
-
throw new Error('Verifier returned an invalid response object.');
|
|
18
|
-
}
|
|
19
|
-
const response = parsed;
|
|
20
|
-
const requiredString = (field) => {
|
|
21
|
-
const value = response[field];
|
|
22
|
-
if (typeof value !== 'string' || value.trim() === '') {
|
|
23
|
-
throw new Error(`Verifier response is missing a valid ${field}.`);
|
|
24
|
-
}
|
|
25
|
-
return value;
|
|
26
|
-
};
|
|
27
|
-
return {
|
|
28
|
-
runId: requiredString('runId'),
|
|
29
|
-
status: requiredString('status'),
|
|
30
|
-
resultsUrl: requiredString('resultsUrl'),
|
|
31
|
-
};
|
|
32
10
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
let parsed;
|
|
11
|
+
function originRepository() {
|
|
12
|
+
const remote = git(['remote', 'get-url', 'origin'], 'Could not read origin; pass --repo owner/repo.');
|
|
13
|
+
let path;
|
|
37
14
|
try {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
return
|
|
42
|
-
}
|
|
43
|
-
if (parsed
|
|
44
|
-
&& typeof parsed === 'object'
|
|
45
|
-
&& !Array.isArray(parsed)
|
|
46
|
-
&& typeof parsed.error === 'string'
|
|
47
|
-
&& parsed.error.trim() !== '') {
|
|
48
|
-
return parsed.error;
|
|
49
|
-
}
|
|
50
|
-
return `JSON error response omitted a string error; raw body: ${raw}`;
|
|
51
|
-
}
|
|
52
|
-
function openResults(url) {
|
|
53
|
-
const platform = process.platform;
|
|
54
|
-
const command = platform === 'darwin' ? 'open' : platform === 'win32' ? 'cmd' : 'xdg-open';
|
|
55
|
-
const args = platform === 'win32' ? ['/c', 'start', '', url] : [url];
|
|
56
|
-
const child = spawn(command, args, { detached: true, stdio: 'ignore' });
|
|
57
|
-
child.unref();
|
|
58
|
-
}
|
|
59
|
-
async function readIntentTranscript(path) {
|
|
60
|
-
if (!path)
|
|
61
|
-
return undefined;
|
|
62
|
-
const absolutePath = resolve(path);
|
|
63
|
-
try {
|
|
64
|
-
return await readFile(absolutePath, 'utf8');
|
|
65
|
-
}
|
|
66
|
-
catch (error) {
|
|
67
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
68
|
-
throw new Error(`Could not read intent transcript at ${absolutePath}: ${message}`);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
export async function startVerificationRun(specimenArg, options) {
|
|
72
|
-
const specimen = specimenArg || 'all';
|
|
73
|
-
if (!VERIFY_SPECIMENS.has(specimen)) {
|
|
74
|
-
throw new Error(`Unknown or unreproduced specimen "${specimen}". Choose all, posthog-js-478, or analytics-js-255.`);
|
|
15
|
+
path = remote.includes('://')
|
|
16
|
+
? new URL(remote).pathname.replace(/^\//, '')
|
|
17
|
+
: remote.match(/^[^@/]+@[^:]+:(.+)$/)?.[1] ?? '';
|
|
18
|
+
return parseHostedRepository(path.replace(/\.git$/, '')).fullName;
|
|
75
19
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
.replace(/\/+$/, '');
|
|
79
|
-
const intentTranscript = await readIntentTranscript(options.intentTranscript);
|
|
80
|
-
let response;
|
|
81
|
-
try {
|
|
82
|
-
response = await fetch(`${server}/api/cloud-verifier/runs`, {
|
|
83
|
-
method: 'POST',
|
|
84
|
-
headers: { 'content-type': 'application/json', ...verifyAuthHeaders() },
|
|
85
|
-
body: JSON.stringify({
|
|
86
|
-
specimen,
|
|
87
|
-
repoPath: options.repo ? resolve(options.repo) : undefined,
|
|
88
|
-
baseRef: options.base,
|
|
89
|
-
headRef: options.head,
|
|
90
|
-
intentTranscript,
|
|
91
|
-
planSourceRunId: options.planSourceRunId,
|
|
92
|
-
}),
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
catch (error) {
|
|
96
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
97
|
-
throw new Error(`Could not reach the Haystack verifier at ${server}. Start the demo control plane with \`pnpm dev\` and retry. ${message}`);
|
|
98
|
-
}
|
|
99
|
-
const raw = await response.text();
|
|
100
|
-
if (response.status === 401) {
|
|
101
|
-
throw new Error(`Control plane at ${server} requires a token (HTTP 401). Pass --token or set HAYSTACK_VERIFY_TOKEN.`);
|
|
102
|
-
}
|
|
103
|
-
if (!response.ok) {
|
|
104
|
-
const reason = verifierErrorReason(raw, response.headers.get('content-type'));
|
|
105
|
-
throw new Error(`Verifier rejected the run (${response.status}): ${reason}`);
|
|
20
|
+
catch {
|
|
21
|
+
throw new Error('Could not determine owner/repo from origin; pass --repo owner/repo.');
|
|
106
22
|
}
|
|
107
|
-
return parseStartRunResponse(raw);
|
|
108
23
|
}
|
|
109
|
-
export
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
24
|
+
export function resolveVerifyRepository(options) {
|
|
25
|
+
const repo = options.repo ?? originRepository();
|
|
26
|
+
let head = options.head;
|
|
27
|
+
if (head === undefined) {
|
|
28
|
+
head = git(['rev-parse', '--verify', 'HEAD^{commit}'], 'Could not read HEAD; run inside a git checkout or pass --head.');
|
|
29
|
+
// The fleet fetches from the GitHub origin, so only origin's branches
|
|
30
|
+
// prove the commit is reachable there; another remote does not.
|
|
31
|
+
const originBranches = git(['for-each-ref', '--format=%(refname)', '--contains', head, 'refs/remotes/origin/'], 'Could not check origin branches for HEAD.');
|
|
32
|
+
if (!originBranches)
|
|
33
|
+
throw new Error('Push HEAD to origin before running haystack verify.');
|
|
34
|
+
}
|
|
35
|
+
let base = options.base;
|
|
36
|
+
if (base === undefined) {
|
|
37
|
+
let defaultBranch = 'origin/main';
|
|
38
|
+
try {
|
|
39
|
+
defaultBranch = git(['symbolic-ref', '--short', 'refs/remotes/origin/HEAD'], 'Could not read origin/HEAD.');
|
|
113
40
|
}
|
|
114
|
-
|
|
115
|
-
|
|
41
|
+
catch {
|
|
42
|
+
// Repositories without origin/HEAD use origin/main.
|
|
116
43
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
base: options.base,
|
|
121
|
-
head: options.head,
|
|
122
|
-
intentFile: options.intentFile,
|
|
123
|
-
idempotencyKey: options.idempotencyKey,
|
|
124
|
-
account: options.account,
|
|
125
|
-
wait: options.wait,
|
|
126
|
-
interval: options.interval,
|
|
127
|
-
timeout: options.timeout,
|
|
128
|
-
json: options.json,
|
|
129
|
-
});
|
|
130
|
-
return;
|
|
131
|
-
}
|
|
132
|
-
if (!options.json) {
|
|
133
|
-
console.error(chalk.dim('Preparing the cloud verification run…'));
|
|
134
|
-
}
|
|
135
|
-
const started = await startVerificationRun(specimenArg, options);
|
|
136
|
-
if (options.json) {
|
|
137
|
-
process.stdout.write(`${JSON.stringify({
|
|
138
|
-
schema_version: '1.0.0',
|
|
139
|
-
run_id: started.runId,
|
|
140
|
-
status: started.status,
|
|
141
|
-
results_url: started.resultsUrl,
|
|
142
|
-
}, null, 2)}\n`);
|
|
143
|
-
}
|
|
144
|
-
else {
|
|
145
|
-
console.log('');
|
|
146
|
-
console.log(`${chalk.green('✓')} Verification started: ${chalk.bold(started.runId)}`);
|
|
147
|
-
console.log(` ${chalk.dim('Results:')} ${chalk.cyan(started.resultsUrl)}`);
|
|
148
|
-
}
|
|
149
|
-
if (options.open !== false) {
|
|
150
|
-
openResults(started.resultsUrl);
|
|
44
|
+
// The base belongs to the head being verified, which may be an explicit
|
|
45
|
+
// --head rather than the working tree.
|
|
46
|
+
base = git(['merge-base', head, defaultBranch], `Could not find the merge base of ${head} with ${defaultBranch}; fetch origin or pass --base.`);
|
|
151
47
|
}
|
|
48
|
+
return { repo, base, head };
|
|
49
|
+
}
|
|
50
|
+
export async function verifyCommand(options) {
|
|
51
|
+
const { repo, base, head } = resolveVerifyRepository(options);
|
|
52
|
+
await verifyHostedStartCommand(repo, {
|
|
53
|
+
provider: 'haystack',
|
|
54
|
+
base,
|
|
55
|
+
head,
|
|
56
|
+
intentFile: options.intentFile,
|
|
57
|
+
idempotencyKey: options.idempotencyKey,
|
|
58
|
+
account: options.account,
|
|
59
|
+
wait: options.wait,
|
|
60
|
+
interval: options.interval,
|
|
61
|
+
timeout: options.timeout,
|
|
62
|
+
json: options.json,
|
|
63
|
+
});
|
|
152
64
|
}
|