Skip to content

jpdev codex, jpdev push, Go steps with -mod=readonly - #10

Merged
kikashy merged 2 commits into
mainfrom
jpdev-codex
Oct 20, 2026
Merged

kikashy merged 2 commits into
mainfrom
jpdev-codex

Conversation

@kikashy

@kikashy kikashy commented Oct 20, 2026

Copy link
Copy Markdown
Contributor

Closes #9. Closes #6. Closes #7.

What it adds

  • jpdev codex run --brief FILE --model M --effort low|medium|high [--dir] [--repo] [--base] [--add PATH] [--no-commit] [--no-push] [--no-pr] [--sandbox] [--log] (jpdev codex: run a Codex CLI build from a brief with the model, effort, sandbox and push form explicit; check a brief for filter-tripping words #9). It checks the brief, then runs codex exec with -m, -c model_reasoning_effort=, --sandbox (with -c sandbox_workspace_write.network_access=true for workspace-write), -C, -o, stdin from /dev/null, and a prompt of one line ("The rules are this repository's AGENTS.md; follow them.") plus the brief's text. The flag names were read from codex exec --help of the installed binary. The transcript goes to the log; the final message and the exit code are printed, and Codex's own exit code is returned when it fails.
    • Codex in workspace-write cannot write .git, so it does not commit. It writes msg.txt and pr.md; after it returns, the command stages tracked changes (git add -u, plus paths named with --add; no other untracked file; never msg.txt or pr.md), commits with -s and the message of msg.txt plus the Co-Authored-By: Codex <noreply@openai.com> trailer when it is missing, pushes as jpdev push does, and opens the pull request with gh pr create --repo ... --base ... --head ... (title: the subject of msg.txt; body: pr.md). No change to a tracked file, or no msg.txt, means no commit and exit 1. A clone on main is refused before the run. --sandbox danger-full-access is an explicit option only.
  • jpdev codex check-brief FILE: refuses a brief that holds a term of config/codex-words.txt (the base list; a term is matched at the start of a word, so stems match) or of the file named by JPDEV_CODEX_WORDS, and prints the neutral phrasing for each. codex run runs it first.
  • jpdev codex brief-template prints templates/codex-brief.md, which tells Codex to write msg.txt and pr.md and not to commit.
  • New settings: JPDEV_CODEX_MODEL_DEFAULT (none: the model is always passed), JPDEV_CODEX_SANDBOX (workspace-write), JPDEV_CODEX_WORDS.
  • jpdev push [BRANCH] (The agent docs and jpdev say how to push: the gh credential helper, never a stored credential #6) runs git -c credential.helper= -c 'credential.helper=!gh auth git-credential' push -u origin BRANCH and refuses --force, -f, --force-* and a + refspec. templates/AGENTS.md (and so templates/CLAUDE.md, and the kit's own AGENTS.md/CLAUDE.md) state the form and name jpdev push; docs/adopting.md mentions it.
  • lib/wrap.sh runs Go steps with GOFLAGS=-mod=readonly (The Go wrapper runs with -mod=mod and can rewrite go.mod; use -mod=readonly #7); config/env.example notes it. A module the files lack now fails the step, as in CI.
  • docs/policy.md states the cross-vendor rule and how a Codex build is run; README.md lists the commands and settings.

Public surface changed: new commands and settings, templates/AGENTS.md, and the Go cap in lib/wrap.sh. Their tests and documentation are in this pull request.

Checks

shellcheck ran as in CI (shellcheck -x -P ".:SCRIPTDIR" over the same file list) with shellcheck 0.10.0 installed in a temporary virtual environment, because the machine has none.

== check summary (dev.json) ==
PASS     diff-check               0s
PASS     local-paths              0s
PASS     agent-docs               0s
    sync-agent-docs: CLAUDE.md matches AGENTS.md
    sync-agent-docs: CLAUDE.md matches AGENTS.md
PASS     bash-n                   0s
    bash -n: every script parses
PASS     json                     0s
    parsed 5 JSON documents
PASS     shellcheck               2s
    shellcheck: clean
PASS     tests                    31s
    226 passed, 0 failed
== 7 passed, 0 failed, 0 skipped, 0 not run ==

Tests went from 102 to 226. A stub codex (and a stub git and gh for the push and pull request calls) is first on PATH in every test; the real programs are not called. Each safeguard was broken in a scratch copy and the tests failed: -mod=readonly back to -mod=mod (4 failures, including go.mod byte-identity), the force refusal (7), < /dev/null (1), the trailer (2), -s on the commit (1), the brief check before the run (2), git add -u to -A (21), the network setting (1).

Not in this PR

  • The six adopted repositories re-sync their agent docs (templates/AGENTS.md, CLAUDE.md) in a later row; none is touched here.
  • No version change and no release notes; the maintainer releases.
  • New files that Codex creates are not committed unless named with --add; the command lists the untracked files it left out.

🤖 Generated with Claude Code

kikashy and others added 2 commits October 20, 2026 18:59
jpdev codex run runs a Codex CLI build from a brief with the model, effort
and sandbox explicit, stdin closed and the transcript in a log, then commits
the tracked changes (signed off, message from msg.txt, Codex trailer), pushes
and opens the pull request from pr.md. jpdev codex check-brief refuses a
brief that holds a word of config/codex-words.txt (or of the file named by
JPDEV_CODEX_WORDS) and suggests the neutral phrasing. jpdev codex
brief-template prints the brief skeleton.

jpdev push [BRANCH] runs the gh credential-helper push form and refuses
--force and -f. templates/AGENTS.md (and CLAUDE.md) state the form.

lib/wrap.sh runs Go steps with GOFLAGS=-mod=readonly, so a step no longer
rewrites go.mod.

docs/policy.md states the cross-vendor rule. Closes #9, #6, #7.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Signed-off-by: kikashy <kikashy@hotmail.com>
… every path

check-brief matches the whole text, with whitespace and hyphens between the
words of a term, so a wrapped or hyphenated term is found; the line reported
is the one the match starts on.

codex run calls the push in a subshell, so the failure message prints when
the push dies through jpdev_die as well as when git push fails.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Signed-off-by: kikashy <kikashy@hotmail.com>
@kikashy

kikashy commented Oct 20, 2026

Copy link
Copy Markdown
Contributor Author

Narrow review record (same vendor, not a cross-vendor claim)

Reviewer: a clean-room Claude Sonnet agent, read-only; the kit tests once and four stubbed probe groups; the real codex never called. Verdict on the reviewed head: mergeable — head 54faf09039267d281140dfce7f402e8e82bdd522 (one MEDIUM, one LOW). Since the next devkit tag is not cut, the pre-release batch is the same builder's one round on this branch (the disposition names the fixing commit). Verbatim report follows, with scratch paths reduced.


Review of judgment-pack-devkit PR 10, head 54faf09. One MEDIUM, one LOW, no HIGH.

Findings

  1. MEDIUM: the brief check is bypassed by a line wrap or a hyphen inside a multi-word term. lib/codex_words.py lines 49-52 build the pattern with \s+ between the words of a term, then match line by line (enumerate(lines)), so a term split across two lines never matches. A hyphen is not in the separator class either.

    • Confirmed by running: a two-word term is refused on one line; the same term hyphenated or split across a line break passes. The same goes for a hyphen or a zero-width character inside a single word.
    • A brief wrapped near 100 columns can split a two-word term across lines by chance. This affects the six multi-word terms of the list.
    • Fix: match against the whole text, not per line. Use [\s-]+ as the separator between a term's words, and report the line of the match start. Add a test for a wrapped term and a hyphenated term.
    • No test covers either case; tests/run.sh only exercises single-line terms. Single-word evasion (hyphen or zero-width inside the word) is inherent to a word list and not worth fixing.
  2. LOW: bin/jpdev line 206, cmd_push "$branch" || {…"the push failed; the commit $sha is local"…}. If cmd_push calls jpdev_die (for example check-ref-format fails), it exits the whole script with status 2 before that message prints. A plain git push failure does reach the message. Fix: run cmd_push in a subshell or return an error code. Confirmed by reading only.

Questions 1-5: all pass

  1. Model and effort are explicit. run dies without --model (unless JPDEV_CODEX_MODEL_DEFAULT is set, which defaults to none) or without --effort low, medium or high. An invalid --sandbox is refused. The stub recorded exec -m m1 -c model_reasoning_effort=medium --sandbox workspace-write -c sandbox_workspace_write.network_access=true -C <dir> -o <tmp> <prompt>. Stdin is /dev/null. The network option is added only for workspace-write. danger-full-access happens only when passed explicitly.
  2. The git part (probe: stub codex editing a tracked file and writing msg.txt and pr.md, with stub git push and stub gh): only the tracked change was committed; created.txt was left out and listed as untracked; the trailer was added and Signed-off-by was present; the push was the credential-helper form with no force; gh pr create --repo O/N --base main --head work --title "Fix thing" --body-file pr.md was called; no edit gave "nothing to commit" and exit 1; a clone on main is refused before codex runs; a missing msg.txt or pr.md is refused; --add of msg.txt or pr.md is refused, and a staged one is reset and refused. --no-commit, --no-push, --no-pr are covered by the suite.
  3. Brief check: a brief with a listed word is refused with a suggested phrasing; a neutral brief ("Refuse a request that names an unknown field, exit 2") passes; JPDEV_CODEX_WORDS extends the list; run calls the check before codex exec (a tripping brief gave exit 1 and the stub was never reached). The bypass is finding 1.
  4. jpdev push runs the credential-helper form; --force, -f*, --force-* and +refspec are refused (six forms tested); -u is refused as unknown. templates/AGENTS.md states the push form and names jpdev push; CLAUDE.md is synced. The PR touches only the kit.
  5. -mod=readonly: lib/wrap.sh line 39 sets GOFLAGS=-mod=readonly inside the locked inner shell, so an environment GOFLAGS does not reach the step (tested). The go.mod byte-identity test also checks that -mod=mod does rewrite the test module. config/env.example notes GOFLAGS.

Question 6: hygiene. tests/run.sh: 226 passed, 0 failed; only the stubs are used. bash -n passes. git diff --check clean; no machine-local path and no personal name. The version is still 0.2.0. docs/policy.md states the cross-vendor rule as #9 does. shellcheck is not installed on this machine; the CI lint check is SUCCESS. gh pr checks 10 before the verdict: lint SUCCESS, DCO SUCCESS, tests QUEUED.

What I ran. tests/run.sh once under ulimit -v and timeout; four stubbed probe groups (the full run, the refusals, the no-edit case, the brief check) from <scratch>/probe-dk10-run/probe.sh; the clone at <scratch>/review-devkit-10, unchanged.

Under the severity rule (the merge waits only for HIGHs), the MEDIUM is filed and fixed with the pre-release batch rather than blocking this PR.

mergeable — head 54faf09


Disposition

# Severity Disposition
1 MEDIUM The pre-release batch for the next devkit tag is this same round: fixed on the branch before the merge (commit 9151abf): whole-text matching with [\s-]+ between a term's words, the match's line reported, tests for a wrapped and a hyphenated term.
2 LOW Rode: the push failure message prints on every failure; a test with a failing stub push.

Merged on green CI after the round.

@kikashy
kikashy merged commit c7129e5 into main Oct 20, 2026
3 checks passed
@kikashy
kikashy deleted the jpdev-codex branch October 20, 2026 23:08
@github-actions

Copy link
Copy Markdown

🎉 Thank you for your contribution to Judgment Pack!

If you’d like another task, choose a path that interests you:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant