# Side-Effects Review — Free-text guard template resolution

**Version / slug:** `free-text-guard-template-resolution`
**Date:** `2026-05-25`
**Author:** `instar-codey`
**Second-pass reviewer:** `Echo`

## Summary of the change

This change fixes how the post-update migrator finds built-in template files.
The free-text guard hook was looking only in the compiled-template layout, but
published packages ship that hook in the source-template layout. The migrator
now has one shared template loader for hook, script, and playbook templates. The
free-text guard and existing similar readers use that loader.

## Decision-point inventory

This change does not add, remove, or modify any block/allow decision. It changes
file lookup for a static built-in template. The free-text guard's own behavior is
passed through unchanged.

- `free-text-guard.sh` — pass-through — installed from the packaged template;
  its blocking rules are not changed.
- `PostUpdateMigrator` template lookup — modified — uses shared lookup instead
  of repeated one-off path checks.

---

## 1. Over-block

No new block/allow surface. Over-block is not applicable to the template lookup
change. The free-text guard may still block exactly the same inputs it blocked
before; this patch only controls whether the hook is installed.

---

## 2. Under-block

This does not change what the guard detects. The remaining failure mode is
package-shape drift: if a future publish stops shipping both supported template
locations, the migrator will fail clearly for the required free-text guard and
skip or fall back for callers that already had softer behavior. The new package
shape test covers the current published layout.

---

## 3. Level-of-abstraction fit

The fix belongs in the migrator because the bug is runtime asset resolution, not
guard policy. A shared helper is the right layer: it keeps package-layout
knowledge in one place and lets each caller decide whether a missing template is
fatal, skippable, or eligible for fallback.

---

## 4. Signal vs authority compliance

**Required reference:** [docs/signal-vs-authority.md](../../docs/signal-vs-authority.md)

- [x] No — this change has no block/allow surface.

The change does not introduce a detector or an authority. It does not decide
whether a message, action, or user request should be blocked. It only locates a
static template file so existing migration behavior can install the existing
hook.

---

## 5. Interactions

- **Shadowing:** no existing decision path is shadowed. Existing template
  readers now share one lookup helper.
- **Double-fire:** no duplicate installer is added. The same migration still
  writes the same built-in hook once.
- **Races:** no shared persistent state is added. File reads are local and
  synchronous, matching the previous migrator style.
- **Feedback loops:** none. The resolver does not feed runtime decisions or
  telemetry.

---

## 6. External surfaces

Existing agents see the external effect on update: the free-text guard hook can
be installed again from the package we actually publish. The hook content and
runtime behavior do not change. There is no new user-facing command, API,
database field, or external service dependency.

---

## 7. Rollback cost

Rollback is a normal patch revert. The change writes no new persistent state and
does not migrate data. If it misbehaves, revert the shared resolver refactor and
ship a patch. Agents that already received the hook do not need repair because
the hook content itself is unchanged.

---

## Conclusion

The review found no new decision authority and no new block/allow behavior. The
main production risk is future package layout drift, and the integration test now
checks the packed package shape and runs the compiled migrator from that shape.
This is clear to ship once CI is green.

---

## Second-pass review (if required)

**Reviewer:** Echo
**Independent read of the artifact: concur**

Echo reviewed the diagnosis and implementation direction during the Threadline
collaboration and signed off on the root cause, shared resolver approach, and
packed-package smoke as the evidence needed before normal CI.

---

## Evidence pointers

- Approved spec: `docs/specs/FREE-TEXT-GUARD-TEMPLATE-RESOLUTION-SPEC.md`
- Plain-language spec overview:
  `docs/specs/FREE-TEXT-GUARD-TEMPLATE-RESOLUTION-SPEC.eli16.md`
- Focused tests: 6 passing.
- Build and lint: passing.
- Packed package smoke: passing.
