orizu 0.5.26 → 0.5.28
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 +19 -0
- package/dist/artifacts-git-runtime.d.ts +34 -0
- package/dist/artifacts-git-runtime.d.ts.map +1 -0
- package/dist/artifacts-git-runtime.js +312 -0
- package/dist/cloudflare-artifacts-git-remote.d.ts +5 -0
- package/dist/cloudflare-artifacts-git-remote.d.ts.map +1 -0
- package/dist/cloudflare-artifacts-git-remote.js +21 -0
- package/dist/dataset-transfer-download.d.ts +2 -0
- package/dist/dataset-transfer-download.d.ts.map +1 -0
- package/dist/dataset-transfer-download.js +66 -0
- package/dist/dataset-transfer-policy.d.ts +2 -0
- package/dist/dataset-transfer-policy.d.ts.map +1 -0
- package/dist/dataset-transfer-policy.js +8 -0
- package/dist/dataset-transfer-upload.d.ts +42 -0
- package/dist/dataset-transfer-upload.d.ts.map +1 -0
- package/dist/dataset-transfer-upload.js +110 -0
- package/dist/git-credential.d.ts.map +1 -1
- package/dist/git-credential.js +1 -1
- package/dist/git-recovery-environment.d.ts +1 -0
- package/dist/git-recovery-environment.d.ts.map +1 -1
- package/dist/git-recovery-environment.js +1 -1
- package/dist/help.d.ts.map +1 -1
- package/dist/help.js +44 -11
- package/dist/hosted-boot.d.ts +75 -2
- package/dist/hosted-boot.d.ts.map +1 -1
- package/dist/hosted-boot.js +585 -102
- package/dist/hosted-bootstrap.d.ts +2 -0
- package/dist/hosted-bootstrap.d.ts.map +1 -1
- package/dist/hosted-bootstrap.js +12 -3
- package/dist/hosted-harness-opencode.d.ts +8 -9
- package/dist/hosted-harness-opencode.d.ts.map +1 -1
- package/dist/hosted-harness-opencode.js +126 -24
- package/dist/hosted-harness.d.ts +3 -0
- package/dist/hosted-harness.d.ts.map +1 -1
- package/dist/hosted-harness.js +4 -1
- package/dist/hosted-harvest.d.ts +30 -9
- package/dist/hosted-harvest.d.ts.map +1 -1
- package/dist/hosted-harvest.js +222 -28
- package/dist/hosted-loop-lifecycle.d.ts +15 -3
- package/dist/hosted-loop-lifecycle.d.ts.map +1 -1
- package/dist/hosted-loop-lifecycle.js +6 -4
- package/dist/hosted-loop.d.ts +47 -7
- package/dist/hosted-loop.d.ts.map +1 -1
- package/dist/hosted-loop.js +310 -64
- package/dist/hosted-question-limits.d.ts +7 -0
- package/dist/hosted-question-limits.d.ts.map +1 -0
- package/dist/hosted-question-limits.js +6 -0
- package/dist/hosted-question.d.ts +27 -0
- package/dist/hosted-question.d.ts.map +1 -0
- package/dist/hosted-question.js +118 -0
- package/dist/hosted-run-event-sink.d.ts +10 -5
- package/dist/hosted-run-event-sink.d.ts.map +1 -1
- package/dist/hosted-run-event-sink.js +12 -8
- package/dist/hosted-runtime-assets.d.ts +16 -7
- package/dist/hosted-runtime-assets.d.ts.map +1 -1
- package/dist/hosted-runtime-assets.js +40 -12
- package/dist/hosted-session-cli.d.ts.map +1 -1
- package/dist/hosted-session-cli.js +10 -19
- package/dist/http.d.ts +1 -1
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js +10 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +113 -92
- package/dist/instruction-set-gepa-launch.d.ts +1 -1
- package/dist/instruction-set-gepa-launch.d.ts.map +1 -1
- package/dist/instruction-set-gepa-launch.js +5 -3
- package/dist/instruction-set-loader.d.ts.map +1 -1
- package/dist/instruction-set-loader.js +63 -2
- package/dist/instruction-set-lock/index.d.ts +51 -0
- package/dist/instruction-set-lock/index.d.ts.map +1 -0
- package/dist/instruction-set-lock/index.js +459 -0
- package/dist/instruction-set-lock/schema.v1.d.ts +136 -0
- package/dist/instruction-set-lock/schema.v1.d.ts.map +1 -0
- package/dist/instruction-set-lock/schema.v1.js +155 -0
- package/dist/instruction-set-provenance.d.ts +26 -0
- package/dist/instruction-set-provenance.d.ts.map +1 -0
- package/dist/instruction-set-provenance.js +68 -0
- package/dist/instruction-set-sync/helpers.d.ts +22 -0
- package/dist/instruction-set-sync/helpers.d.ts.map +1 -0
- package/dist/instruction-set-sync/helpers.js +677 -0
- package/dist/instruction-set-sync/index.d.ts +60 -0
- package/dist/instruction-set-sync/index.d.ts.map +1 -0
- package/dist/instruction-set-sync/index.js +689 -0
- package/dist/instruction-set-update/index.d.ts +42 -0
- package/dist/instruction-set-update/index.d.ts.map +1 -0
- package/dist/instruction-set-update/index.js +445 -0
- package/dist/instruction-set-verify/index.d.ts +27 -0
- package/dist/instruction-set-verify/index.d.ts.map +1 -0
- package/dist/instruction-set-verify/index.js +865 -0
- package/dist/instruction-sets-cli.d.ts +1 -4
- package/dist/instruction-sets-cli.d.ts.map +1 -1
- package/dist/instruction-sets-cli.js +220 -109
- package/dist/model-config-fields.d.ts +35 -0
- package/dist/model-config-fields.d.ts.map +1 -0
- package/dist/model-config-fields.js +28 -0
- package/dist/optimizations-list-cli.d.ts.map +1 -1
- package/dist/optimizations-list-cli.js +7 -4
- package/dist/score-format.d.ts +2 -0
- package/dist/score-format.d.ts.map +1 -0
- package/dist/score-format.js +18 -0
- package/dist/workbench-repo-contract.d.ts +65 -0
- package/dist/workbench-repo-contract.d.ts.map +1 -0
- package/dist/workbench-repo-contract.js +250 -0
- package/dist/workspace-bootstrap-job.d.ts +45 -0
- package/dist/workspace-bootstrap-job.d.ts.map +1 -0
- package/dist/workspace-bootstrap-job.js +431 -0
- package/dist/workspace-bootstrap-seed.d.ts +74 -0
- package/dist/workspace-bootstrap-seed.d.ts.map +1 -0
- package/dist/workspace-bootstrap-seed.js +209 -0
- package/package.json +4 -3
- package/src/artifacts-git-runtime.ts +360 -0
- package/src/cloudflare-artifacts-git-remote.ts +24 -0
- package/src/dataset-transfer-download.ts +61 -0
- package/src/dataset-transfer-policy.ts +8 -0
- package/src/dataset-transfer-upload.ts +145 -0
- package/src/git-credential.ts +1 -2
- package/src/git-recovery-environment.ts +1 -1
- package/src/help.ts +44 -11
- package/src/hosted-boot.ts +644 -109
- package/src/hosted-bootstrap.ts +14 -3
- package/src/hosted-harness-opencode.ts +130 -28
- package/src/hosted-harness.ts +4 -1
- package/src/hosted-harvest.ts +258 -33
- package/src/hosted-loop-lifecycle.ts +19 -5
- package/src/hosted-loop.ts +340 -68
- package/src/hosted-question-limits.ts +6 -0
- package/src/hosted-question.ts +145 -0
- package/src/hosted-run-event-sink.ts +24 -12
- package/src/hosted-runtime-assets.ts +51 -11
- package/src/hosted-session-cli.ts +10 -24
- package/src/http.ts +10 -4
- package/src/index.ts +108 -134
- package/src/instruction-set-gepa-launch.ts +4 -4
- package/src/instruction-set-loader.ts +53 -2
- package/src/instruction-set-lock/index.ts +561 -0
- package/src/instruction-set-lock/schema.v1.json +141 -0
- package/src/instruction-set-lock/schema.v1.ts +155 -0
- package/src/instruction-set-provenance.ts +89 -0
- package/src/instruction-set-sync/helpers.ts +707 -0
- package/src/instruction-set-sync/index.ts +791 -0
- package/src/instruction-set-update/index.ts +488 -0
- package/src/instruction-set-verify/index.ts +1067 -0
- package/src/instruction-sets-cli.ts +226 -114
- package/src/model-config-fields.ts +31 -0
- package/src/optimizations-list-cli.ts +7 -4
- package/src/score-format.ts +16 -0
- package/src/workbench-repo-contract.ts +314 -0
- package/src/workspace-bootstrap-job.ts +611 -0
- package/src/workspace-bootstrap-seed.ts +350 -0
- package/vendor/orizu-gepa/src/orizu_gepa_connector/instruction_set_loader.py +46 -2
- package/vendor/skills/orizu/SKILL.md +4 -2
- package/vendor/skills/orizu/flows/promote.md +4 -0
- package/vendor/skills/orizu/references/assess-and-plan.md +1 -1
- package/vendor/skills/orizu/references/authority-map.md +1 -1
- package/vendor/skills/orizu/references/cli-reference.md +151 -35
- package/vendor/skills/orizu/references/instructions-after-prompts.md +3 -3
- package/vendor/skills/orizu/references/migrate-existing-gepa-setup.md +5 -6
- package/vendor/skills/orizu/references/migrate-hand-rolled-instruction-layout.md +252 -0
- package/vendor/skills/orizu/references/optimization-reports.md +5 -4
- package/vendor/skills/orizu/references/optimization-with-gepa.md +1 -1
- package/vendor/skills/orizu/references/orizu-in-your-codebase.md +195 -0
- package/vendor/skills/orizu/references/primer.md +4 -2
- package/vendor/skills/orizu/references/prompt-control-plane.md +33 -29
- package/vendor/skills/orizu/references/vocabulary.md +1 -1
package/dist/hosted-harvest.js
CHANGED
|
@@ -11,31 +11,139 @@
|
|
|
11
11
|
* 2. If dirty: `git add -A` then `git commit` attributed to the agent identity
|
|
12
12
|
* (AGENT_GIT_IDENTITY) with message `checkpoint: run <runId> auto-harvest`.
|
|
13
13
|
* 3. If there is anything unpushed (a fresh checkpoint OR pre-existing local
|
|
14
|
-
* commits the agent made but did not push),
|
|
15
|
-
*
|
|
14
|
+
* commits the agent made but did not push), push the exact HEAD SHA to the
|
|
15
|
+
* session branch at bootstrap's independently validated repository locator.
|
|
16
16
|
* 4. Return a typed outcome the loop records as a run event: `work_persisted`
|
|
17
|
-
* (sha + files), `work_none` (clean, nothing to push),
|
|
18
|
-
* (error). Harvest NEVER throws —
|
|
19
|
-
*
|
|
17
|
+
* (sha + files), `work_none` (clean, nothing to push), `work_not_inspected`
|
|
18
|
+
* (safety-gated), or `work_persist_failed` (error). Harvest NEVER throws —
|
|
19
|
+
* a harvest failure must not change the run's terminal status; it is recorded
|
|
20
|
+
* and the run proceeds to terminal.
|
|
20
21
|
*
|
|
21
22
|
* The loop runs IN the sandbox, so git is driven with `child_process` (matching
|
|
22
23
|
* `defaultRunSetupHook` / `installOpenCodePinned` in `hosted-loop.ts`). `exec` is
|
|
23
|
-
* injectable so the whole thing is unit-testable with no real git
|
|
24
|
+
* injectable so the whole thing is unit-testable with no real git; the HTTPS
|
|
25
|
+
* smart-Git boundary tests independently prove the production transport.
|
|
24
26
|
*/
|
|
25
27
|
import { spawnSync } from 'child_process';
|
|
28
|
+
import { randomUUID } from 'crypto';
|
|
29
|
+
import { mkdtempSync, readdirSync, rmSync, statSync } from 'fs';
|
|
30
|
+
import { tmpdir } from 'os';
|
|
31
|
+
import { join } from 'path';
|
|
32
|
+
import { isValidCloudflareArtifactsGitRemote, parseCanonicalCredentialFreeHttpsUrl, } from './cloudflare-artifacts-git-remote.js';
|
|
33
|
+
export const HOSTED_HARVEST_CA_BUNDLE_CANDIDATES = [
|
|
34
|
+
'/etc/pki/tls/certs/ca-bundle.crt',
|
|
35
|
+
'/etc/ssl/certs/ca-certificates.crt',
|
|
36
|
+
'/etc/ssl/cert.pem',
|
|
37
|
+
];
|
|
38
|
+
export const HOSTED_HARVEST_CA_PATH_CANDIDATES = [
|
|
39
|
+
'/etc/pki/ca-trust/extracted/pem/directory-hash',
|
|
40
|
+
'/etc/ssl/certs',
|
|
41
|
+
];
|
|
42
|
+
export const HOSTED_HARVEST_TRANSPORT_POLICY = {
|
|
43
|
+
environmentDenylist: [
|
|
44
|
+
'HTTP_PROXY', 'http_proxy', 'HTTPS_PROXY', 'https_proxy', 'ALL_PROXY', 'all_proxy',
|
|
45
|
+
'GIT_SSL_NO_VERIFY', 'GIT_PROXY_COMMAND', 'GIT_SSL_CAINFO', 'GIT_SSL_CAPATH',
|
|
46
|
+
'CURL_CA_BUNDLE', 'SSL_CERT_FILE', 'SSL_CERT_DIR', 'GIT_SSL_CERT', 'GIT_SSL_KEY',
|
|
47
|
+
'GIT_ASKPASS', 'GIT_ASKPASS_REQUIRE', 'SSH_ASKPASS', 'SSH_ASKPASS_REQUIRE',
|
|
48
|
+
'GIT_TERMINAL_PROMPT',
|
|
49
|
+
],
|
|
50
|
+
exactUrlHttpConfig: [
|
|
51
|
+
['proxy', ''], ['sslVerify', 'true'], ['curloptResolve', ''],
|
|
52
|
+
['followRedirects', 'false'],
|
|
53
|
+
],
|
|
54
|
+
rejectedLocalHttpKeys: [
|
|
55
|
+
'sslcert', 'sslkey', 'sslcertpasswordprotected', 'sslbackend',
|
|
56
|
+
'pinnedpubkey', 'sslversion', 'sslcipherlist',
|
|
57
|
+
],
|
|
58
|
+
};
|
|
59
|
+
function isRegularFile(path) {
|
|
60
|
+
try {
|
|
61
|
+
return statSync(path).isFile();
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
export function resolveHostedHarvestCaBundle(candidates = HOSTED_HARVEST_CA_BUNDLE_CANDIDATES) {
|
|
68
|
+
return candidates.find(isRegularFile) ?? null;
|
|
69
|
+
}
|
|
70
|
+
function resolveHostedHarvestCaPath(candidates = HOSTED_HARVEST_CA_PATH_CANDIDATES) {
|
|
71
|
+
for (const candidate of candidates) {
|
|
72
|
+
try {
|
|
73
|
+
if (!statSync(candidate).isDirectory())
|
|
74
|
+
continue;
|
|
75
|
+
if (readdirSync(candidate).some(entry => /^[0-9a-f]{8}\.[0-9]+$/u.test(entry)))
|
|
76
|
+
return candidate;
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
// A missing or unreadable directory is not a trust source.
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
26
84
|
function defaultHarvestExec(workspaceDir) {
|
|
27
85
|
return (args) => {
|
|
28
|
-
const
|
|
86
|
+
const env = { ...process.env };
|
|
87
|
+
for (const name of Object.keys(env)) {
|
|
88
|
+
if (HOSTED_HARVEST_TRANSPORT_POLICY.environmentDenylist.includes(name) ||
|
|
89
|
+
name === 'GIT_CONFIG' || name.startsWith('GIT_CONFIG_'))
|
|
90
|
+
delete env[name];
|
|
91
|
+
}
|
|
92
|
+
env.GIT_CONFIG_NOSYSTEM = '1';
|
|
93
|
+
env.GIT_CONFIG_GLOBAL = '/dev/null';
|
|
94
|
+
env.GIT_TERMINAL_PROMPT = '0';
|
|
95
|
+
const res = spawnSync('git', [...args], { cwd: workspaceDir, encoding: 'utf8', env });
|
|
29
96
|
if (res.error) {
|
|
30
97
|
return { exitCode: 1, stdout: '', stderr: res.error.message };
|
|
31
98
|
}
|
|
32
99
|
return { exitCode: res.status ?? 1, stdout: res.stdout ?? '', stderr: res.stderr ?? '' };
|
|
33
100
|
};
|
|
34
101
|
}
|
|
102
|
+
function protectPinnedRemote(exec, remote, caBundle, caPath, credentialHelper) {
|
|
103
|
+
const httpConfig = HOSTED_HARVEST_TRANSPORT_POLICY.exactUrlHttpConfig.flatMap(([key, value]) => ['-c', `http.${remote}.${key}=${value}`]);
|
|
104
|
+
const credentialUsername = new URL(remote).hostname === 'github.com' ? 'x-access-token' : 'x';
|
|
105
|
+
const credentialConfig = credentialHelper ? [
|
|
106
|
+
// An empty helper resets Git's accumulated helper list, including URL-scoped entries.
|
|
107
|
+
'-c', 'credential.helper=',
|
|
108
|
+
'-c', `credential.helper=${credentialHelper}`,
|
|
109
|
+
'-c', 'credential.useHttpPath=true',
|
|
110
|
+
'-c', `credential.${remote}.useHttpPath=true`,
|
|
111
|
+
'-c', `credential.username=${credentialUsername}`,
|
|
112
|
+
'-c', `credential.${remote}.username=${credentialUsername}`,
|
|
113
|
+
'-c', 'credential.interactive=false',
|
|
114
|
+
'-c', 'core.askPass=',
|
|
115
|
+
] : ['-c', 'credential.helper='];
|
|
116
|
+
return (args) => {
|
|
117
|
+
const alias = `https://orizu-harvest.invalid/${randomUUID()}`;
|
|
118
|
+
const temporaryCaPath = caPath ? null : mkdtempSync(join(tmpdir(), 'orizu-harvest-ca-'));
|
|
119
|
+
try {
|
|
120
|
+
return exec([
|
|
121
|
+
'-c', `url.${remote}.insteadOf=${alias}`,
|
|
122
|
+
'-c', `url.${remote}.pushInsteadOf=${alias}`,
|
|
123
|
+
...httpConfig,
|
|
124
|
+
'-c', `http.${remote}.sslCAInfo=${caBundle}`,
|
|
125
|
+
'-c', `http.${remote}.sslCAPath=${caPath ?? temporaryCaPath}`,
|
|
126
|
+
...credentialConfig,
|
|
127
|
+
...args.map(arg => arg === remote ? alias : arg),
|
|
128
|
+
]);
|
|
129
|
+
}
|
|
130
|
+
finally {
|
|
131
|
+
if (temporaryCaPath)
|
|
132
|
+
rmSync(temporaryCaPath, { recursive: true, force: true });
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
}
|
|
35
136
|
function detail(res) {
|
|
36
137
|
const text = (res.stderr && res.stderr.trim()) || (res.stdout && res.stdout.trim()) || `exit ${res.exitCode}`;
|
|
37
138
|
return text;
|
|
38
139
|
}
|
|
140
|
+
const GITHUB_PATH = /^\/[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+\.git$/u;
|
|
141
|
+
function isValidRepositoryRemote(remote) {
|
|
142
|
+
if (isValidCloudflareArtifactsGitRemote(remote))
|
|
143
|
+
return true;
|
|
144
|
+
const parsed = parseCanonicalCredentialFreeHttpsUrl(remote);
|
|
145
|
+
return parsed !== null && parsed.hostname === 'github.com' && GITHUB_PATH.test(parsed.pathname);
|
|
146
|
+
}
|
|
39
147
|
function splitLines(text) {
|
|
40
148
|
return text
|
|
41
149
|
.split('\n')
|
|
@@ -43,16 +151,20 @@ function splitLines(text) {
|
|
|
43
151
|
.filter(line => line.length > 0);
|
|
44
152
|
}
|
|
45
153
|
/**
|
|
46
|
-
* Count commits present locally but not on the
|
|
47
|
-
*
|
|
48
|
-
* could not land anyway, so "nothing to push" is the safe reading.
|
|
154
|
+
* Count commits present locally but not on the private ref fetched from the
|
|
155
|
+
* pinned repository. Exit-zero empty output is zero; lookup failures are unknown.
|
|
49
156
|
*/
|
|
50
|
-
function countUnpushed(exec) {
|
|
51
|
-
const res = exec(['rev-list', '--count',
|
|
157
|
+
function countUnpushed(exec, pinnedRef) {
|
|
158
|
+
const res = exec(['rev-list', '--count', `${pinnedRef}..HEAD`]);
|
|
52
159
|
if (res.exitCode !== 0)
|
|
160
|
+
return null;
|
|
161
|
+
const output = res.stdout.trim();
|
|
162
|
+
if (output === '')
|
|
53
163
|
return 0;
|
|
54
|
-
|
|
55
|
-
|
|
164
|
+
if (!/^\d+$/u.test(output))
|
|
165
|
+
return null;
|
|
166
|
+
const count = Number(output);
|
|
167
|
+
return Number.isSafeInteger(count) ? count : null;
|
|
56
168
|
}
|
|
57
169
|
/**
|
|
58
170
|
* Persist any uncommitted or unpushed work in the workspace. Deterministic and
|
|
@@ -60,12 +172,58 @@ function countUnpushed(exec) {
|
|
|
60
172
|
*/
|
|
61
173
|
export function harvestWorkspace(opts) {
|
|
62
174
|
// Safety gate: never touch a real repo unless explicitly enabled or given an
|
|
63
|
-
// injected exec. Absent both, report
|
|
175
|
+
// injected exec. Absent both, report that inspection was skipped.
|
|
64
176
|
if (!opts.exec && !opts.enabled) {
|
|
65
|
-
return { kind: '
|
|
177
|
+
return { kind: 'work_not_inspected' };
|
|
66
178
|
}
|
|
67
|
-
|
|
179
|
+
if (!isValidRepositoryRemote(opts.repositoryRemote)) {
|
|
180
|
+
return { kind: 'work_persist_failed', error: 'repository_locator_invalid' };
|
|
181
|
+
}
|
|
182
|
+
// Every invocation gets a fresh, one-shot alias. Its exact command-scoped
|
|
183
|
+
// rewrite outranks repo-local prefix rules and resolves to the validated URL
|
|
184
|
+
// byte-for-byte; an observer of one argv cannot redirect a later command.
|
|
185
|
+
if (!opts.exec && (!opts.credentialHelper || /[\r\n\0]/u.test(opts.credentialHelper))) {
|
|
186
|
+
return { kind: 'work_persist_failed', error: 'checkpoint_credential_helper_invalid' };
|
|
187
|
+
}
|
|
188
|
+
const caBundleCandidates = opts.caBundleCandidates ?? HOSTED_HARVEST_CA_BUNDLE_CANDIDATES;
|
|
189
|
+
const caBundle = resolveHostedHarvestCaBundle(caBundleCandidates);
|
|
190
|
+
if (!caBundle) {
|
|
191
|
+
return {
|
|
192
|
+
kind: 'work_persist_failed',
|
|
193
|
+
error: `hosted_harvest_ca_bundle_missing: ${caBundleCandidates.join(', ')}`,
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
const caPath = resolveHostedHarvestCaPath(opts.caPathCandidates);
|
|
197
|
+
const rawExec = opts.exec ?? defaultHarvestExec(opts.workspaceDir);
|
|
198
|
+
const exec = protectPinnedRemote(rawExec, opts.repositoryRemote, caBundle, caPath, opts.credentialHelper);
|
|
199
|
+
const pinnedRef = `refs/orizu/pinned/${opts.sessionBranch}`;
|
|
68
200
|
try {
|
|
201
|
+
const rejectedKeyPattern = HOSTED_HARVEST_TRANSPORT_POLICY.rejectedLocalHttpKeys.join('|');
|
|
202
|
+
const localTransportConfig = exec([
|
|
203
|
+
'config', '--includes', '--show-origin', '--name-only', '--get-regexp',
|
|
204
|
+
`^http\\.(.*\\.)?(${rejectedKeyPattern})$`,
|
|
205
|
+
]);
|
|
206
|
+
if (localTransportConfig.exitCode !== 0 && localTransportConfig.exitCode !== 1) {
|
|
207
|
+
return { kind: 'work_persist_failed', error: `git config inspection failed: ${detail(localTransportConfig)}` };
|
|
208
|
+
}
|
|
209
|
+
if (splitLines(localTransportConfig.stdout).length > 0) {
|
|
210
|
+
return { kind: 'work_persist_failed', error: 'hosted_harvest_transport_config_present' };
|
|
211
|
+
}
|
|
212
|
+
if (!opts.exec) {
|
|
213
|
+
const effectiveSslVerify = exec([
|
|
214
|
+
'config', '--get-urlmatch', 'http.sslVerify', `${opts.repositoryRemote}/`,
|
|
215
|
+
]);
|
|
216
|
+
if (effectiveSslVerify.exitCode !== 0 || effectiveSslVerify.stdout.trim() !== 'true') {
|
|
217
|
+
return { kind: 'work_persist_failed', error: 'hosted_harvest_tls_policy_ineffective' };
|
|
218
|
+
}
|
|
219
|
+
const effectiveCaPath = exec(['config', '--get-urlmatch', 'http.sslCAPath', `${opts.repositoryRemote}/`]);
|
|
220
|
+
const resolvedCaPath = effectiveCaPath.stdout.trim();
|
|
221
|
+
const expectedTemporaryPrefix = join(tmpdir(), 'orizu-harvest-ca-');
|
|
222
|
+
const isExpectedCaPath = caPath ? resolvedCaPath === caPath : resolvedCaPath.startsWith(expectedTemporaryPrefix);
|
|
223
|
+
if (effectiveCaPath.exitCode !== 0 || !isExpectedCaPath) {
|
|
224
|
+
return { kind: 'work_persist_failed', error: 'hosted_harvest_ca_path_policy_ineffective' };
|
|
225
|
+
}
|
|
226
|
+
}
|
|
69
227
|
// Never harvest bootstrap-injected runtime scaffolding (ALI-1051): the
|
|
70
228
|
// .claude/skills symlink is a sandbox-local pointer, not the agent's work.
|
|
71
229
|
// Bootstrap also excludes it via .git/info/exclude; this pathspec is the
|
|
@@ -86,6 +244,12 @@ export function harvestWorkspace(opts) {
|
|
|
86
244
|
`user.name=${opts.author.name}`,
|
|
87
245
|
'-c',
|
|
88
246
|
`user.email=${opts.author.email}`,
|
|
247
|
+
'-c',
|
|
248
|
+
'core.hooksPath=/dev/null',
|
|
249
|
+
'-c',
|
|
250
|
+
'commit.gpgsign=false',
|
|
251
|
+
'-c',
|
|
252
|
+
'gpg.program=',
|
|
89
253
|
'commit',
|
|
90
254
|
'--author',
|
|
91
255
|
`${opts.author.name} <${opts.author.email}>`,
|
|
@@ -96,23 +260,53 @@ export function harvestWorkspace(opts) {
|
|
|
96
260
|
return { kind: 'work_persist_failed', error: `git commit failed: ${detail(commit)}` };
|
|
97
261
|
}
|
|
98
262
|
}
|
|
99
|
-
//
|
|
100
|
-
|
|
101
|
-
|
|
263
|
+
// Never derive checkpoint truth from mutable `origin`. Refresh a private ref
|
|
264
|
+
// from the independently validated repository before deciding there is no work.
|
|
265
|
+
const fetchPinned = exec([
|
|
266
|
+
'fetch', '--no-tags', '--force', opts.repositoryRemote,
|
|
267
|
+
`+refs/heads/${opts.sessionBranch}:${pinnedRef}`,
|
|
268
|
+
]);
|
|
269
|
+
const hasPinnedBase = fetchPinned.exitCode === 0;
|
|
270
|
+
const unpushed = hasPinnedBase ? countUnpushed(exec, pinnedRef) : null;
|
|
271
|
+
// Unknown is not none. Preserve round-3 behavior by attempting the exact
|
|
272
|
+
// pinned-repository push; omit file claims if no trustworthy base exists.
|
|
273
|
+
if (!dirty && unpushed === 0)
|
|
102
274
|
return { kind: 'work_none' };
|
|
103
|
-
}
|
|
104
275
|
const headRes = exec(['rev-parse', 'HEAD']);
|
|
105
276
|
const sha = headRes.exitCode === 0 ? headRes.stdout.trim() : '';
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
const
|
|
112
|
-
|
|
277
|
+
if (!/^[a-f0-9]{40}$/.test(sha)) {
|
|
278
|
+
return { kind: 'work_persist_failed', error: `git rev-parse HEAD failed: ${detail(headRes)}` };
|
|
279
|
+
}
|
|
280
|
+
// Files are the complete delta the exact push delivers, including any local
|
|
281
|
+
// commits the agent made before the final auto-harvest commit.
|
|
282
|
+
const filesRes = hasPinnedBase
|
|
283
|
+
? exec(['diff', '--name-only', `${pinnedRef}..HEAD`])
|
|
284
|
+
: null;
|
|
285
|
+
const files = filesRes?.exitCode === 0 ? splitLines(filesRes.stdout) : null;
|
|
286
|
+
// --no-verify blocks hostile hooks, including Git LFS's legitimate upload
|
|
287
|
+
// hook. Run the equivalent upload explicitly before publishing the pointer ref.
|
|
288
|
+
const lfsVersion = exec(['lfs', 'version']);
|
|
289
|
+
if (lfsVersion.exitCode === 0) {
|
|
290
|
+
const lfsFiles = exec(['lfs', 'ls-files', '--name-only']);
|
|
291
|
+
if (lfsFiles.exitCode !== 0) {
|
|
292
|
+
return { kind: 'work_persist_failed', error: `git_lfs_inspection_failed: ${detail(lfsFiles)}` };
|
|
293
|
+
}
|
|
294
|
+
if (splitLines(lfsFiles.stdout).length > 0) {
|
|
295
|
+
const lfsPush = exec(['lfs', 'push', opts.repositoryRemote, sha]);
|
|
296
|
+
if (lfsPush.exitCode !== 0) {
|
|
297
|
+
return { kind: 'work_persist_failed', error: `git_lfs_push_failed: ${detail(lfsPush)}` };
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
// Push the exact object we report to the exact session destination. This
|
|
302
|
+
// avoids separately deriving a local claim and a tracking-branch update.
|
|
303
|
+
const push = exec([
|
|
304
|
+
'push', '--no-verify', opts.repositoryRemote, `${sha}:refs/heads/${opts.sessionBranch}`,
|
|
305
|
+
]);
|
|
113
306
|
if (push.exitCode !== 0) {
|
|
114
307
|
return { kind: 'work_persist_failed', error: `git push failed: ${detail(push)}` };
|
|
115
308
|
}
|
|
309
|
+
exec(['update-ref', pinnedRef, sha]);
|
|
116
310
|
return { kind: 'work_persisted', sha, files };
|
|
117
311
|
}
|
|
118
312
|
catch (error) {
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
* (`@/packages/cli/src/hosted-loop`) is unchanged.
|
|
23
23
|
*/
|
|
24
24
|
import type { HarnessEvent } from './hosted-harness.js';
|
|
25
|
+
import type { HostedSessionOrigin } from './hosted-runtime-assets.js';
|
|
25
26
|
/**
|
|
26
27
|
* Default provider-qualified hosted model — the SINGLE source of truth
|
|
27
28
|
* (ALI-1086). Imported by both the operator-path session CLI
|
|
@@ -56,9 +57,20 @@ export interface HostedLoopContext {
|
|
|
56
57
|
taskFile: string;
|
|
57
58
|
/** Directory the agent operates in (the cloned session-branch workspace). */
|
|
58
59
|
workspaceDir: string;
|
|
60
|
+
/** Validated destination branch for the CLI-owned checkpoint push. */
|
|
61
|
+
sessionBranch: string;
|
|
62
|
+
/** Credential-free repository locator established by bootstrap. */
|
|
63
|
+
repositoryRemote: string;
|
|
64
|
+
/** Bootstrap-owned helper re-applied command-scoped during checkpoint transport. */
|
|
65
|
+
repositoryCredentialHelper?: string;
|
|
59
66
|
/** Provider-qualified model, e.g. "anthropic/claude-opus-4-8". */
|
|
60
67
|
model: string;
|
|
61
68
|
reasoningEffort?: string;
|
|
69
|
+
/**
|
|
70
|
+
* Session entry surface (ALI-1867). Missing values fail safely to CLI's
|
|
71
|
+
* unattended behavior; only `hosted-web` enables human question custody.
|
|
72
|
+
*/
|
|
73
|
+
sessionOrigin?: HostedSessionOrigin;
|
|
62
74
|
/** Idempotency / correlation key for the prompt. */
|
|
63
75
|
messageId: string;
|
|
64
76
|
/** Git identity for commit attribution during the prompt. */
|
|
@@ -143,14 +155,14 @@ export interface EgressProbeResult {
|
|
|
143
155
|
detail: string;
|
|
144
156
|
}
|
|
145
157
|
/**
|
|
146
|
-
* Default probe: attempt a bounded
|
|
147
|
-
* firewall makes this THROW for a DENIED host (connection reset / timeout / DNS
|
|
158
|
+
* Default probe: attempt a bounded GET to a full URL target, or HTTPS when the
|
|
159
|
+
* target is a bare host. A live default-deny firewall makes this THROW for a DENIED host (connection reset / timeout / DNS
|
|
148
160
|
* failure) → `reachable: false`. Any response at all — even an error status —
|
|
149
161
|
* proves the host was reachable → `reachable: true`. Used for BOTH the allowed
|
|
150
162
|
* (positive-control) and denied probes.
|
|
151
163
|
*/
|
|
152
164
|
export declare function defaultProbeEgress(host: string): Promise<EgressProbeResult>;
|
|
153
|
-
/** The two
|
|
165
|
+
/** The two host/URL targets the positive-control canary probes. */
|
|
154
166
|
export interface EgressCanaryTargets {
|
|
155
167
|
/** A known-ALLOWED host (the Orizu API base) that MUST be reachable — the
|
|
156
168
|
* positive control that distinguishes "policy blocking" from "network dead". */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hosted-loop-lifecycle.d.ts","sourceRoot":"","sources":["../src/hosted-loop-lifecycle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"hosted-loop-lifecycle.d.ts","sourceRoot":"","sources":["../src/hosted-loop-lifecycle.ts"],"names":[],"mappings":"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"}
|
|
@@ -68,8 +68,8 @@ export const DEFAULT_EGRESS_CANARY_HOST = 'example.com';
|
|
|
68
68
|
* reachable host answers well within this. */
|
|
69
69
|
const EGRESS_CANARY_TIMEOUT_MS = 5000;
|
|
70
70
|
/**
|
|
71
|
-
* Default probe: attempt a bounded
|
|
72
|
-
* firewall makes this THROW for a DENIED host (connection reset / timeout / DNS
|
|
71
|
+
* Default probe: attempt a bounded GET to a full URL target, or HTTPS when the
|
|
72
|
+
* target is a bare host. A live default-deny firewall makes this THROW for a DENIED host (connection reset / timeout / DNS
|
|
73
73
|
* failure) → `reachable: false`. Any response at all — even an error status —
|
|
74
74
|
* proves the host was reachable → `reachable: true`. Used for BOTH the allowed
|
|
75
75
|
* (positive-control) and denied probes.
|
|
@@ -78,7 +78,8 @@ export async function defaultProbeEgress(host) {
|
|
|
78
78
|
const controller = new AbortController();
|
|
79
79
|
const timer = setTimeout(() => controller.abort(), EGRESS_CANARY_TIMEOUT_MS);
|
|
80
80
|
try {
|
|
81
|
-
const
|
|
81
|
+
const target = URL.canParse(host) ? new URL('/', host).toString() : `https://${host}/`;
|
|
82
|
+
const response = await fetch(target, {
|
|
82
83
|
method: 'GET',
|
|
83
84
|
redirect: 'manual',
|
|
84
85
|
signal: controller.signal,
|
|
@@ -184,7 +185,8 @@ export async function runEgressCanary(targets, sink, probe, now = () => Date.now
|
|
|
184
185
|
*/
|
|
185
186
|
export function egressCanaryAllowedHost(apiBaseUrl) {
|
|
186
187
|
try {
|
|
187
|
-
|
|
188
|
+
const parsed = new URL(apiBaseUrl);
|
|
189
|
+
return parsed.port === '' ? parsed.hostname : parsed.origin;
|
|
188
190
|
}
|
|
189
191
|
catch {
|
|
190
192
|
return apiBaseUrl.replace(/^[a-z]+:\/\//i, '').split('/')[0].split(':')[0];
|
package/dist/hosted-loop.d.ts
CHANGED
|
@@ -16,7 +16,8 @@
|
|
|
16
16
|
* driver; 'claude-agent-sdk': construct the in-process Claude-Agent-SDK
|
|
17
17
|
* driver — no server to install or spawn), then drive the SINGLE task prompt
|
|
18
18
|
* (v0: no queue) through `drainHarnessToSink`;
|
|
19
|
-
* 5.
|
|
19
|
+
* 5. checkpoint dirty or local-only Git work without replacing the agent's
|
|
20
|
+
* terminal result, then deliver that original result through the sink.
|
|
20
21
|
*
|
|
21
22
|
* SWAPPABILITY (ALI-929 / P3.6): harness SELECTION is the ONLY thing that differs
|
|
22
23
|
* between the two drivers — `start()` → `runPrompt()` → `drainHarnessToSink()` →
|
|
@@ -29,10 +30,11 @@
|
|
|
29
30
|
* per-exec fallback — with firewall brokering the real key never reaches here).
|
|
30
31
|
*
|
|
31
32
|
* TESTABILITY: `runHostedLoop` takes injected `fetchImpl`, `spawnOpenCode`,
|
|
32
|
-
* `installOpenCode`,
|
|
33
|
-
* against
|
|
33
|
+
* `installOpenCode`, `createHarness`, and Git execution, so the whole loop can
|
|
34
|
+
* run in-process against fake boundaries; separate tests exercise the real
|
|
35
|
+
* packaged CLI, HTTPS smart-Git transport, and OpenCode process boundary.
|
|
34
36
|
*/
|
|
35
|
-
import type
|
|
37
|
+
import { type AgentHarness } from './hosted-harness.js';
|
|
36
38
|
import { type HarvestExec } from './hosted-harvest.js';
|
|
37
39
|
import { type ModelValidationOutcome, type SpawnOpenCodeOptions, type SpawnedOpenCode } from './hosted-harness-opencode.js';
|
|
38
40
|
import { type HostedFetch, type TerminalStatus } from './hosted-run-event-sink.js';
|
|
@@ -51,8 +53,35 @@ export interface InstallResult {
|
|
|
51
53
|
ok: boolean;
|
|
52
54
|
detail: string;
|
|
53
55
|
}
|
|
56
|
+
interface HostedLoopSharedRuntime {
|
|
57
|
+
harness: AgentHarness | null;
|
|
58
|
+
spawned: SpawnedOpenCode | null;
|
|
59
|
+
agentSessionId: string | null;
|
|
60
|
+
installOk: boolean;
|
|
61
|
+
startupComplete: boolean;
|
|
62
|
+
spawnLogPath: string;
|
|
63
|
+
closed: boolean;
|
|
64
|
+
}
|
|
65
|
+
export interface HostedLoopSessionContext extends Omit<HostedLoopContext, 'runId' | 'bearerFile' | 'taskFile' | 'messageId'> {
|
|
66
|
+
sessionId: string;
|
|
67
|
+
projectId: string | null;
|
|
68
|
+
sessionDir: string;
|
|
69
|
+
}
|
|
70
|
+
export interface HostedLoopTurnContext {
|
|
71
|
+
runId: string;
|
|
72
|
+
ordinal: number;
|
|
73
|
+
taskFile: string;
|
|
74
|
+
messageId: string;
|
|
75
|
+
bearerFile: string;
|
|
76
|
+
}
|
|
77
|
+
export interface HostedLoopSessionHandle {
|
|
78
|
+
context: HostedLoopSessionContext;
|
|
79
|
+
runtime: HostedLoopSharedRuntime;
|
|
80
|
+
}
|
|
54
81
|
export interface RunHostedLoopOptions {
|
|
55
82
|
context: HostedLoopContext;
|
|
83
|
+
/** Internal session runtime used by the public session/turn lifecycle. */
|
|
84
|
+
sharedRuntime?: HostedLoopSharedRuntime;
|
|
56
85
|
/**
|
|
57
86
|
* Agent bearer, as a FIXED string (tests / in-process launcher) OR omitted in
|
|
58
87
|
* favor of `bearerProvider`. In production the loop reads the rotated 0600
|
|
@@ -91,6 +120,9 @@ export interface RunHostedLoopOptions {
|
|
|
91
120
|
}) => Promise<ModelValidationOutcome>;
|
|
92
121
|
now?: () => number;
|
|
93
122
|
signal?: AbortSignal;
|
|
123
|
+
/** Prompt-only human interrupt. Unlike `signal`, this never controls harness
|
|
124
|
+
* provisioning or the session-scoped runtime. */
|
|
125
|
+
interruptSignal?: AbortSignal;
|
|
94
126
|
/** Extra verbatim secrets to redact (the bearer is added by the sink itself). */
|
|
95
127
|
redactSecretsList?: readonly string[];
|
|
96
128
|
/** Egress-canary probe (default: a bounded `fetch` to https://<host>/).
|
|
@@ -104,9 +136,9 @@ export interface RunHostedLoopOptions {
|
|
|
104
136
|
workspaceDir: string;
|
|
105
137
|
}) => Promise<SetupHookOutcome> | SetupHookOutcome;
|
|
106
138
|
/**
|
|
107
|
-
* Standing preamble wrapped around the user task (ALI-1036). Defaults
|
|
108
|
-
* `
|
|
109
|
-
* to send the task verbatim (tests). The
|
|
139
|
+
* Standing preamble wrapped around the user task (ALI-1036/ALI-1867). Defaults
|
|
140
|
+
* according to `context.sessionOrigin`; pass an override to customize it, or
|
|
141
|
+
* an empty string to send the task verbatim (tests). The task stays verbatim
|
|
110
142
|
* beneath a delimiter (see `composeHostedTaskPrompt`).
|
|
111
143
|
*/
|
|
112
144
|
taskPreamble?: string;
|
|
@@ -124,6 +156,9 @@ export interface RunHostedLoopOptions {
|
|
|
124
156
|
/** Injectable sleep for the terminal-delivery retry backoff (ALI-1065
|
|
125
157
|
* finding 2). Tests pass a no-op to avoid real delays. */
|
|
126
158
|
sleepImpl?: (ms: number) => Promise<void>;
|
|
159
|
+
/** Value-free local diagnostics shared with the event sink. Production routes
|
|
160
|
+
* this through hosted-boot's stderr seam; consumer failures are ignored. */
|
|
161
|
+
onDiagnostic?: (message: string) => void;
|
|
127
162
|
}
|
|
128
163
|
export interface HostedLoopResult {
|
|
129
164
|
status: TerminalStatus;
|
|
@@ -156,6 +191,11 @@ export declare const TERMINAL_DELIVERY_RETRY_DELAYS_MS: readonly number[];
|
|
|
156
191
|
*/
|
|
157
192
|
export { INJECTED_ENV_VARS_ENV } from './hosted-environment.js';
|
|
158
193
|
export declare function runHostedLoop(opts: RunHostedLoopOptions): Promise<HostedLoopResult>;
|
|
194
|
+
export declare function startHostedLoopSession(context: HostedLoopSessionContext): Promise<HostedLoopSessionHandle>;
|
|
195
|
+
export declare function runHostedLoopTurn(session: HostedLoopSessionHandle, turn: HostedLoopTurnContext, options: Omit<RunHostedLoopOptions, 'context' | 'taskPrompt' | 'sharedRuntime'> & {
|
|
196
|
+
taskPrompt: string;
|
|
197
|
+
}): Promise<HostedLoopResult>;
|
|
198
|
+
export declare function closeHostedLoopSession(session: HostedLoopSessionHandle): Promise<void>;
|
|
159
199
|
export interface HostedLoopCommandIo {
|
|
160
200
|
print: (line: string) => void;
|
|
161
201
|
printErr?: (line: string) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hosted-loop.d.ts","sourceRoot":"","sources":["../src/hosted-loop.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"hosted-loop.d.ts","sourceRoot":"","sources":["../src/hosted-loop.ts"],"names":[],"mappings":"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"}
|