Skip to content

v2.32.0 — dispatch budget, richer recording, and artifact gitignore guidance

Choose a tag to compare

@cheezy cheezy released this 02 Aug 01:06
· 29 commits to main since this release

Ports three more stride-side changes into this GitHub Copilot port — an explicit session budget with a named environment context on the Step 5.5 / Phase 3.5 dispatch, richer session recording, and .exploratory/ gitignore guidance — plus two later refinements of the same prose. Prompt text only; the companion stride-copilot-exploratory-testing plugin is untouched.

Added — an explicit session budget and a named environment context

The dispatch said only "passing the running-app environment context": what that had to contain was nowhere stated, and Step 5.5 passed no budget at all — an unbounded dispatch inside an autonomous workflow, against a live application.

  • Eight named inputs, packed into the single free-text block the explorer agent takes alongside the charter, two of them safety-bearing: the authorized non-production confirmation (recorded here, not re-opened — the determination itself already happens before dispatch, per v2.31.0). Where that warrant comes from is stated, because it differs from the canonical plugin: there a human affirmative is collected once at Step 0 and may be neither supplied nor inferred; this port has no such collection point and never prompts between steps, so the confirmation is one the orchestrator establishes from the environment — the target is authorized because it is the task's own local or explicitly non-production instance. That is a narrower warrant, and it is why the determination fails closed: with no other source to fall back on, an unestablished target means no dispatch at all (never supplied on the user's behalf), and a pointer to where test accounts live, never inlined credentials, because the dispatch prompt is an artifact like any other.
  • The budget is the caller's to set, in whatever unit the installed contract declares — the two plugins release independently, so the unit is established from stride-copilot-exploratory-testing/agents/explorer.agent.md rather than hardcoded here. Today that is probes: default 12, band 8–20, tool-call ceiling 5×, whichever is reached first ending the session and recorded in stop_reason. If it will not fund one workable charter, do not dispatch at all — the band is per dispatch, not a pool to divide.
  • Phase 3.5 was passing the wrong unit. Its dispatch list said "Any test accounts or seed data, and the time box" — a wall-clock box, against an installed contract that states outright it has no duration and no tbs and will not report a duration it never measured. That bullet is replaced rather than supplemented: never hand a wall-clock box to a probes contract.
  • Budget exhaustion is a normal outcome that never fails completion. What changes is only what may honestly be claimed: charter_quiet (and risk_acceptable) is the only ending supporting "this manual test was performed"; probe_budget_exhausted is valid partial findings with an incomplete coverage claim; tool_call_ceiling and blocked are judged on the session sheet, not on the word — at or near zero probes both mean the session did not happen, so it is recorded as not performed and the manual test handed back, while after meaningful probes both are partial coverage. Claiming a spun-out session as a performed manual test is worse than not running the plugin at all, because the plugin-absent path at least flags the test as still owed. Leftover risk goes to a filed follow-up with an ID, never to a "follow-up charter", which has no identifier and no lifetime past the session.
  • Capture everything the dispatch returned, the session sheet included, establishing its fields from the installed contract rather than from the page — enumerating them here is how a later contract change silently drops one.

Added — richer recording: stakeholder impact, the artifact path, and a completion_summary mirror

  • Each finding now names who is harmed and how, not only its severity — a severity word says how bad the failure is, not who it lands on, which is what a reader triaging the Review queue needs. Read from the installed contract's bugs[].stakeholder_impact (emitted honest-or-"could not establish"), restated and redacted rather than pasted; where a contract emits none, say who is harmed in your own assessment or say plainly that the session did not establish it. Never invent an impact the session did not support.
  • The artifact's path is cited when one exists — and the text is explicit that usually it does not. The explorer agent is not asked to write a session file, and the plugin's own session skill attributes session-sheet writes to the -explore, -pair and -debrief skills, none of which Step 5.5 dispatches — so on the automated path the prose summary is the normal and complete record rather than a degraded fallback. The reasoning is deliberately narrower than the reference's: the agent's tools: list holds no write tool but does hold run, a shell surface, so "no write tool" does not settle it. Record the path, never the contents, repository-relative, since an absolute path discloses a username and machine layout and the artifact may hold unredacted output.
  • One line is mirrored into completion_summary, which is required, persisted and rendered on the Review queue, where completion_notes is persisted only by newer servers. It matters most in the case that looks safest — a small task with no reviewer, where completion_notes is the only carrier. This is not a new field and not a third record: the two carriers remain the sole carriers of the record, and the mirror is a durability backstop on an already-required field.
  • Redaction now binds explicitly on the impact text and the artifact path, and on every finding field that carries secrets, as examples rather than a closed list — the rule is the sink, not the field name. Restating is not redacting: a faithful paraphrase carries an account name, a customer email and a hostname through untouched, so redact by generalising the referent, and name a finding rather than quoting it when its text carries a secret.

Added — .exploratory/ gitignore guidance, delivered at Step 0

Session artifacts land under .exploratory/, hold transcribed application output — the exact material the redaction rules keep out of the completion payload — and arrive untracked. An operator's ## after_doing that stages everything (git add -A) sweeps them into a commit, which is far harder to walk back than a payload field.

  • Step 0 gains item 3, which is the delivery point: Step 5.5 runs only once a session is already under way, so it is structurally too late. It names .stride/, .stride_auth.md and the three hook temp files unconditionally, and adds .exploratory/ only when the exploratory plugin is installed. Step 5.5 and Phase 3.5 carry the reasoning as the agent's reminder of what to say.
  • Operator guidance only — the workflow never edits their .gitignore. git commit -a is named as the safe shape against git add -A, and the sweeper is correctly attributed: this plugin's own hooks/stride-hook.sh stages nothing. An already-committed artifact needs git rm --cached, because .gitignore is inert for a tracked path.
  • The line's limits are stated, not glossed: it protects the default locations only, and since all seven command-derived skills accept --output, a redirected destination outside .exploratory/ carries the same transcribed output with no protection from that entry. The cited artifact path is also rendered inert on the same terms as an unrecognized severity string, since a path learned rather than authored is application-influenced text and completion_notes renders as Markdown on the Review queue.
  • README.md's existing gitignore sentence is extended rather than replaced, and gains .stride/ and .stride_auth.md, which it had never named despite the port creating both.

Fixed — a blocked session is recorded as an obstacle, not as a finding

Both skills said an unreachable app should have its obstacle "reported as a finding". That hands it to the absent-severity rule, which maps it to important — filing an unreachable dev server as an important testing finding whose worst impact the agent is then asked to name. The installed contract requires a blocked session to set its status, record the obstacle in its debrief and not fabricate results, so the obstacle lives there carrying no exploratory severity. A blocked session that returns bugs is no contradiction — those are real observations recorded on their own terms; only the obstacle is never one. Coverage is judged from the sheet rather than the word, so a blocked session at or near zero probes takes the same disposition as a zero-probe ceiling hit.

Added — where the exploratory session's wall-clock goes

The port forbade the wrong answer in one skill and gave the right answer for the sibling deep-security dispatch in another, while saying nothing at the site where the question arises. It now says it: fold the session's wall-clock into the existing reviewer workflow_steps entry, never a seventh step name. The wall-clock is the orchestrator's own measurement, never a field read out of the session sheet — today's contract carries no duration and no tbs. When no reviewer ran, that entry is the skip form carrying no duration, so the dispatch is recorded in completion_notes rather than given an invented one; that case is routine here, since this gate has no review precondition.

Scope

Prompt text and documentation only. No completion field is added, removed, or made required; no seventh workflow_steps name; no enum, schema, hook-script or agent change. No trigger condition moves — the budget-too-small and unestablished-target refusals are post-gate dispatch decisions, so every path still skips gracefully when the plugin is absent. Deliberately not in this release: the optional -harden sub-step and its after_doing sequencing.