Skip to content

feat: add wt step eval for template expression evaluation#1004

Merged
max-sixty merged 12 commits intomainfrom
arbitrary-data
Mar 16, 2026
Merged

feat: add wt step eval for template expression evaluation#1004
max-sixty merged 12 commits intomainfrom
arbitrary-data

Conversation

@max-sixty
Copy link
Copy Markdown
Owner

Summary

  • Add experimental wt step eval subcommand that evaluates a minijinja template in the current worktree context and prints the result to stdout
  • Reuses existing hook template infrastructure — all variables (branch, repo, worktree_path, etc.) and filters (hash_port, sanitize, sanitize_db) are available
  • Output goes to stdout with no decoration or shell escaping, designed for scripting and shell substitution
$ wt step eval '{{ branch | hash_port }}'
16066

$ curl http://localhost:$(wt step eval '{{ branch | hash_port }}')/health

This is the first step from the IDEAS.md design doc, directly addressing the user request in #947 — "found no way to run it on a single branch."

Test plan

  • 6 integration tests: basic branch, hash_port, multiple values, sanitize_db, conditionals, template error
  • Help text and completion snapshots updated
  • stdout guard allowlisted
  • Doc pages auto-synced
  • All lints pass
  • 2360 tests pass (5 pre-existing shell_wrapper failures excluded)

Ref #947

This was written by Claude Code on behalf of @max-sixty

…ntal)

Evaluates a minijinja template in the current worktree context and prints
the result to stdout. Reuses the existing hook template infrastructure
(variables, filters like hash_port/sanitize/sanitize_db).

Designed for scripting — no shell escaping, no decoration, output to
stdout only.

```
$ wt step eval '{{ branch | hash_port }}'
16066

$ curl http://localhost:$(wt step eval '{{ branch | hash_port }}')/health
```

Ref #947

Co-Authored-By: Claude <noreply@anthropic.com>
@max-sixty
Copy link
Copy Markdown
Owner Author

Follow-up PR for per-branch kv state: #1006

This was written by Claude Code on behalf of @max-sixty

max-sixty and others added 4 commits February 13, 2026 16:03
# Conflicts:
#	src/main.rs
#	tests/integration_tests/completion.rs
The merge brought a debug_assert for multiline errors without .context(),
which caught step_eval wrapping TemplateExpandError into a plain anyhow
string. Let the typed error propagate so main.rs handles it via its
TemplateExpandError display handler, producing better output with
template line context and available variables.

Co-authored-by: Claude <noreply@anthropic.com>
# Conflicts:
#	src/cli/mod.rs
@max-sixty max-sixty marked this pull request as ready for review February 19, 2026 21:44
Features 1+2 are implemented across arbitrary-data (step eval) and
kv-state (arbitrary per-branch state, templates, JSON output).
Feature 3 (custom columns) can be tracked as a separate issue.

Co-authored-by: Claude <noreply@anthropic.com>
max-sixty added a commit that referenced this pull request Feb 19, 2026
… code

The CI reviewer was approving PRs without noticing obviously misplaced
files (e.g. IDEAS.md at repo root in PR #1004). It read the diff but
went straight to Rust code review without stepping back to look at the
change holistically. Add a substep prompting the reviewer to look at
what files are being added/changed before reading them in detail.

Co-Authored-By: Claude <noreply@anthropic.com>
max-sixty added a commit that referenced this pull request Feb 20, 2026
…#1117)

## Summary

- **pr-review skill**: adds a substep prompting the reviewer to assess
the PR's shape (what files are being added/changed) before diving into
code details — so obvious misplacements like a scratch file at the repo
root don't slip through
- **nightly review-reviewers**: adds a cross-check step that compares
bot review verdicts against subsequent commits and human comments on the
same PR, identifying things the bot should have caught

Triggered by the bot approving PR #1004 without flagging an `IDEAS.md`
design document at the repo root.

## Test plan

- [ ] Next `claude-review` run: verify the reviewer pauses to assess
file list before code review
- [ ] Next `claude-nightly-review-reviewers` run: verify it cross-checks
review sessions against PR outcomes

> _This was written by Claude Code on behalf of max-sixty_

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude <noreply@anthropic.com>
# Conflicts:
#	src/main.rs
#	tests/integration_tests/completion.rs
# Conflicts:
#	src/main.rs
worktrunk-bot
worktrunk-bot previously approved these changes Mar 11, 2026
Copy link
Copy Markdown
Collaborator

@worktrunk-bot worktrunk-bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CI failed on all three platforms with two test failures caused by this PR:

  1. test_builtin_step_commands_matches_clap"eval" needs to be added to BUILTIN_STEP_COMMANDS in src/commands/alias.rs (the list that prevents aliases from silently conflicting with built-in step commands).

  2. test_eval_template_error — snapshot mismatch; the committed snapshot has env var names that differ from what CI produces. Needs regeneration via cargo insta test --accept.

I can push a fix commit for both if you'd like.

@worktrunk-bot worktrunk-bot dismissed their stale review March 11, 2026 18:21

CI failed: eval missing from BUILTIN_STEP_COMMANDS and snapshot mismatch in test_eval_template_error

The eval subcommand was missing from the alias conflict list, and the
snapshot needed updating for the bright-black → underline style change.

Co-Authored-By: Claude <noreply@anthropic.com>
@max-sixty
Copy link
Copy Markdown
Owner Author

@worktrunk-bot resolve conflicts. consider adding a --dry-run flag to show the reified template

Resolve conflicts from main (doc format changes: badge spans, anchor
links, subdoc restructuring). Add --dry-run flag that prints template
variables and expanded result to stderr for debugging templates.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@worktrunk-bot
Copy link
Copy Markdown
Collaborator

Resolved conflicts and added --dry-run flag to wt step eval.

Conflicts resolved: Three files had conflicts from main's doc format changes (badge-experimental spans, anchor links in operations list, subdoc restructuring). Took main's format and added the eval entries.

--dry-run flag: Shows all template variables and their current values, plus the expanded result — useful for debugging templates:

$ wt step eval --dry-run '{{ branch | hash_port }}'
branch=feature/auth-oauth2
worktree_path=/home/user/projects/myapp-feature-auth-oauth2
...
---
Result: 16066

Variables go to stderr, so --dry-run output doesn't interfere with piping. All 1187 integration tests + 463 unit tests pass locally. Waiting on CI.

worktrunk-bot
worktrunk-bot previously approved these changes Mar 15, 2026
@worktrunk-bot worktrunk-bot dismissed their stale review March 15, 2026 18:03

codecov/patch failed (74.07%) — mostly from merging main, but the dry_run path in eval.rs is also untested. See follow-up comment.

Copy link
Copy Markdown
Collaborator

@worktrunk-bot worktrunk-bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

codecov/patch reports 74.07% — the bulk of the gap is from merging main into this branch (codecov measures all changed lines in the diff, including the merged-in code).

For the eval-specific code: the --dry-run path in src/commands/eval.rs (lines 40–47) has no test coverage. Adding a test_eval_dry_run integration test would close this gap. I can push a fix commit if you'd like.

worktrunk-bot added a commit that referenced this pull request Mar 15, 2026
…oring

The skill said "monitor CI using the approach from /running-in-ci" but
didn't tell the bot to actually load that skill. In 1/3 recent sessions
(run 23116000492, PR #1004), the bot skipped loading it and improvised
with `gh pr checks --watch --fail-fast` (blocked foreground, 600s timeout)
and `sleep 120` — burning 17/37 tool calls (46%) on CI polling.

The other 2/3 sessions loaded the skill and used run_in_background correctly.

Make the instruction explicit: load the skill first, and reinforce the
--watch and blocking-sleep prohibitions inline so the bot sees them even
if it still skips the skill load.

Recurrence of #1316, #1402, #1301.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@max-sixty
Copy link
Copy Markdown
Owner Author

@worktrunk-bot fix codecov

Covers the dry-run code path (lines 40-47 in eval.rs) that was flagged
by codecov/patch as uncovered.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@worktrunk-bot
Copy link
Copy Markdown
Collaborator

Added test_eval_dry_run integration test covering the --dry-run code path in src/commands/eval.rs (lines 40–47). All CI checks pass — codecov/patch hasn't reported a new status for this commit (it may not re-report when the gap is resolved).

Co-authored-by: worktrunk-bot <w@worktrunk.dev>
@max-sixty max-sixty enabled auto-merge (squash) March 16, 2026 05:38
Comment on lines +19 to +20
/// With `dry_run`, prints the template variables and the expanded result
/// With `dry_run`, prints the template variables and the expanded result
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicated line.

Suggested change
/// With `dry_run`, prints the template variables and the expanded result
/// With `dry_run`, prints the template variables and the expanded result
/// With `dry_run`, prints the template variables and the expanded result

max-sixty pushed a commit that referenced this pull request Mar 16, 2026
…1542)

## Summary

- Remove backticks from `/running-in-ci` skill reference in the
review-pr skill so the model treats it as an invocable skill rather than
a code literal.

## Evidence

In run
[23116000492](https://github.com/max-sixty/worktrunk/actions/runs/23116000492)
(review of PR #1004), the bot never loaded `/running-in-ci` and
improvised CI monitoring. The backtick-wrapped reference
(`/running-in-ci`) was likely treated as a code literal rather than a
skill to invoke.

## Test plan

- [ ] Next review-pr sessions should load /running-in-ci before CI
monitoring

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: worktrunk-bot <254187624+worktrunk-bot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
@max-sixty max-sixty merged commit a7f224d into main Mar 16, 2026
24 of 25 checks passed
@max-sixty max-sixty deleted the arbitrary-data branch March 16, 2026 05:55
max-sixty added a commit that referenced this pull request Mar 30, 2026
Adds `wt config state vars set/get/list/clear` commands for storing
custom variables per branch in git config
(`worktrunk.state.{branch}.vars.{key}`). Variables are available in all
template contexts via `{{ vars.key }}` syntax (hooks, `wt step eval`),
with JSON dot access (`{{ vars.config.port }}`) and default filters (`{{
vars.env | default('dev') }}`).

Uses `KEY=VALUE` syntax for `set` — `wt config state vars set
env=staging` — matching Docker `-e`, Heroku `config:set`, Fly `secrets
set`, and worktrunk's own `--var KEY=VALUE` convention. Splits on first
`=` only, so values can contain `=` (URLs, JSON).

The database-per-worktree example now uses `vars` to store the
connection string during `post-start`, replacing the `.env.local`
heredoc pattern. The URL is accessible outside hooks via `$(wt config
state vars get db-url)`.

Includes vars data in `wt list --format=json` output and `wt config
state get` display. Builds on #1004 (`wt step eval`). Part of #947.

## Test plan

- [x] Unit tests for vars template injection (empty, with data, no
branch, JSON dot access, shell escaping)
- [x] Integration tests for vars CLI commands (set, get, list, clear,
clear --all, --branch flag)
- [x] Edge-case tests for KEY=VALUE parsing (values containing `=`,
empty values)
- [x] Integration tests for vars in JSON output (present with data,
absent when empty)
- [x] All 493 unit + 1294 integration tests pass

> _This was written by Claude Code on behalf of max-sixty_

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants