@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.
Files changed (133) hide show
  1. package/README.md +111 -60
  2. package/dist/assets/hooks/scripts/commit-msg.sh +3 -0
  3. package/dist/assets/hooks/scripts/post-commit.sh +3 -0
  4. package/dist/assets/hooks/scripts/pre-commit.sh +11 -6
  5. package/dist/assets/hooks/scripts/pre-push.sh +3 -0
  6. package/dist/assets/hooks/scripts/prepare-commit-msg.sh +3 -0
  7. package/dist/commands/case-batch-contract.js +608 -0
  8. package/dist/commands/case-batch.js +713 -0
  9. package/dist/commands/cloud-verifier-identity-census.js +5 -2
  10. package/dist/commands/combination-search-hook.js +139 -0
  11. package/dist/commands/dismiss.js +2 -1
  12. package/dist/commands/hooks.js +66 -7
  13. package/dist/commands/install-session-hooks.js +131 -44
  14. package/dist/commands/policy.js +32 -45
  15. package/dist/commands/precompute-delivery.js +6 -1
  16. package/dist/commands/scaffold-provisional-universe.js +8 -10
  17. package/dist/commands/setup.js +32 -10
  18. package/dist/commands/submit.js +7 -2
  19. package/dist/commands/telemetry.js +17 -2
  20. package/dist/commands/triage.js +2 -1
  21. package/dist/commands/verify-explore.js +1 -0
  22. package/dist/commands/verify-hosted-mcp.js +3 -12
  23. package/dist/commands/verify-hosted-reproducibility.js +49 -547
  24. package/dist/commands/verify-hosted.js +66 -168
  25. package/dist/commands/verify-precompute.js +57 -10
  26. package/dist/commands/verify.js +51 -139
  27. package/dist/index.js +238 -350
  28. package/dist/lazy.js +8 -0
  29. package/dist/schema.js +1 -0
  30. package/dist/tools/detect.js +3 -24
  31. package/dist/triage/prompts.js +46 -45
  32. package/dist/triage/runner.js +119 -33
  33. package/dist/types.js +3 -3
  34. package/dist/utils/auth.js +14 -2
  35. package/dist/utils/git.js +60 -29
  36. package/dist/utils/github-api.js +14 -1
  37. package/dist/utils/haystack-api.js +26 -7
  38. package/dist/utils/hooks.js +43 -6
  39. package/dist/utils/prompter.js +25 -10
  40. package/dist/utils/safe-write.js +31 -0
  41. package/dist/utils/secret-paths.js +115 -0
  42. package/dist/utils/secrets.js +0 -1
  43. package/dist/utils/telemetry.js +34 -14
  44. package/dist/utils/update-check.js +151 -0
  45. package/package.json +18 -14
  46. package/schemas/case-batch.v1.json +184 -0
  47. package/schemas/cloud-verifier.v1.json +55 -100
  48. package/dist/commands/ask.d.ts +0 -14
  49. package/dist/commands/cloud-verifier-behaviors.d.ts +0 -27
  50. package/dist/commands/cloud-verifier-data-store-census.d.ts +0 -47
  51. package/dist/commands/cloud-verifier-data-store-drift.d.ts +0 -42
  52. package/dist/commands/cloud-verifier-identity-census.d.ts +0 -88
  53. package/dist/commands/cloud-verifier-materialization.d.ts +0 -16
  54. package/dist/commands/cloud-verifier-pascal-selector-census.d.ts +0 -29
  55. package/dist/commands/cloud-verifier-python-manifest-selector-census.d.ts +0 -27
  56. package/dist/commands/cloud-verifier-specialized-operational-census.d.ts +0 -51
  57. package/dist/commands/cloud-verifier-universe.d.ts +0 -31
  58. package/dist/commands/config.d.ts +0 -46
  59. package/dist/commands/design-verify.d.ts +0 -33
  60. package/dist/commands/dismiss.d.ts +0 -29
  61. package/dist/commands/hooks.d.ts +0 -13
  62. package/dist/commands/inbox.d.ts +0 -65
  63. package/dist/commands/init.d.ts +0 -10
  64. package/dist/commands/install-session-hooks.d.ts +0 -17
  65. package/dist/commands/login.d.ts +0 -8
  66. package/dist/commands/mcp.d.ts +0 -1
  67. package/dist/commands/policy.d.ts +0 -31
  68. package/dist/commands/pr-status.d.ts +0 -144
  69. package/dist/commands/pr.d.ts +0 -40
  70. package/dist/commands/precompute-delivery-contract.d.ts +0 -68
  71. package/dist/commands/precompute-delivery.d.ts +0 -20
  72. package/dist/commands/prepare-universe-review.d.ts +0 -115
  73. package/dist/commands/production-source-deny-policy.d.ts +0 -15
  74. package/dist/commands/request-review.d.ts +0 -26
  75. package/dist/commands/review.d.ts +0 -25
  76. package/dist/commands/rules.d.ts +0 -4
  77. package/dist/commands/scaffold-provisional-universe.d.ts +0 -468
  78. package/dist/commands/schema-cmd.d.ts +0 -2
  79. package/dist/commands/setup.d.ts +0 -28
  80. package/dist/commands/skills.d.ts +0 -8
  81. package/dist/commands/status.d.ts +0 -4
  82. package/dist/commands/submit.d.ts +0 -30
  83. package/dist/commands/system-map.d.ts +0 -42
  84. package/dist/commands/telemetry.d.ts +0 -53
  85. package/dist/commands/tokens.d.ts +0 -14
  86. package/dist/commands/triage.d.ts +0 -35
  87. package/dist/commands/verify-core.d.ts +0 -449
  88. package/dist/commands/verify-core.js +0 -789
  89. package/dist/commands/verify-explore.d.ts +0 -14
  90. package/dist/commands/verify-history.d.ts +0 -14
  91. package/dist/commands/verify-hosted-mcp.d.ts +0 -12
  92. package/dist/commands/verify-hosted-reproducibility.d.ts +0 -90
  93. package/dist/commands/verify-hosted.d.ts +0 -92
  94. package/dist/commands/verify-mcp.d.ts +0 -8
  95. package/dist/commands/verify-mcp.js +0 -517
  96. package/dist/commands/verify-ops.d.ts +0 -158
  97. package/dist/commands/verify-ops.js +0 -1148
  98. package/dist/commands/verify-precompute.d.ts +0 -30
  99. package/dist/commands/verify-reproducibility.d.ts +0 -85
  100. package/dist/commands/verify-reproducibility.js +0 -494
  101. package/dist/commands/verify-reseal.d.ts +0 -9
  102. package/dist/commands/verify-reseal.js +0 -148
  103. package/dist/commands/verify-sandboxes.d.ts +0 -95
  104. package/dist/commands/verify-sandboxes.js +0 -352
  105. package/dist/commands/verify.d.ts +0 -28
  106. package/dist/commands/webhooks.d.ts +0 -30
  107. package/dist/index.d.ts +0 -22
  108. package/dist/schema.d.ts +0 -28
  109. package/dist/states.d.ts +0 -29
  110. package/dist/tools/detect.d.ts +0 -50
  111. package/dist/triage/prompts.d.ts +0 -24
  112. package/dist/triage/runner.d.ts +0 -34
  113. package/dist/triage/types.d.ts +0 -42
  114. package/dist/types/verify-history.d.ts +0 -38
  115. package/dist/types.d.ts +0 -1684
  116. package/dist/utils/action-output.d.ts +0 -24
  117. package/dist/utils/analysis-api.d.ts +0 -187
  118. package/dist/utils/auth.d.ts +0 -79
  119. package/dist/utils/config.d.ts +0 -24
  120. package/dist/utils/design-verifier-api.d.ts +0 -208
  121. package/dist/utils/design-verifier-history.d.ts +0 -46
  122. package/dist/utils/design-verifier-result.d.ts +0 -74
  123. package/dist/utils/detect.d.ts +0 -43
  124. package/dist/utils/git.d.ts +0 -135
  125. package/dist/utils/github-api.d.ts +0 -104
  126. package/dist/utils/haystack-api.d.ts +0 -37
  127. package/dist/utils/hooks.d.ts +0 -12
  128. package/dist/utils/pending-state.d.ts +0 -40
  129. package/dist/utils/pr-ref.d.ts +0 -27
  130. package/dist/utils/prompter.d.ts +0 -85
  131. package/dist/utils/secrets.d.ts +0 -47
  132. package/dist/utils/telemetry.d.ts +0 -19
  133. /package/dist/commands/{precompute-delivery-worker.d.ts → combination-search-hook-contract.js} +0 -0
@@ -1,152 +1,64 @@
1
- import { readFile } from 'node:fs/promises';
2
- import { spawn } from 'node:child_process';
3
- import { resolve } from 'node:path';
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
- parsed = JSON.parse(raw);
5
+ return execFileSync('git', args, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] }).trim();
12
6
  }
13
7
  catch {
14
- throw new Error('Verifier returned an invalid JSON response.');
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
- export function verifierErrorReason(raw, contentType) {
34
- if (!contentType?.toLowerCase().includes('application/json'))
35
- return raw;
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
- parsed = JSON.parse(raw);
39
- }
40
- catch (error) {
41
- return `malformed JSON error response (${error instanceof Error ? error.message : String(error)}); raw body: ${raw}`;
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
- setVerifyToken(options.token);
77
- const server = (options.server || process.env.HAYSTACK_VERIFY_SERVER || DEFAULT_CONTROL_PLANE)
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 async function verifyCommand(specimenArg, options) {
110
- if (specimenArg === undefined && (options.repo !== undefined || options.base !== undefined || options.head !== undefined)) {
111
- if (!options.repo || !options.base || !options.head) {
112
- throw new Error('Repository verification requires --repo owner/repo, --base <ref>, and --head <ref>.');
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
- if (options.intentTranscript !== undefined) {
115
- throw new Error('Repository verification accepts optional --intent-file JSON with problem, goal, and intended_outcomes.');
41
+ catch {
42
+ // Repositories without origin/HEAD use origin/main.
116
43
  }
117
- const { verifyHostedStartCommand } = await import('./verify-hosted.js');
118
- await verifyHostedStartCommand(options.repo, {
119
- provider: 'haystack',
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
  }