Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
0eaaab5
[Spec 1216] Draft configurable Porch gate artifact auto-open
mohidmakhdoomi Jul 23, 2026
57ab712
chore(porch): 1216 init spir
mohidmakhdoomi Jul 23, 2026
35ffddb
[Spec 1216] Initial specification draft
mohidmakhdoomi Jul 23, 2026
1f88037
chore(porch): 1216 specify build-complete
mohidmakhdoomi Jul 23, 2026
668ac67
chore(porch): 1216 spec-approval gate-requested
mohidmakhdoomi Jul 23, 2026
46e4fda
[Spec 1216] Specification with multi-agent review
mohidmakhdoomi Jul 23, 2026
54cdf9d
chore(porch): 1216 spec-approval gate-approved
mohidmakhdoomi Jul 23, 2026
58af527
chore(porch): 1216 plan phase-transition
mohidmakhdoomi Jul 23, 2026
88dfd64
[Spec 1216] Initial implementation plan
mohidmakhdoomi Jul 23, 2026
09565ca
chore(porch): 1216 plan build-complete
mohidmakhdoomi Jul 23, 2026
753c544
[Spec 1216] Plan with multi-agent review
mohidmakhdoomi Jul 23, 2026
500156e
chore(porch): 1216 plan-approval gate-requested
mohidmakhdoomi Jul 23, 2026
b5acfdc
chore(porch): 1216 plan-approval gate-approved
mohidmakhdoomi Jul 23, 2026
fa05259
chore(porch): 1216 implement phase-transition
mohidmakhdoomi Jul 23, 2026
219c221
chore(porch): 1216 implement build-complete
mohidmakhdoomi Jul 23, 2026
7815cc5
chore(porch): 1216 implement re-iter (iter 2)
mohidmakhdoomi Jul 23, 2026
9d9f975
chore(porch): 1216 implement build-complete
mohidmakhdoomi Jul 23, 2026
0abb41d
chore(porch): 1216 implement re-iter (iter 3)
mohidmakhdoomi Jul 23, 2026
adf008d
chore(porch): 1216 implement build-complete
mohidmakhdoomi Jul 23, 2026
32b069f
chore(porch): 1216 advance plan phase → worktree_local_config
mohidmakhdoomi Jul 23, 2026
04d0703
chore(porch): 1216 implement build-complete
mohidmakhdoomi Jul 23, 2026
8aa39ba
[Spec 1216][Phase: porch-toggle] feat: Add artifact auto-open toggle
mohidmakhdoomi Jul 23, 2026
b620356
[Spec 1216][Phase: worktree-local-config] feat: Snapshot personal con…
mohidmakhdoomi Jul 23, 2026
79f2e23
[Spec 1216][Phase: worktree-local-config] test: Verify setup snapshot…
mohidmakhdoomi Jul 23, 2026
93ff6db
chore(porch): 1216 implement re-iter (iter 2)
mohidmakhdoomi Jul 23, 2026
1a52552
chore(porch): 1216 implement build-complete
mohidmakhdoomi Jul 23, 2026
5e7d35e
[Spec 1216] docs: Record Phase 2 approval checkpoint
mohidmakhdoomi Jul 23, 2026
bab43b9
chore(porch): 1216 advance plan phase → documentation_verification
mohidmakhdoomi Jul 23, 2026
7beeb9b
chore(porch): 1216 implement build-complete
mohidmakhdoomi Jul 23, 2026
82d4e0f
chore(porch): 1216 all plan phases complete → review
mohidmakhdoomi Jul 23, 2026
d432d7e
[Spec 1216][Phase: documentation-verification] docs: Document and ver…
mohidmakhdoomi Jul 23, 2026
34ccec7
[Spec 1216][Phase: review] docs: Complete review and governance updates
mohidmakhdoomi Jul 23, 2026
3608246
chore(porch): 1216 review build-complete
mohidmakhdoomi Jul 23, 2026
bcdc30c
[Spec 1216][Phase: review] docs: Commit consultation context artifacts
mohidmakhdoomi Jul 23, 2026
d082b44
[Spec 1216][Phase: review] docs: Address PR consultation feedback
mohidmakhdoomi Jul 23, 2026
deee1bf
chore(porch): 1216 pr gate-requested
mohidmakhdoomi Jul 23, 2026
144619c
chore(porch): 1216 pr gate-approved
mohidmakhdoomi Jul 23, 2026
9b344a0
chore(porch): 1216 verify phase-transition
mohidmakhdoomi Jul 23, 2026
27f1801
chore(porch): 1216 verify skipped: Upstream cross-fork PR must be mer…
mohidmakhdoomi Jul 23, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions codev-skeleton/resources/commands/agent-farm.md
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,36 @@ Customize commands via `.codev/config.json` at the project root:
}
```

### Porch Gate Artifact Auto-Open

When Porch requests a specification, plan, or review gate, it automatically
opens the phase artifact in Tower. This is enabled when the setting is unset or
`true`. Set `porch.autoOpenArtifacts` to `false` to prevent that automatic
`afx open` action:

```json
{
"porch": {
"autoOpenArtifacts": false
}
}
```

This setting controls only Porch's automatic gate artifact opens. A manual
`afx open <path>` still creates a Tower file tab and follows the dashboard's
normal focus behavior.

You can set the preference globally in `~/.codev/config.json`, for the team in
the project's committed `.codev/config.json`, or per engineer and project in
the gitignored `.codev/config.local.json`. Project settings override global
settings, and project-local settings override both.

When the main workspace has `.codev/config.local.json`, Agent Farm copies it
into each builder during spawn and `afx setup`. The builder receives a managed
regular-file snapshot rather than a write-through symlink, so builder edits
cannot change the main workspace's personal config. Running `afx setup` again
refreshes the snapshot from the main workspace.

Or override via CLI flags:

```bash
Expand Down
264 changes: 264 additions & 0 deletions codev/plans/1216-configurable-porch-gate-artifact-auto-open.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
# Plan: Configurable Porch Gate Artifact Auto-Open

## Metadata

- **ID**: 1216
- **Status**: implemented — all phases complete
- **Specification**: [codev/specs/1216-configurable-porch-gate-artifact-auto-open.md](../specs/1216-configurable-porch-gate-artifact-auto-open.md)
- **Created**: 2026-07-22

## Executive Summary

Implement the specification's producer-side opt-out at the existing `porch gate` boundary. Extend the unified config type with `porch.autoOpenArtifacts`, treat only explicit `false` as disabled, and leave manual `afx open` plus dashboard tab focus unchanged.

For Agent Farm builders, synchronize the main workspace's gitignored `.codev/config.local.json` into the builder as a managed file snapshot during both worktree creation and `afx setup`. A copy rather than a symlink preserves the main personal file's mutation boundary: builder reads see the same effective value after spawn/setup, while builder-side edits cannot write through to the main workspace. Re-running setup refreshes the snapshot idempotently.

## Success Metrics

- [x] Unset and explicit `true` preserve the existing automatic open.
- [x] Explicit `false` prevents the real gate command from spawning `afx open` for specification, plan, and review artifacts.
- [x] Gate state, audit commits, artifact-path output, approval instructions, missing-artifact behavior, manual `afx open`, and dashboard focus behavior remain unchanged.
- [x] Global, project, and project-local precedence is preserved.
- [x] Fresh spawn and `afx setup` refresh the builder's personal-config snapshot without linking writes back to main.
- [x] Behavioral tests cover the actual gate-command boundary, not only a boolean helper.
- [x] Relevant build, Porch, config-loader, worktree-setup, and full test suites pass.
- [x] User documentation is updated in both the project and shipped skeleton trees.

## Phases (Machine Readable)

```json
{
"phases": [
{"id": "porch_toggle", "title": "Producer-Side Porch Toggle"},
{"id": "worktree_local_config", "title": "Safe Builder Personal-Config Snapshot"},
{"id": "documentation_verification", "title": "Documentation and End-to-End Verification"}
]
}
```

## Phase Breakdown

### Phase 1: Producer-Side Porch Toggle

**Status**: completed
**Dependencies**: None

#### Objective

Add the public configuration key and enforce it at the sole automatic producer while preserving all gate semantics.

#### Files

- `packages/codev/src/lib/config.ts`
- `packages/codev/src/__tests__/config.test.ts`
- `packages/codev/src/commands/porch/index.ts`
- `packages/codev/src/commands/porch/__tests__/gate-auto-open.test.ts` (new)

#### Implementation Details

1. Add `autoOpenArtifacts?: boolean` to `CodevConfig.porch`; do not require a migration or change the default object.
2. In `gate()`, keep state persistence, artifact resolution, existence checks, path output, and approval output in their existing order.
3. Load the merged config and invoke the detached `afx open` child only when `config.porch?.autoOpenArtifacts !== false`.
4. Print `Opening artifact for human review...` only on the enabled path. The disabled path still prints `Artifact: <relative path>` and the unchanged approval instructions.
5. Test the exported `gate()` command with real temporary Porch state/artifact fixtures and mock only the external child-process boundary. Parameterize specification, plan, and review phases; assert spawn calls, output, and persisted gate state.

#### Acceptance Criteria

- [x] Unset and `true` each launch one `afx open` for an existing mapped artifact.
- [x] `false` launches no child for specification, plan, or review artifacts and emits no inaccurate opening message.
- [x] Missing/unmapped artifacts launch no child regardless of configuration.
- [x] Disabled execution still records the pending gate and prints the artifact path plus approval instructions.
- [x] Config-layer tests prove global/project/local override behavior for the new boolean.
- [x] Targeted Porch and config tests pass.

#### Test Plan

- **Unit:** Extend unified loader tests for unset, true, false, and precedence.
- **Behavioral integration:** Call the real `gate()` implementation against temporary status/protocol/artifact files, mocking `spawn` only to observe the `afx open` process boundary.
- **Regression:** Assert enabled arguments and detached/unref behavior remain unchanged.

#### Rollback Strategy

Revert the config type, gate conditional, and focused tests together; the pre-feature unconditional open path is restored without state migration.

#### Risks and Mitigations

- **Risk:** The default is accidentally inverted.
**Mitigation:** Use an explicit `!== false` condition and distinct unset/true tests.
- **Risk:** Config parsing couples the convenience action to gate persistence.
**Mitigation:** Retain the state-write ordering and assert the pending gate before observing the child-process decision.

---

### Phase 2: Safe Builder Personal-Config Snapshot

**Status**: completed
**Dependencies**: Phase 1

#### Objective

Make the main workspace's per-engineer preference available in Agent Farm builders after fresh spawn and reconfiguration without exposing the main personal file as a write-through symlink.

#### Files

- `packages/codev/src/agent-farm/commands/spawn-worktree.ts`
- `packages/codev/src/agent-farm/commands/setup.ts`
- `packages/codev/src/agent-farm/__tests__/spawn-worktree.test.ts`
- `packages/codev/src/agent-farm/__tests__/local-config-snapshot.test.ts` (new)

#### Implementation Details

1. Add an exported, focused helper that synchronizes `.codev/config.local.json` from `config.workspaceRoot` to the same relative path in a builder worktree using file-copy semantics, never a symlink.
2. Treat the main workspace file as authoritative when present: create the target directory, refresh the snapshot atomically, and preserve the source file unchanged. If no main personal file exists, do not create or delete a builder-local file; this preserves pre-existing builder-local preferences.
3. Call the helper after `symlinkConfigFiles()` and before `runPostSpawnHooks()` in both new-branch and existing-branch spawn paths. In `afx setup`, call it immediately after `symlinkConfigFiles()` and before any post-spawn hooks.
4. Keep the existing `.env`, `.codev/config.json`, and configured `worktree.symlinks` behavior unchanged.
5. Verify refresh/idempotency with real temporary files: initial copy, main-file update plus repeated setup-equivalent sync, builder snapshot mutation, and proof that the main file's bytes never change.

#### Acceptance Criteria

- [x] A fresh builder receives a non-symlink personal-config snapshot when the main file exists.
- [x] The snapshot participates in the existing layer-5 loader and yields the same effective opt-out as main immediately after spawn/setup.
- [x] Reconfiguration refreshes an existing snapshot without duplicate files or precedence drift; repeating it with unchanged input is behaviorally idempotent.
- [x] Editing the builder snapshot cannot mutate the main workspace's personal file, and the next setup refresh restores the authoritative main value.
- [x] An absent main personal file causes no new snapshot and does not delete an existing builder-local preference.
- [x] Existing worktree symlink and post-spawn behavior remains green.

#### Test Plan

- **Unit:** Extend mocked worktree tests to prove both worktree creation paths call the snapshot synchronizer and existing symlink behavior is unchanged.
- **Filesystem integration:** Use real temp directories and `loadConfig()` to verify non-symlink copies, effective values, refresh, idempotency, source immutability, and absent-source handling.
- **Setup path:** Exercise the same helper path used by `afx setup` and assert refresh occurs before configured post-spawn hooks.

#### Rollback Strategy

Remove the snapshot helper and its spawn/setup calls. Existing shared `.codev/config.json` symlinking and all other worktree setup behavior remain intact.

#### Risks and Mitigations

- **Risk:** Snapshot refresh overwrites an intentional builder-only local edit.
**Mitigation:** Document the builder copy as setup-managed when a main personal file exists; main remains authoritative, while absent-source setup leaves builder-local files alone.
- **Risk:** Copy failure leaves a partial JSON file.
**Mitigation:** write/copy to a sibling temporary path and rename atomically, with cleanup and established setup error reporting.
- **Risk:** Snapshot logic changes unrelated worktree symlinks.
**Mitigation:** keep it in a separate helper and retain focused regression tests for `symlinkConfigFiles`.

---

### Phase 3: Documentation and End-to-End Verification

**Status**: completed
**Dependencies**: Phases 1 and 2

#### Objective

Document the public setting and prove the complete disabled flow creates no Tower file tab while manual opens retain their existing behavior.

#### Files

- `codev/resources/commands/agent-farm.md`
- `codev-skeleton/resources/commands/agent-farm.md`
- Test or fixture adjustments identified by the end-to-end verification, only if required

#### Implementation Details

1. Add matching configuration-reference sections to both documentation trees covering the exact key, default/unset and boolean semantics, scope, manual `afx open` non-effect, and global/project/project-local locations. `agent-farm.md` is the canonical target because it already owns the Porch configuration reference (`porch.checks`); verify the overview does not claim an exhaustive key list before deciding that no extra mention is needed.
2. Document that Agent Farm snapshots the main personal config into builders during spawn/setup so the main personal file is not a write-through target; `afx setup` refreshes the snapshot.
3. Run focused tests, the package build, the full relevant test suite, and diff/grep both documentation trees for synchronization.
4. Exercise the actual flow with Tower from inside the builder worktree: keep a non-file tab active, use a builder whose main-workspace personal config disables the feature, invoke `porch gate` in that builder, and verify the tabs API/state gains no file tab and the active tab is unchanged. Then invoke manual `afx open` and verify its file tab still appears and receives normal focus.
5. Repeat the disabled gate after changing the main personal preference and running `afx setup` to cover reconfiguration.

#### Acceptance Criteria

- [x] Both documentation copies contain equivalent public guidance and a valid opt-out example.
- [x] Automated focused suites, full tests, and build pass.
- [x] Disabled `porch gate` creates no Tower file tab and does not change the active dashboard tab.
- [x] Manual `afx open` still creates/focuses a file tab.
- [x] The builder-worktree flow honors a preference sourced only from the main workspace's personal config after fresh setup and reconfiguration.
- [x] No dashboard source is modified; Playwright is not required unless implementation unexpectedly changes UI code.

#### Test Plan

- **Automated:** Run focused Vitest files for config, gate behavior, and worktree snapshot, then the Porch/config/worktree relevant suites and the full package suite.
- **Build:** Run the repository-supported build command from the repository root.
- **Manual integration:** From inside the builder worktree, inspect Tower tab state before and after disabled gate and manual open, including the `afx setup` refresh path.
- **Documentation:** Compare the added sections in `codev/` and `codev-skeleton/` and grep for stale key names or dashboard ownership claims.

#### Rollback Strategy

Revert the matching documentation sections. If end-to-end verification exposes a defect, return to the owning implementation phase rather than weakening or skipping the check.

#### Risks and Mitigations

- **Risk:** A unit-only proof misses a real Tower tab request.
**Mitigation:** require tab-state observation around the actual CLI flow.
- **Risk:** Documentation drifts between project and skeleton.
**Mitigation:** apply equivalent sections in one phase and compare them before commit.

## Dependency Map

```text
Phase 1: Producer Toggle
Phase 2: Safe Worktree Snapshot
Phase 3: Documentation + End-to-End Verification
```

## Integration Points

- **Unified config loader:** public type and five-layer precedence remain authoritative.
- **Porch gate command:** sole automatic `afx open` producer and behavioral test boundary.
- **Agent Farm worktree setup:** both fresh spawn paths and `afx setup` share the personal snapshot helper.
- **Tower tabs API/state:** final observation point proving that disabled producer behavior creates no file tab.

## Resource and Infrastructure Requirements

- Existing pnpm workspace and Vitest harness.
- Temporary filesystem/git fixtures for config and worktree tests.
- A local Tower workspace for final integration verification; no new service, dependency, database, migration, or monitoring infrastructure.

## Validation Checkpoints

1. **After Phase 1:** Gate-command tests prove unset/true/false, phase mapping, missing artifact, truthful output, and preserved state.
2. **After Phase 2:** Spawn/setup tests prove snapshot refresh, idempotency, loader behavior, and main-file immutability.
3. **After Phase 3:** Documentation is synchronized, all automated checks pass, and Tower tab state verifies the real disabled/manual flows.

## Overall Risk Analysis

| Risk | Probability | Impact | Mitigation |
|---|---|---|---|
| Default behavior changes | Low | High | Explicit-false condition plus unset/true regressions |
| Main personal config becomes write-through | Low | High | Managed copy, non-symlink assertion, source-byte immutability test |
| Builder snapshot becomes stale | Medium | Medium | Refresh on `afx setup`, document ownership, test main-change refresh |
| Gate state becomes coupled to convenience config | Low | High | Preserve ordering and test state independently of spawn |
| Docs imply a dashboard preference | Low | Medium | State clearly that Porch producer behavior alone is controlled |

## Documentation Updates Required

- [x] Exact `porch.autoOpenArtifacts` JSON example.
- [x] Unset/true/false semantics and default enabled behavior.
- [x] Scope limited to Porch's automatic gate artifact action.
- [x] Manual `afx open` remains unchanged.
- [x] Global, shared project, and personal project configuration locations and precedence.
- [x] Builder snapshot and `afx setup` refresh behavior.
- [x] Equivalent updates in both `codev/` and `codev-skeleton/` command references.

## Expert Review

- **Status:** Complete — Gemini and Claude approved; Codex returned a high-confidence comment with two non-blocking clarifications.
- **Feedback incorporated:** The Tower verification now explicitly runs `porch gate` inside the builder worktree; `agent-farm.md` is confirmed as the canonical Porch config reference, with an overview exhaustiveness check; snapshot insertion ordering is explicit after symlinks and before post-spawn hooks.

## Approval

- [x] Specification approved
- [x] Three-way plan consultation complete
- [x] Human plan approval

## Change Log

| Date | Change | Reason |
|---|---|---|
| 2026-07-22 | Initial implementation plan | Translate approved specification into three independently testable phases |
| 2026-07-22 | Plan updated after three-way review | Clarify builder-cwd verification, canonical docs, and snapshot ordering |
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Rebuttal — `porch_toggle` iteration 1

## Codex: required gate-boundary tests appeared absent

The requested behavioral test already exists at
`packages/codev/src/commands/porch/__tests__/gate-auto-open.test.ts`. It was
untracked when Consult generated Codex's changed-file list, so that static list
omitted the file even though it was present in the worktree. The file is now
explicitly staged so the next review prompt includes it.

The test calls the real exported `gate()` command with temporary protocol,
state, config, and artifact fixtures while mocking only
`node:child_process.spawn`. It covers:

- unset and explicit `true` enabled behavior, including spawn arguments,
detached execution, and `unref()`;
- explicit `false` for specification, plan, and review artifacts;
- truthful disabled-path output and persisted pending-gate state;
- missing mapped artifacts under unset, `true`, and `false`; and
- an unmapped phase.

No implementation change was required in response to this review; the issue was
review-input visibility, not missing coverage. The focused suites pass 96/96,
and Porch's full build and test checks pass.

## Claude: implementation changes are not yet committed

This is expected during Porch's build/verify cycle. Porch commits the complete
plan-phase change only after reviewers approve it; committing manually before
that transition would bypass the strict-mode orchestration. The implementation,
tests, and adjacent HOME-isolation regression fix remain ready for Porch's
phase-completion commit after re-verification.
Loading
Loading