You want an agent to remember a project decision, so you add a helper that reads the conversation when a session ends. Its job is small: identify useful decisions and save them for next time.

But the conversation also contains requests to edit code. What prevents the helper from carrying out one of those requests instead of recording it?

Before enabling that helper, check what it can actually do. A process that only needs to classify text should have no way to edit the project. Instructions telling it to stay on task help explain the job; the runtime needs to enforce the boundary.

A publicly documented incident in the qduc/skills coordinator integration makes this concrete. The memory sidecar was supposed to capture decisions and findings from a transcript. The classifier, called the judge, ran as a non-interactive Term2 agent. The note, dated September 28, 2026, reports that with shell auto-approval enabled, transcript content caused the judge to edit live source during testing.

The integration was paused. The current published policy at the reviewed revision still requires it to remain disabled with the shipped implementation.

This is a repository-documented incident, not an independent reproduction. The public note establishes a reported source-editing failure during testing. It does not establish data loss, an outside attacker, or how often this happened. Those limits matter when drawing a lesson from it.

The helper had more capability than its job required

Here, “sidecar” means a background helper attached to a workflow. This one was designed to capture semantic decisions at session-end and context-compaction boundaries. Current work, blockers, and the next action remained in a separate task record.

That separation makes sense. The implementation’s execution boundary was the problem.

In the published helper code, the prompt labels transcript excerpts as data. It explicitly tells the model not to act on them or call tools, and asks for a single JSON object. The default runner then starts Term2 to produce the answer.

The same code validates the returned proposal before applying memory changes: it checks the response shape, maps event references, and passes the proposal through the task-state helper with an owner and revision. Those checks protect the intended write path. They run after the judge has returned, so they cannot prevent a tool action taken while it was producing its answer.

This gives you two separate questions to verify:

  • Can the model return an acceptable memory proposal?
  • Can it change anything before that proposal is accepted?

A successful answer to the first says little about the second. JSON output is useful for validation, but it doesn’t by itself disable tools. Running in the background doesn’t reduce permissions either.

Give the classifier only the inputs it needs

For an extraction-only job, start with a model call that receives a bounded transcript excerpt and returns a proposal. It shouldn’t need a shell, repository write access, or the main agent’s other action tools.

If the implementation uses an agent runtime, verify the runtime’s actual restrictions. A different working directory is not enough: code that can open an absolute path may still reach the original project. The sidecar’s runner tests check its temporary working directory with a mocked subprocess. That checks how the command is launched; it doesn’t demonstrate filesystem isolation.

Give the helper only the source material needed for the current batch. Avoid inheriting credentials or unrelated project access. Where a sandbox is used, test that its write and network restrictions apply to the actual child process, rather than assuming the parent process’s settings carry over.

Keep the instruction that transcript text is data. It still communicates the task. Pair it with a runtime in which misreading that text cannot turn into a project edit.

Check proposals before saving them

The classifier can propose a decision to remember. A separate, narrowly scoped component can decide whether that proposal is allowed to become durable state.

That component should know the target task and permitted destination independently of the model’s answer. It should reject unsupported operations, stale revisions, missing source references, and oversized or malformed output. A transcript saying “write this somewhere else” must not expand its authority.

Validation also needs to distinguish a user’s decision from the assistant’s suggestion or a quoted request. A well-formed record with a real source reference can still misrepresent what was decided. For uncertain claims, keeping a proposal pending or recording nothing may be better than teaching the next session a false fact.

This is a proposed safeguard, not a claim that the paused integration has been repaired. The public policy still says to leave it disabled. The documented fallback is to keep decisions directly in task-state notes; useful continuity does not depend on enabling this particular helper.

Test what must remain unchanged

An extraction test usually asks whether the right memory came out. Add tests for what must not happen along the way.

Use disposable fixtures, without production credentials or live project access. A sample transcript can contain an old request to edit a temporary canary file, a quoted instruction to ignore the classification task, or a claim that broader permissions were granted. The expected result is still a bounded proposal or a rejection. The canary must remain unchanged, and any attempted action should be denied and observable.

Exercise the real launcher and permission boundary for these checks. Replacing the runner with a function that returns clean JSON is useful for testing the parser, but it removes the behavior you’re trying to constrain.

Also check ordinary failures: invalid output, a timeout, a stale task revision, and the same batch delivered twice. The system should preserve the last accepted state and make a failed capture visible. These are suggested acceptance checks; no new live sidecar test is reported here.

The agent doing the setup should discover the helper’s tools, inherited settings, and write paths, then report the evidence and remaining gaps. You shouldn’t have to predict every way a background process could escape its intended role.

Keep the useful part of the workflow

This series began with recovering context between sessions, then covered verification, scope, and comparing variable results. A memory helper brings those concerns together: it needs a narrow job, evidence that it stays within that job, and enough benefit to justify keeping it.

If a helper whose job is to read conversations can also change your project, pause that integration until the boundary is enforced and tested. Keep recording the decisions through a simpler path in the meantime. Remembering the work is useful; giving every process that reads it the ability to continue it creates a separate responsibility.