Skip to content

chore: release - merge dev into main#1288

Merged
zbigniewsobiecki merged 23 commits into
mainfrom
dev
May 9, 2026
Merged

chore: release - merge dev into main#1288
zbigniewsobiecki merged 23 commits into
mainfrom
dev

Conversation

@zbigniewsobiecki
Copy link
Copy Markdown
Member

Automated release PR created by the release workflow.

Commits (23):

cc90d069 Merge pull request #1285 from mongrel-intelligence/fix/cascade-tools-help-stdout-strict
2757cc91 refactor(triggers): share worker resolution and concurrency (#1286)
93d566af fix(cascade-tools): drop dead github/trello topics with no CLI commands
072f81b3 fix(cascade-tools): drop inherited LLMIST_LOG_TEE so stdout stays envelope-only
ffc0e8e7 refactor(triggers): thin agent execution facade (#1284)
a8c17c89 chore(cascade-tools): pin oclif strict mode on CredentialScopedCommand
bc23ce09 fix(cascade-tools): explicit topic summaries in --help
0befb548 refactor(github): extract CI dispatch decisions (#1283)
1785bb9e Merge pull request #1281 from mongrel-intelligence/fix/cascade-tools-bool-flag-grammar
82ce18a2 refactor(triggers): share PM status and label decisions (#1282)
e0592010 fix(cascade-tools): handle false values for non-negatable boolean flags
1dde404c refactor(triggers): extract follow-up dispatch helpers (#1280)
ec5e2d61 chore(cascade-tools): add biome-ignore comments for argv/parse-error taxonomies
2566760f fix(cascade-tools): accept --boolFlag value + wrap oclif parse errors in envelope
6be75067 refactor(triggers): extract agent PM summary posting (#1279)
670f26f1 refactor(router): decompose webhook trigger outcomes (#1278)
b5d28cec docs: refresh active documentation (#1277)
d446b5ee Merge pull request #1269 from mongrel-intelligence/refactor/agent-execution-lifecycle
4d4a3737 test(triggers): expand agent-execution-lifecycle coverage for uncovered branches
12914114 fix: address feedback
54f4ad75 Merge pull request #1274 from mongrel-intelligence/feature/trigger-enable-gate-helper
fc6ca422 feat(triggers): centralize trigger enablement checks
1c190613 refactor(triggers): extract agent execution lifecycle

Cascade Bot and others added 23 commits May 8, 2026 15:00
…ed branches

Add four tests that exercise code paths not covered by the original 8:
- validateAgentExecutionLifecycle: skips PM notification when workItemId
  is absent from result (exercises the `result.workItemId` guard)
- prepareAgentExecutionLifecycle: skips prepareForAgent when workItemId
  is absent from context (exercises the `context.workItemId` guard)
- runPostAgentExecutionLifecycle: skips handleBudgetWarning when the
  post-run budget check returns null (no budget field configured)
- runPostAgentExecutionLifecycle: calls handleFailure when the agent
  fails and skipHandleFailure is not set

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs: refresh active documentation

* docs: remove stale architecture diagram embed from README

Replace the embedded docs/architecture.jpg (stale — missing Linear/Sentry
nodes) with a prose note pointing readers to the D2 source and the d2 CLI
render command, so the README no longer surfaces a diagram that contradicts
the updated docs/architecture.d2.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs: remove stale WebhookStep statement from Post-spec-011 table

The Post-spec-011 integration guide row said "The legacy WebhookStep
remains … migration into the manifest path is follow-up scope." Spec 012
completed that migration (WebhookStep deleted, every PM wizard step now
renders via the manifest path), making the statement both false and
internally contradictory with the Post-spec-012 section immediately
below it.

Update the row to reflect that WebhookStep was temporarily retained
during spec 011 and fully migrated in spec 012.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs: fix stale TriggerResult and worker env contract docs

- Remove `waitForChecks?: boolean` from the TriggerResult code block in
  03-trigger-system.md; the field no longer exists in src/types/index.ts
- Move `mergeabilityRecheckAttempt` mention from the JOB_TYPE row to the
  JOB_DATA row in 01-services.md; the router serializes it into the GitHub
  job object inside JOB_DATA, not as part of the job type string

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Cascade Bot <bot@cascade.dev>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Cascade Bot <bot@cascade.dev>
Co-authored-by: Cascade Bot <bot@cascade.dev>
… in envelope

Prod 2026-05-09: 9/14 codex runs that called pm read-work-item hit
`--includeComments true` with `exit=2` and empty stdout — silent failures
that triggered help-read storms and wasted iterations. Two coupled regressions
against spec 014:

1. nativeToolPrompts.formatParam emitted `# example: --includeComments 'true'`
   for boolean flags whose example was a literal `true|false`. Oclif's
   `Flags.boolean({ allowNo: true })` rejects that form — the prompt taught a
   syntax the CLI rejected ("no prompt lying" rule violation).

2. Oclif's `FailedFlagValidationError`, `FlagInvalidOptionError`, and
   `UnexpectedArgsError` escaped the existing unknown-flag catch in
   cliCommandFactory. Parse-time failures bypassed emitCliError, so the agent
   got exit 2 with no envelope to self-correct from.

Fixes:
- formatParam now renders boolean examples as the canonical toggle (`--key`
  or `--no-key`), never `--key 'true'`.
- cliCommandFactory.execute pre-processes argv so boolean flags accept
  `--key true|false|yes|no|1|0` (space- or equals-separated, case-insensitive),
  rewriting them into oclif's canonical toggle. Malformed values surface
  inline through emitCliError as a `flag-parse` envelope with `got`,
  `expected`, and `hint` populated.
- classifyParseError wraps the three oclif parse-time error classes into
  structured envelopes (missing-required, enum-mismatch, flag-parse fallback).
- New static guard at tests/unit/gadgets/shared/promptExamplesGrammar.test.ts
  iterates all 23 production gadget definitions and asserts the rendered
  prompt never contains `--<bool-flag> 'true'` / `'false'` for any boolean
  param. Verified to fail loudly when the renderer fix is reverted.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…taxonomies

Mirrors the existing pattern at formatParam / formatExampleLine — both
flagged for the same noExcessiveCognitiveComplexity rule with the same
"-taxonomy" rationale. The two new functions added in the previous commit
(massageBooleanFlagValues, FactoryCommand.execute's catch chain) are also
shape-driven taxonomies that read more clearly inline than split.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* refactor(triggers): extract follow-up dispatch helpers

* fix(triggers): restore non-fatal boundary around recursive review pipeline execution

The refactor moved the recursive `runAgentExecutionPipeline` call for
post-completion review outside of any try/catch, allowing exceptions from
the nested review pipeline (lifecycle hooks, validation, engine execution)
to bubble up and fail the implementation run after it had already succeeded
and produced a PR.

Restore the best-effort boundary by wrapping the recursive call in a
try/catch that logs a warn and lets the implementation pipeline complete.
Add a facade test covering the case where the review pipeline throws.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Cascade Bot <bot@cascade.dev>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
`massageBooleanFlagValues` was rewriting every recognised false value to
`--no-<name>`, but oclif only accepts that form for flags declared with
`allowNo: true`. `scm create-pr`'s `draft` flag has no `allowNo`, so
`--draft false` / `--draft=false` was emitted as `--no-draft` and oclif
rejected it as an unknown flag — leaving the PR's promised `--boolFlag
true|false` support incomplete for one production command.

Fix: `collectBooleanFlagNames` now returns a `Map<string, boolean>` where
the value tracks `allowNo`. The preprocessor emits `--no-<name>` only when
`allowNo` is true; for non-negatable booleans a `false` value simply
consumes the token without pushing anything (flag absence = false, which is
the correct oclif parse result). Malformed-value error hints are updated to
not suggest `--no-<name>` for non-negatable flags.

Three new tests added covering the `draft`-style case:
- `--draft false` (space-separated) → no unknown-flag error
- `--draft=false` (equals-separated) → no unknown-flag error
- `--draft true` → still works

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Cascade Bot <bot@cascade.dev>
Co-authored-by: Cascade Bot <bot@cascade.dev>
When `pjson.oclif.topics` is unset, oclif borrows each topic's description
from its first command (`node_modules/@oclif/core/lib/config/config.js` —
`this._topics.set(name, { description: c.summary || c.description, name })`).
That made bare `cascade-tools --help` show:

  pm        Add a checklist with items to a work item. ...
  scm       Create a GitHub pull request. Handles the full workflow ...
  alerting  Retrieve full details for an alerting event ...
  session   Call this gadget when you have completed all tasks ...

Agents reading bare --help to map the surface got a misleading frame (saw
≥ 2× in the 2026-05-09 prod corpus). Set explicit topic summaries so each
TOPICS line is one truthful sentence per topic.

Also covers the two direct-provider topics (`github`, `trello`) that mirror
the canonical `scm` / `pm` surfaces; their summaries point operators back to
the provider-agnostic topic.

Regression net at tests/unit/cli/cascade-tools-help.test.ts pins both the
borrowed-description-must-not-appear and canonical-summary-must-appear
invariants for all six topics.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Locks oclif's documented default (`strict = true`) explicitly. Without it,
unknown flags would slip past parse validation and reach the gadget body as
positional args — silently bypassing the spec-014 `unknown-flag` envelope
even though every cascade-tools command claims to honor it.

Adds a regression test on the factory-generated command surface that asserts
unknown flags fire the structured `unknown-flag` envelope (passes today;
guards against any future drift if oclif loosens the default).

Note: the original 2026-05-09 analysis read run 27be3592 as a strict-mode
gap (`session finish --agent-type review --review-submitted --comment ...`
returning success despite `finishDef` declaring only `comment`). Closer
inspection of `src/cli/session/finish.ts` shows it's a hand-written oclif
command — `--agent-type`, `--pr-created`, and `--review-submitted` are
legitimate CLI extensions, listed in `--help`. Not a real bug. The pin in
this commit is preventive, not a fix.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Cascade Bot <bot@cascade.dev>
…elope-only

Prod 2026-05-09: 75/120 cascade-tools calls (62%) emitted DEBUG/INFO log
lines + ANSI escapes on stdout BEFORE the JSON envelope, polluting the
agent's tool-result channel.

Root cause: the worker process at `src/backends/llmist/index.ts:83-84`
sets `LLMIST_LOG_FILE=<engineLogPath>` AND `LLMIST_LOG_TEE='true'` so its
own logger tees to both file and stdout. Both env vars are in the
subprocess allowlist (`src/utils/cascadeEnv.ts:14-15`) and pass through to
the bash subprocess that runs cascade-tools. The cascade-tools logger
then ALSO tees, polluting the agent's view.

Fix: strip `LLMIST_LOG_TEE` at the very top of `bin/cascade-tools.js`
(before the singleton logger reads env). With `LLMIST_LOG_FILE` still set,
all logs (including the load-bearing `[image-pipeline] work-item-fetch
summary` per spec 016 / `src/integrations/README.md`) land in the engine
log file the worker collects — operator observability via `cascade runs
logs <runId>` is preserved. For standalone runs (no LLMIST_LOG_FILE
inherited), redirect to /dev/null so dev runs stay envelope-only too;
developers can override with `LLMIST_LOG_FILE=/tmp/x.log cascade-tools ...`.

No source-tree code changes — `src/utils/logging.ts`, the cascade logger
usage everywhere, and the `[image-pipeline]` log line all unchanged. The
fix is one entrypoint env tweak.

Regression net at tests/unit/cli/cascade-tools-stdout-cleanliness.test.ts
spawns cascade-tools as a subprocess under three env shapes (worker /
standalone / dev-override) and asserts stdout matches `^{"success":` with
no ANSI escapes (ESC byte 0x1b absent), no `[cascade]` substring, and no
tab-separated log-level prefixes. Also asserts the engine log file DOES
receive the cascade logger output — the operator-observability invariant.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Remove `github` and `trello` from the explicit topics block in
bin/cascade-tools.js and the matching test assertions. There are no
src/cli/github/* or src/cli/trello/* commands in the source tree, so
oclif filters these topics out of root help on a clean build. The test
expectations only passed against stale dist artifacts, causing CI
failures.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Cascade Bot <bot@cascade.dev>
@zbigniewsobiecki zbigniewsobiecki merged commit 51978d7 into main May 9, 2026
10 checks passed
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