Repository navigation
Conversation
job contract attach gains --model, --reasoning-effort, --repo, --commit-output, --input, --inputs-file, --environment, --file, --clear-repo, --clear-commit-output, --clear-input, --clear-files and --replace for webhook jobs; other job types refuse them after the job is read. Re-attaching a bound program changes only the options given: on a service that reports each binding's environment it re-binds the same reference with just the changed fields (null clears); on an older service it merges the saved settings and warns that stored files and environment may be dropped. --replace onto another revision is a full replace that carries the saved settings and environment (stored files must be given again with --file); --replace onto a program that is already bound is refused. The attach plan quotes the hold for the binding as it will run, with the job's type. job contract list reports each binding's saved settings, effective model, revision and bind time. Interrupts during a plan's advisory quote now stop the command. run quote's help is reworded briefly to keep the published manifest within its size budget, and the contracts response schema names program_ref. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Address a second review of job contract attach. The job is always read first: another job type, and a plain re-attach of a bound webhook program, send only program_ref. On a service that does not report stored files and environment, re-binding a bound webhook program is refused unless the files and environment are given or --allow-reset accepts the reset; --replace needs --file, --clear-files or --allow-reset when the old binding has stored files. The stderr notes and the live hint are gone in favour of these refusals. --commit-output takes OWNER/NAME (the service picks the branch), a new --repo no longer drops a saved commit output silently, --repo naming the saved repository keeps its branch, and --file names follow the names the service stores. The published manifest size budget is raised to 106,496 bytes for the new options. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add shared cases for the --file count limit, non-UTF-8 file content, the service's 409 for a --replace target that is already bound, and a service refusal to change a live binding. A bound program on a merging service now gets a bare program_ref when no setting changes (only --allow-reset or a same-ref --replace), the webhook-only refusal names --allow-reset, both ports check --commit-output against --repo before reading files, and the --allow-reset help mentions --replace. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #53, which is stacked on #51. Retarget to
mainafter they merge.Why
Once a GitHub App's repository access is configured (on GitHub), everything the web app can do to a job should be possible from the CLI. #51 lets
job createset a webhook's model, reasoning effort, repository, branch and commit output. But an existing webhook job couldn't be changed or inspected from the CLI:job contract attachsent onlyprogram_refand refused--model.job contract listshowed none of a binding's settings.The web app changes these by re-binding the same program with new settings:
POST /triggers/{id}/contracts, includingfileswhen a new revision is deployed from the editor.What changes
job contract attach JOB_ID OWNER/SLUG@REVgains these options for webhook jobs. Other job types refuse them after the job is read.--model,--reasoning-effortmodel,reasoning_effort--repo OWNER/NAME[@BRANCH]repository_url+repository_branch(the repository runs read as context)--commit-output OWNER/NAMEoutput(type: commit); it must be that repository, andoutput.repositoryis the repository's URL--input KEY=VALUE,--inputs-file FILEinputs, merged over the saved inputs--environment ENVenvironment--file [NAME=]PATHfiles(UTF-8, base64); replaces the stored file set, as an editor re-deploy does. At most 20 files, 5 MiB each, 10 MiB in total--clear-repo,--clear-commit-output,--clear-input KEY,--clear-files--allow-reset--replace OWNER/SLUG@REVreplace_program_ref, to move the binding to another revisionRe-attaching and changing a bound program. The job is always read first.
program_ref. The service treats re-attaching a bound program as a no-op.environment, the CLI re-binds the same reference (replace_program_refequal toprogram_ref) with just the changed fields, usingnullfor clears. The service keeps the rest, including stored files.--file/--clear-filesand--environment, or accepts the reset with--allow-reset. A plain re-attach of a bound program is refused there too.--reponaming the saved repository keeps its branch.--repowhile the saved commit output goes elsewhere is refused until--commit-outputor--clear-commit-outputis also given.--commit-outputtakesOWNER/NAME; the service picks the branch.--filenames must be what the service stores: 1 to 200 characters of[A-Za-z0-9._-], with no leading dot and no...--replaceonto another revision is a full replace on the service. The CLI sends the replaced binding's model, effort, repository, inputs and environment. Stored files can't be re-sent (only their metadata is listed), so when the old binding has any,--file,--clear-filesor--allow-resetis required.--replaceonto a program that's already bound is refused locally (the service refuses it too); change that binding in place instead.The attach plan (
--previeworCONFIRMATION_REQUIRED) quotes the hold for the binding as it will run:GET /run/quotewith the program,job_typeand the effective model, effort, environment and repository. The quote is advisory.job contract listreports for each binding:effective_model,rev_id,bound_atandis_platform_default;run_configurationholdingreasoning_effort,inputs(cost-named inputs ininput_entries),context_repositories,output,environmentandstored_files({name, size, sha256}; content is never shown).Human output adds a
settings:line that names inputs and files, not their values.Also:
run submit,program draft/program save,contract attach) now stops the command in both ports instead of being swallowed.run quote's help is reworded briefly.cli service operationsgoes from 98,304 to 106,496 bytes (96 to 104 KiB) to fit the new job options. That's a policy knob; say if you'd rather trim help text instead.trigger-contractsresponse schema now namesprogram_ref; it saidprogramRef.Parity notes:
--filedoes.--inputsends the full resulting input set, so a concurrent edit of the same binding's inputs can be overwritten.Evidence
Local, on macOS with Python 3.10.21, Rust from
rust-toolchain.tomland Bun 1.4.2. These gates pass:shared-contracts,service-help,public-surface-filesandservice-operations-corpusdifferential-conformanceandservice-coverage(0 routes unaccounted)rust-formatandrust-clippyservice-operations-rust: 1162 cases, 0 failures (1170 on the integration branch)bun-typecheckservice-operations-bun: 1162 cases, 0 failures (1170 on the integration branch)Rust (
prose-runner-corelib,service_jobs) and Bun (service-jobs,service-runs) unit tests also pass. The fullrust-testsgate is load-flaky on this machine in unrelated process-timing tests; GitHub CI is authoritative for it.Corpus: 48 new attach and list cases. Every attach exchange pins its exact request: method, path, query,
Authorizationpresence, andexpectedBodyincluding thenullclears. The cases cover:--replace, and every local refusal;repositories=1);Every expected output was accepted only where the independently written Rust and Bun ports produced identical bytes.
Review: two independent reviews read the diff. The first, before this was opened, found:
--replace;All of them are fixed and pinned by cases. The second, after it was opened, found two blockers, both fixed in the second commit:
replace_program_ref;Its re-review confirmed those fixes and found no new blockers. The third commit closes its remaining points:
--filecount limit, non-UTF-8 content, the 409 for an already-bound--replacetarget, and a live-binding refusal passing through;program_refwhen nothing changes;--allow-resetnamed in the webhook-only refusal;The 5 MiB and 10 MiB file limits are covered by unit tests in both ports rather than shared cases, which would need multi-megabyte fixtures.
Staging gate
Passed on a staging deployment that carries the matching service changes. The gate ran at the integration commit after this PR's second commit. The third commit only adds cases, the bare re-attach when nothing changes and refusal texts, none of which are on the gate's path.
cargo build --release --locked -p prose-cli --features dev-endpoint) of the integration branch that combines this PR with Document webhook delivery signing and fix endpoint_url name #49, Quote holds with the run's options and accept webhook binding keys #51, Quote holds for the program, not only the given options #53 and Report the account's job limit from its entitlement #55:integration/pending-prs@58ef6dc.Sequence:
--repo …@main --reasoning-effort …. The preview quoted the hold, and the binding runs on the job-default model.contract list.--commit-outputto the bound issue-fix binding. Only the output was sent, and the read-back shows the repository and effort kept, so the service-side merge works.Redactions: the staging host, the inbound endpoint capability URLs, the webhook secret, job and run IDs, the canary repository name and local paths are redacted. Nothing else is edited.
Transcript
🤖 Generated with Claude Code