Plan: Issue 181 Lint Feedback Adoption
Plan: Issue 181 Lint Feedback Adoption
Status: Completed Mode: parallel Task identity mode: planning-only Architecture applicability: architecture-bearing
Architecture Applicability
This work changes one capability across five owners: lint policy and scaffold compilation, the managed edited-file runner, provider projection, update publication, and operator guidance. It changes generated public output and adds a process result consumed by several providers. The work is architecture-bearing even though its runtime implementation remains in the CLI surface.
Initial Situation
Harness compiles pack-owned lint assets into generated or adopted Oxlint
configuration and projects format-edited-file.mjs into provider hook
locations. That hook formats edited JavaScript and TypeScript files and runs a
read-only Oxlint check, but discards Oxlint's output and reports a generic
failure. It also starts from the repository root, so workspace-owned typed
settings can be skipped or applied from the wrong working directory.
Collective Intelligence repair commit
1a9927873317cbbeb7e26e909155d7372e24f398 reduced a measured inventory from
54,451 to 51,187 diagnostics by correcting hierarchy and ownership defects.
Substantial historical debt remained. The delivery must separate that adoption
debt from findings produced during an active edit.
The highest supported tuple that passes Effect's explicit Oxlint guard is:
| Package | Version |
|---|---|
@effect/tsgo | 0.39.0 |
oxlint | 1.80.0 |
oxlint-tsgolint | 7.0.2001 |
typescript | 7.0.2 |
ultracite | 7.10.7 |
oxfmt | 0.66.0 |
Oxlint 1.81.0 is outside the Effect 0.39.0 supported range.
Problem
The active agent cannot see the exact lint rule, location, or repair constraint after an edit. Generated hierarchy drift can also create inconsistent root and workspace results. Copying Ultracite's generated hooks does not solve this: they omit Codex, call a project fix script without an edited-file argument, and do not return raw diagnostics to the current Harness agent.
The implementation must use the useful Ultracite behavior without importing its rules, skill, or generated hooks into the default Harness context.
Proposed Solution Shape
agent edit
-> exact accepted path
-> owning workspace
-> staged Oxfmt
-> Oxlint safe fix
-> Oxlint JSON verification
-> normalized lint result
-> Codex or Claude continuation context
-> Cursor message or OpenCode log
-> active agent repairs
-> next edit rechecks, at most three unchanged-fingerprint attempts
hi update
-> materialized candidate state
-> isolated dependency-visible preview
-> per-owner read-only Oxlint JSON check
-> ordinary findings: warn and continue
-> process/config/dependency/output/cleanup failure: stop publication
operator cleanup
-> explicit bounded Ultracite command
-> never automatic from the post-edit hookThe realtime hook calls Oxfmt and Oxlint directly. This keeps raw JSON, path confinement, staged atomic publication, and current-agent feedback under Harness control. Operators use Ultracite's commands where their contracts fit:
bunx ultracite check <bounded-targets>for a deliberate read-only check.bunx ultracite doctorfor setup diagnosis.bunx ultracite fix <bounded-targets>for explicit safe fixes.bunx ultracite fix --codex <bounded-targets>for repair by a separate Codex CLI process.
Omitting targets from check or fix defaults to the current project. The
managed hook never calls ultracite fix --codex.
Resolved Decision Ledger
| Decision | State | Evidence |
|---|---|---|
| One delivery covers hierarchy, reduced policy, versions, realtime feedback, provider projection, adoption preview, and operator workflows. | Locked | User accepted Q1 and added the reduced policy to scope. |
| Automatic mutation is Oxfmt plus safe Oxlint fixes on the edited file only. | Locked | User accepted Q2. |
| Providers share one diagnostic model and use capability-specific response envelopes. | Locked | User accepted Q3. |
| The delivery uses the proven exact six-package version tuple. | Locked | User accepted Q4; live proof rejects Oxlint 1.81.0. |
| Existing adoption debt warns; process, config, dependency, output, or cleanup failures stop publication. | Locked | User accepted Q5. |
| Global policy keeps three disables and removes the six named exemptions. | Locked | User accepted Q6 after the stricter effect was made explicit. |
| Ultracite commands are explicit bounded operator tools. | Locked | User follow-up and pinned 7.10.7 CLI inspection. |
| Ultracite AI rules, skill, and generated hooks stay out of default Harness context packs. | Locked | Initial constraint and research. |
Planning uses local Tn identities and performs no backlog mutation. | Locked | No provider Task projection was requested. |
Dependency Readiness
Ready. The research report records a disposable live probe of the exact tuple,
a successful lint-only Effect patch, combined Ultracite and Effect preset
loading, and a structured effecttsgo(floating-effect) diagnostic. Pinned
Ultracite 7.10.7 help and source confirm the bounded target forms.
Branch/Base Intent
- Parent/base branch:
main. - Parent/base commit:
694420ca15c8b37536338e85719c6ec00a7154df. - Child branch:
team/stefan/fix/ultracite-lint-config. - Keep implementation on the child branch until normal review and merge.
Assumptions and Constraints
- Root lint preserves nested-config discovery; workspace lint runs from its owning workspace.
- Formatting checks remain separate from lint checks in generated scripts.
- Typed lint settings activate only in the workspace that owns them.
effecttsgois registered only when the selected asset and compatible dependencies support it.- Adoption mutates new or receipt-owned output, or an exact recognized legacy Harness shape. Project-owned variants are preserved and reported.
- Retry state is temporary and keyed by provider session, repository, file, and normalized diagnostic fingerprint.
- Project-local Codex hook trust stays platform-owned. Live validation includes
the manual
/hookstrust action. - No release or publication is part of the implementation plan.
Codebase Findings
apps/cli/src/data/catalog/lint.tsowns presets, plugin requirements, dependency versions, and prepare commands.apps/cli/src/scaffold/output.tsowns generated/adopted Oxlint configuration, dependency entries, and managed receipts.apps/cli/src/content/wiki.tsandapps/cli/src/scaffold/stage.tsown the default generated wiki package and lint configuration.apps/cli/src/data/hooks/format-edited-file.mjsowns path confinement, staged formatting, atomic publication, Codex session state, and provider output.apps/cli/src/data/scripts/harness-projection/adapters/*.mjsandapps/cli/src/data/scripts/sync-subagents.mjsown provider projection.apps/cli/src/update/run.tsmaterializes desired state in apunks-update-*staging directory before reconciliation and already has a cleanup finalizer.apps/cli/src/runtime/scripts.tscaptures process status, stdout, stderr, and spawn errors.apps/cli/src/presentation/operation-result/*owns public update warnings, handled failures, and machine-readable facts.packages/config/public-config-contract.test.tsandapps/cli/src/cli/behavioral-portfolio.test.tscover dependency ownership and public scaffold/update behavior.- No focused automated test proves remaining Oxlint diagnostics or provider response payloads from the edited-file runner.
External Research Used
- Ultracite 7.10.7
check [files...]andfix [files...]accept bounded paths or globs. Without targets, both fall back to the current project. fixruns Oxfmt and safe Oxlint--fix;--unsafeswitches to dangerous fixes and is excluded from all automatic paths.fix --codexapplies automatic fixes, groups remaining JSON diagnostics by file, launches a separate Codex CLI, re-lints, and retries up to three times.- Ultracite generated hooks omit Codex and do not pass the edited path to their project fix command.
- Codex synchronous
PostToolUseacceptsdecision: "block"andhookSpecificOutput.additionalContext, returning feedback to the same turn. - Repository-local Codex hooks require manual trust; a changed definition invalidates that trust.
- Ultracite rules and its reusable skill provide guidance, not runtime diagnostic transport.
parallel-research covered upstream AI surfaces, the current hook/projection
path, the 50k consumer case, dependency compatibility, and adoption-preview
placement. Pinned source and live help resolved the bounded command syntax.
Target Ownership Topology
| Responsibility | Owner | Allowed consumers |
|---|---|---|
| Lint policy, hierarchy, and compatible tool declarations | Lint catalog and scaffold compiler | Scaffold, update, config tests, generated repositories |
| Safe edited-file execution and normalized lint result | Managed edited-file runner | Provider runtime branches and update preview adapter |
| Provider capability and hook configuration | Harness projection adapters | Codex, Claude, Cursor, OpenCode generated configuration |
| Candidate adoption classification and publication gate | Update orchestration | Operation-result presentation and reconciliation |
| Bounded Ultracite and hook-trust guidance | CLI/scaffolding runbooks | Operators and implementation agents |
Public Seam Contract
Normalized lint result
The edited-file runner returns one discriminated process result:
type LintFeedbackResult =
| { status: "clean"; files: string[] }
| {
status: "findings";
diagnostics: LintDiagnostic[];
fingerprint: string;
attempt: number;
exhausted: boolean;
}
| {
status: "operational-failure";
stage: "format" | "lint-fix" | "lint-verify" | "config-load";
command: string;
exitCode?: number;
message: string;
};LintDiagnostic contains file, rule, severity, line, column,
message, and optional help and documentation. The runner normalizes raw
tool output once; provider projections and update presentation do not parse
Oxlint output again.
Provider response
- Codex findings return
decision: "block", a short reason, and actionablehookSpecificOutput.additionalContextforPostToolUse. - Claude findings return actionable additional context through its native post-edit response.
- Cursor receives a
user_message; OpenCode logs the same facts once. - Clean results emit no repair message.
- Exhausted results stay visible but do not request another retry.
Generated lint hierarchy
The scaffold compiler emits root discovery, workspace commands, workspace-local typed settings, supported plugins, selected Ultracite presets, exact guarded versions, and receipt-owned policy migrations as one desired-state contract. Adoption preserves project-owned variants.
Update preview
hi update exposes a bounded lint preview in its existing operation result.
Human output shows affected-owner counts and a capped diagnostic sample. JSON
output exposes deterministic counts, truncation state, and normalized samples.
Findings warn. Operational failures prevent reconciliation.
Declared Dependency Graph
Lint asset catalog
-> scaffold compiler
-> desired scaffold state and receipts
-> update candidate preview
-> generated repository config and scripts
Managed edited-file runner
-> normalized lint result
-> Codex runtime response
-> Claude runtime response
-> Cursor runtime response
-> OpenCode runtime response
-> update candidate preview classification
Harness projection adapters
-> provider hook configuration
-> managed edited-file runner mode
Update candidate preview
-> operation result
-> reconciliation publication gateAllowed edges use the named seams above. Provider adapters select runner modes and response capabilities; they do not own lint policy or parse Oxlint output. Presentation renders normalized preview facts; it does not execute processes. The scaffold compiler declares assets; it does not contain provider runtime behavior.
Forbidden edges:
- Provider adapter to raw Oxlint JSON parsing.
- Provider adapter to scaffold lint-policy mutation.
- Operation-result renderer to filesystem or process execution.
- Realtime hook to
ultracite fix --codexor another agent launcher. - Candidate preview to live repository mutation.
- Lint catalog to provider-specific response shapes.
Responsibility Acceptance Criteria
| Criterion | Owner | Observable assertion | Evidence | Due architecture wave |
|---|---|---|---|---|
| RAC-001 | Lint policy and scaffold compiler | Output uses exact tuple, nested discovery, separate format command, workspace-owned typed settings, supported plugins, three global disables, and no six removed exemptions; receipt-owned legacy output migrates and project-owned variants survive. | Scaffold/update tests, config contract, frozen install, Effect/Oxlint probe | A1 |
| RAC-002 | Managed edited-file runner | One accepted edit receives staged formatting, safe file-only fixes, JSON verification, normalized diagnostics, and bounded retry without unrelated writes. | Real-process disposable repository test | A1 |
| RAC-003 | Provider projection | Codex and Claude get continuation context; Cursor and OpenCode get the same facts through supported channels; clean output is silent. | Provider fixtures and live Codex hook run | A2 |
| RAC-004 | Update orchestration | Candidate findings warn; operational failures stop before reconciliation; isolated candidate state is removed on every exit. | Public hi update tests with real process fixtures | A2 |
| RAC-005 | Operator guidance | Runbooks document bounded commands, separate-agent semantics, safe automatic scope, and hook trust without installing upstream AI assets. | Pinned CLI help/source check and wiki sync | A3 |
Architecture Waves
A1: Establish policy and diagnostic boundaries
- Entry dependencies: Approved spec and proven dependency tuple.
- Topology delta: The compiler owns one corrected lint hierarchy; the managed runner owns one normalized lint result.
- Tasks: T1, T2.
- Criteria due: RAC-001, RAC-002.
- Allowed temporary seams: None.
- Continuous convergence checkpoint: Run both public suites, load the combined Ultracite/Effect configuration with the exact tuple, inspect changed ownership, and confirm no provider parser entered the runner core.
A2: Connect consumers
- Entry dependencies: A1 is green.
- Topology delta: Provider responses and update preview consume the normalized result without taking ownership of lint execution.
- Tasks: T3, T4.
- Criteria due: RAC-003, RAC-004.
- Allowed temporary seams: A uniquely marked live Codex fixture exists only during T3 runtime proof.
- Continuous convergence checkpoint: Re-run RAC-001 and RAC-002; create the fixture, validate trusted Codex continuation, remove the fixture and matching session state, then verify provider fixtures, update classification, candidate isolation, and cleanup. A2 cannot close until removal is proven.
A3: Make the workflow operable and close drift
- Entry dependencies: A2 is green.
- Topology delta: Operators receive one accurate command and trust runbook; source and routed wiki artifacts agree.
- Tasks: T5.
- Criteria due: RAC-005.
- Allowed temporary seams: None.
- Continuous convergence checkpoint: Re-run all prior criteria, verify docs against pinned help/source, confirm the migration ledger is empty, run wiki sync and diff checks, and record release classification without publishing.
Migration Ledger
| Temporary seam | Introduced by | Reason | Allowed consumers | Removal task | Expiry | Removal proof |
|---|---|---|---|---|---|---|
| Live Codex fixture repository | T3 | Prove trusted PostToolUse delivery in Codex App. | T3 runtime validation only | T3 | End of A2 | Fixture path and matching temporary session state are absent after evidence capture. |
Session retry files and update-preview directories are runtime artifacts, not migration seams. T2 and T4 prove their same-session or same-run cleanup. Final closure requires no active migration-ledger entry.
Task Dependency Graph
T1 lint hierarchy, policy, exact tuple ──┬──> T3 provider projection ──┐
│ │
T2 edited-file normalized runner ───────┼──> T3 │
└──> T4 adoption preview ────┼──> T5
T1 ─────────────────────────────────────────> T4 │
│
T3 + T4 ─────────────────────────────────────────────────────────────┘Parallel Execution Waves
| Worker wave | Tasks | Start condition | Write boundary |
|---|---|---|---|
| W1 | T1, T2 | Immediately after handoff | T1 owns policy/config/dependencies; T2 owns the hook runner and focused test. |
| W2 | T3, T4 | T1 and T2 complete; A1 green | T3 owns provider paths; T4 owns update/process/presentation paths. |
| W3 | T5 | T3 and T4 complete; A2 green | Documentation, implementation notes, and closeout checks only. |
Tasks in each parallel wave have disjoint owned_paths. A later wave may edit a
path from an earlier wave only after the earlier task and architecture checkpoint
are complete.
Skill Routing
- T1 uses
turborepofor root/workspace dependency and script ownership,effectfor the guarded lint-only patch proof,quality-typesfor supported asset-state modeling,codebase-designfor the compiler seam, andtddfor public scaffold/update RED/GREEN. - T2 and T3 use only
codebase-designandtdd; their portable JavaScript and provider adapter work does not need Effect workflow guidance. - T4 uses
effectbecause update orchestration has typed failures and finalizer cleanup,quality-typesfor its public result variants, pluscodebase-designandtdd. - T5 uses
writing-for-agentsbecause it writes actionable agent/operator guidance. Generic CLI “Primary skills” without a matching task trigger are intentionally not assigned.
Tasks
T1: Align lint hierarchy, reduced policy, and compatible tool tuple
-
depends_on: []
-
location: Lint catalog, scaffold compiler, generated wiki scaffold, root/workspace manifests and configs, lockfile, public config/scaffold tests.
-
owned_paths:
package.jsonbun.lock.oxlintrc.jsonapps/api/package.jsonapps/backoffice/package.jsonapps/cli/package.jsonapps/web/package.jsonapps/wiki/package.jsonapps/wiki/oxlint.config.tspackages/auth/package.jsonpackages/config/package.jsonpackages/contract/package.jsonpackages/db/package.jsonpackages/env/package.jsonpackages/scaffold/package.jsonpackages/ui/package.jsonapps/cli/src/data/catalog/lint.tsapps/cli/src/scaffold/output.tsapps/cli/src/content/wiki.tsapps/cli/src/scaffold/stage.tsapps/cli/src/cli/behavioral-portfolio.test.tspackages/config/public-config-contract.test.tspackages/config/oxlint-1-78-transition.mts.devpunks/specs/lint/assets.json
-
wave_boundary: W1
-
description: Update exact root overrides and workspace declarations to the proven tuple while preserving root-only Effect patch ownership. Make new and receipt-owned generated output use nested discovery, workspace-local lint commands, separate format checks, guarded typed settings, selected Ultracite presets, and supported
effecttsgoregistration. Keep onlyfunc-names,func-style, andsort-keysglobally disabled, retain the ownedno-unused-varswarning, and remove the six accepted exemptions. Preserve unrelated project-owned rules and scripts. Remove the inactive 1.78 transition only if a fresh reference scan proves it unused. -
validation: Public behavior proves exact output, safe receipt-owned migration, project-owned preservation, exact resolution, successful Effect patch, and a combined Ultracite/Effect config load.
-
status: Completed
-
log:
- 2026-09-02: W1 dispatched with RED-first TDD; worker owns T1 production paths while the parent retains shared evidence artifacts.
- 2026-09-02: Exact tuple, reduced policy, generated hierarchy, workspace scripts, receipt migration, and public scaffold/config witnesses completed. Parent recovered the public RED against the pre-fix Oxlint 1.78 catalog slice and completed the A1 regression checkpoint.
-
files edited/created:
package.json,bun.lock,.oxlintrc.json,.devpunks/specs/lint/assets.json, all listed app/package manifests,apps/wiki/oxlint.config.ts,apps/cli/src/data/catalog/lint.ts,apps/cli/src/scaffold/output.ts,apps/cli/src/content/wiki.ts,apps/cli/src/scaffold/stage.ts,apps/cli/src/cli/behavioral-portfolio.test.ts,packages/config/public-config-contract.test.ts; removed inactivepackages/config/oxlint-1-78-transition.mts. -
task_identity_mode: planning-only
-
backlog_item_id: not_applicable
-
backlog_item_url: not_applicable
-
relation_mode: unprojected
-
backlog_sync_skip_reason: Issue 181 is planning context; no provider Task projection was requested.
-
assigned_skills: [
codebase-design,effect,quality-types,tdd,turborepo] -
implementation_skill_guidance:
- skill:
codebase-designapplicable_behavior: Keep policy and compatibility behind the existing desired-state compiler seam; do not spread migration logic across callers. - skill:
effectapplicable_behavior: Verify the live@effect/tsgoguard and preserve the exact lint-only patch contract before changing declarations. - skill:
quality-typesapplicable_behavior: Represent supported and unsupported lint-asset states explicitly so incompatible plugin and version combinations cannot reach generated output. - skill:
tddapplicable_behavior: Capture one public scaffold/update RED before production edits, then advance in vertical RED/GREEN slices. - skill:
turborepoapplicable_behavior: Keep executable lint/format work in package tasks; root scripts only delegate and the lockfile records the exact toolchain.
- skill:
-
tdd_status: recovered
-
tdd_target: A scaffolded multi-workspace repository receives the corrected hierarchy and exact tuple while an adopted project-owned rule remains intact.
-
red_command:
bun test packages/config/public-config-contract.test.ts \ apps/cli/src/cli/behavioral-portfolio.test.ts \ -t "issue 181 lint hierarchy" -
expected_red_failure: Current output resolves the old tuple and lacks the complete hierarchy and reduced-policy migration asserted by the new test.
-
green_command:
set -euo pipefail bun install --frozen-lockfile bun test packages/config/public-config-contract.test.ts \ apps/cli/src/cli/behavioral-portfolio.test.ts \ -t "issue 181 lint hierarchy" bunx --no-install effect-tsgo patch --no-typescript --oxlint bunx --no-install oxlint --version bunx --no-install ultracite --version -
reason_not_testable:
-
red_evidence: Parent reconstructed the pre-fix catalog slice by setting generated Oxlint ownership to the pre-fix catalog after the public witness existed. The issue-181 selector failed with scaffold status 1 where status 0 was expected. The earlier worker RED did not prove this public result and is not counted.
-
green_evidence:
bun install --frozen-lockfilemade no changes; the exact fail-closed issue-181 command passed 3 tests and 26 assertions; hook tests passed 5/5; config tests passed 3/3;apps/clitype-check passed; the Effect patch command passed; version readback reported Oxlint 1.80.0, Oxfmt 0.66.0, and Ultracite 7.10.7; syntax and diff checks passed. -
codebase_design_notes: The catalog declares policy inputs; the compiler owns deterministic output and receipt-aware migration. Tests use public scaffold/update entrypoints, not private encoder exports.
-
review_mode: cli
-
runtime_validation: required
-
runtime_target: A uniquely marked disposable generated Effect workspace with the exact frozen tuple.
-
runtime_evidence: Exact version readback, successful lint-only patch, and a structured
effecttsgo(floating-effect)diagnostic through a combined Ultracite/Effect configuration. -
runtime_cleanup: Create the fixture outside the live repository; remove only its marked path after capturing results and verify the path is absent.
-
architecture_wave: A1
-
behavior_owner: Lint policy and scaffold compiler.
-
integration_surface: Package manifests, Oxlint configs, managed receipts, and root/workspace lint commands.
-
public_seam: Generated and adopted desired scaffold state [RAC-001].
-
topology_delta: Consolidates hierarchy, policy, and guarded version ownership in the compiler that already emits lint output.
-
forbidden_ownership: No lint policy in provider adapters, hooks, docs, or consumer-specific cases. Do not overwrite unreceipted project-owned scripts or rules.
-
temporary_seams: None.
-
responsibility_acceptance_criteria: [RAC-001]
T2: Add safe autofix, normalized diagnostics, and bounded retry
- depends_on: []
- location: Managed edited-file runner and focused real-process tests.
- owned_paths:
apps/cli/src/data/hooks/format-edited-file.mjsapps/cli/src/data/hooks/format-edited-file.test.ts
- wave_boundary: W1
- description: Preserve path confinement, descriptor checks, staged Oxfmt,
and atomic publication. Resolve the owning workspace for each accepted file.
Run safe
oxlint --fixonly on that file, then read-only JSON verification. Normalize clean, findings, and operational-failure results. Extend temporary session state with diagnostic fingerprints and stop repair requests after three unchanged attempts. Add a read-only bounded preview mode for T4. - validation: A disposable repository invokes the hook as a process and proves file-only mutation, normalized fields, owning-workspace cwd, malformed-output classification, race preservation, three-attempt exhaustion, state pruning, and read-only preview behavior.
- status: Completed
- log:
- 2026-09-02: W1 dispatched with RED-first real-process coverage; worker owns the managed runner and focused test while the parent retains shared evidence artifacts.
- 2026-09-02: Added owning-workspace execution, staged safe Oxlint fixes, normalized verification results, bounded retry state, and read-only preview.
- files edited/created:
apps/cli/src/data/hooks/format-edited-file.mjs,apps/cli/src/data/hooks/format-edited-file.test.ts. - task_identity_mode: planning-only
- backlog_item_id: not_applicable
- backlog_item_url: not_applicable
- relation_mode: unprojected
- backlog_sync_skip_reason: Issue 181 is planning context; no provider Task projection was requested.
- assigned_skills: [
codebase-design,tdd] - implementation_skill_guidance:
- skill:
codebase-designapplicable_behavior: Normalize tool output behind one small result seam consumed by runtime response and preview callers. - skill:
tddapplicable_behavior: Start with the real-process RED expecting a rule, location, and message but receiving genericlint_failed.
- skill:
- tdd_status: required
- tdd_target: A non-autofixable finding in one edited file returns its exact Oxlint diagnostic after safe fixes without changing another file.
- red_command:
bun test apps/cli/src/data/hooks/format-edited-file.test.ts \ -t "returns remaining Oxlint diagnostics" - expected_red_failure: The current runner discards Oxlint output and
returns only
lint_failed. - green_command:
bun test apps/cli/src/data/hooks/format-edited-file.test.ts - reason_not_testable:
- red_evidence: Real-process test expected file/rule/location/message for a
non-autofixable finding and failed because the prior hook returned only
generic
lint_failedoutput. - green_evidence:
bun test apps/cli/src/data/hooks/format-edited-file.test.tspassed 5/5 with safe fixes, workspace ownership, normalized diagnostics, clean silence, malformed-output classification, read-only preview, unrelated-file byte identity, and third unchanged-fingerprint exhaustion. Parent rerun passed in 2.68 seconds;node --checkandgit diff --checkpassed. - codebase_design_notes: The hook remains a portable managed asset. Its deep interface is the normalized process result; path safety, processes, parsing, retry storage, and staged publication remain internal.
- review_mode: cli
- runtime_validation: required
- runtime_target: Managed post-edit hook in a uniquely marked disposable multi-workspace repository.
- runtime_evidence: The edited file receives safe fixes, another file is byte-identical, remaining diagnostics are structured, and the third unchanged fingerprint reports exhaustion.
- runtime_cleanup: Remove only the marked fixture and its matching temporary session-state key; verify both are absent.
- architecture_wave: A1
- behavior_owner: Managed edited-file runner.
- integration_surface: Oxfmt, Oxlint, provider runtime responses, and update preview process adapter.
- public_seam:
LintFeedbackResultprocess output [RAC-002]. - topology_delta: Replaces a generic pass/fail summary with one reusable diagnostic boundary.
- forbidden_ownership: No provider configuration, scaffold policy, dangerous fix, suppression, config mutation, unrelated-file mutation, or child-agent launch.
- temporary_seams: None.
- responsibility_acceptance_criteria: [RAC-002]
T3: Deliver normalized feedback through provider-native hooks
- depends_on: [T1, T2]
- location: Hook response branches, projection adapters, sync projection, provider fixtures, and a focused projection test.
- owned_paths:
apps/cli/src/data/hooks/format-edited-file.mjsapps/cli/src/data/scripts/harness-projection/adapters/codex.mjsapps/cli/src/data/scripts/harness-projection/adapters/claude.mjsapps/cli/src/data/scripts/harness-projection/adapters/cursor.mjsapps/cli/src/data/scripts/harness-projection/adapters/opencode.mjsapps/cli/src/data/scripts/sync-subagents.mjsapps/cli/src/data/scripts/harness-projection/test-fixtures/codexapps/cli/src/data/scripts/harness-projection/test-fixtures/claudeapps/cli/src/data/scripts/harness-projection/test-fixtures/cursorapps/cli/src/data/scripts/harness-projection/test-fixtures/opencodeapps/cli/src/data/scripts/harness-projection/lint-feedback.test.ts
- wave_boundary: W2
- description: Translate the normalized result into each provider's
supported output. Codex uses synchronous
PostToolUseblock feedback; Claude gets actionable additional context; Cursor gets a user message; OpenCode logs one structured finding set without duplicate runner invocation. Keep projection mirrors and capability metadata aligned. After automated GREEN, create a uniquely marked Codex App fixture, trust its hook through/hooks, validate same-turn diagnostics and clean follow-up behavior, then remove the fixture and matching session state before A2 can close. - validation: Fixtures prove equivalent diagnostic facts, native envelopes, clean silence, exhaustion behavior, and one invocation per edit. Live Codex evidence proves an unfixable finding reaches the active turn after trust and that cleanup follows create then validate then remove ordering.
- status: Automated complete; manual Codex App gate outstanding
- log: Provider fixtures and the injected process-capture witness prove
actionable response envelopes, clean follow-up silence, and bounded
exhaustion. Codex App trust and same-turn
/hooksdelivery were not observed; no disposable Codex App fixture was created. Manual validation remains required before A2 is closed. - files edited/created:
apps/cli/src/data/hooks/format-edited-file.mjs, provider projection adapters and fixtures,apps/cli/src/data/scripts/harness-projection/lint-feedback.test.ts,apps/cli/src/data/hooks/format-edited-file.test.ts. - task_identity_mode: planning-only
- backlog_item_id: not_applicable
- backlog_item_url: not_applicable
- relation_mode: unprojected
- backlog_sync_skip_reason: Issue 181 is planning context; no provider Task projection was requested.
- assigned_skills: [
codebase-design,tdd] - implementation_skill_guidance:
- skill:
codebase-designapplicable_behavior: Keep response envelopes thin over the normalized result and make provider capabilities explicit. - skill:
tddapplicable_behavior: Capture Codex's public response RED first, then add one provider adapter per RED/GREEN slice.
- skill:
- tdd_status: required
- tdd_target: Codex
PostToolUsereturns one actionabledecision: "block"response with file, rule, location, and message. - red_command:
bun test \ apps/cli/src/data/scripts/harness-projection/lint-feedback.test.ts \ -t "Codex continues with remaining lint diagnostics" - expected_red_failure: Codex currently emits a generic
systemMessageand lacksdecision: "block"plus diagnosticadditionalContext. - green_command:
set -euo pipefail bun test apps/cli/src/data/scripts/harness-projection/lint-feedback.test.ts bun test apps/cli/src/data/hooks/format-edited-file.test.ts - reason_not_testable:
- red_evidence:
- green_evidence:
- codebase_design_notes: The portable hook owns runtime response adapters; projection adapters own hook configuration and mode selection. Both consume the same capability labels.
- review_mode: cli
- runtime_validation: required
- runtime_target: A uniquely marked disposable repository opened in Codex
App with generated
SessionStartandPostToolUsehooks trusted via/hooks. - runtime_evidence: A non-autofixable finding reaches the same Codex turn with actionable fields; a compliant follow-up becomes silent; trust state and hook-definition identity are recorded.
- runtime_cleanup: Create the fixture, validate the hook, remove only the marked fixture and matching temporary state, then verify both paths are absent.
- architecture_wave: A2
- behavior_owner: Provider runtime response and projection adapters.
- integration_surface: Codex, Claude, Cursor, and OpenCode edit hooks.
- public_seam: Provider-native response from
LintFeedbackResult[RAC-003]. - topology_delta: Replaces generic warnings with actionable, capability-aware current-session feedback.
- forbidden_ownership: No raw Oxlint parsing in projection adapters, false continuation claims, upstream generated hook imports, or nested agents.
- temporary_seams: Live Codex fixture until runtime evidence and removal proof are captured in T3.
- responsibility_acceptance_criteria: [RAC-003]
T4: Add candidate lint preview before update publication
- depends_on: [T1, T2]
- location: Update orchestration, process capture, operation-result facts and presentation, and public behavioral tests.
- owned_paths:
apps/cli/src/update/run.tsapps/cli/src/runtime/scripts.tsapps/cli/src/presentation/operation-result.tsapps/cli/src/presentation/operation-result/fields.tsapps/cli/src/presentation/operation-result/lint-preview-facts.tsapps/cli/src/cli/behavioral-portfolio.test.ts
- wave_boundary: W2
- description: Insert lint preview after desired state materialization and
before reconciliation touches the live repository. Create the candidate with
mkdtempbelow the approved OS temporary parent, write and read back a unique ownership marker, canonicalize both roots, and reject any ancestor/descendant relationship with the live repository. Copy affected lint owners without following links; before and after dependency materialization, require every candidate symlink's canonical target to remain inside the candidate root. Spawn without a shell from a fixed allowlist: the current Bun executable withinstall --frozen-lockfile --ignore-scripts, candidate-localeffect-tsgo --no-typescript --oxlintonly when selected, and candidate-local Oxlint with the fixed read-only JSON arguments. Fresh candidate dependencies must not reuse a live writable dependency root. Preserve local plugin/config visibility inside the copy. Fingerprint live manifests, lockfiles, dependency roots, and affected source before preview and prove them unchanged afterward. Return deterministic counts, truncation, and a bounded sample. Findings warn and may proceed; dependency, spawn, config-load, malformed-output, or cleanup-proof failures prevent reconciliation. Always remove the candidate. - validation: Public
hi updatetests prove warning continuation, no live publication on operational failure, project-owned preservation, candidate dependency visibility, process allowlisting, symlink rejection, no live dependency mutation, bounded output, and cleanup on success, findings, failure, interruption, and exception. - status: Completed
- log: Candidate preview runs frozen dependency installation and read-only Oxlint JSON in an isolated marked directory. Findings warn and continue; dependency/config/process/malformed-output/cleanup failures prevent reconciliation. Public and runtime tests prove cleanup, bounded findings, symlink rejection, dependency failure, and unchanged live state.
- files edited/created:
apps/cli/src/runtime/scripts.ts,apps/cli/src/runtime/scripts.test.ts,apps/cli/src/update/run.ts, operation-result facts/presentation,apps/cli/src/cli/behavioral-portfolio.test.ts. - task_identity_mode: planning-only
- backlog_item_id: not_applicable
- backlog_item_url: not_applicable
- relation_mode: unprojected
- backlog_sync_skip_reason: Issue 181 is planning context; no provider Task projection was requested.
- assigned_skills: [
codebase-design,effect,quality-types,tdd] - implementation_skill_guidance:
- skill:
codebase-designapplicable_behavior: Keep candidate execution behind one injected port; update orchestration owns classification and publication only. - skill:
effectapplicable_behavior: Model preview failures as typed failures, preserve finalizer cleanup on interruption, and never convert failure into success. - skill:
quality-typesapplicable_behavior: Preserve findings and operational failures as distinct variants through process, application, and JSON presentation. - skill:
tddapplicable_behavior: Begin with the public update RED that publishes an invalid candidate, then add warning and cleanup slices vertically.
- skill:
- tdd_status: required
- tdd_target:
hi update --writestops before live reconciliation when the candidate config cannot load, while valid existing findings warn and proceed. - red_command:
bun test apps/cli/src/cli/behavioral-portfolio.test.ts \ -t "lint adoption preview" - expected_red_failure: The current update path has no candidate lint preview and reaches reconciliation without the asserted warning or failure.
- green_command:
bun test apps/cli/src/cli/behavioral-portfolio.test.ts \ -t "lint adoption preview" - reason_not_testable:
- red_evidence:
- green_evidence:
- codebase_design_notes: The process adapter captures the normalized result. Update orchestration maps it to the operation result and gate. Presentation renders facts but does not execute or parse tools.
- review_mode: cli
- runtime_validation: required
- runtime_target:
hi update --writeagainst uniquely marked disposable repositories covering findings and operational failure. - runtime_evidence: Findings return a warning and continue; an invalid config returns a handled failure before live mutation; process and cleanup facts name only the isolated candidate path.
- runtime_cleanup: Every preview uses a unique
punks-update-*descendant with an ownership marker. Finalizers remove only that candidate and verify its absence before returning any outcome. - architecture_wave: A2
- behavior_owner: Update adoption-preview application.
- integration_surface: Desired-state staging, candidate dependencies, managed preview mode, operation result, and reconciliation gate.
- public_seam:
hi updatewarnings, preview facts, and handled failures [RAC-004]. - topology_delta: Adds an isolated read-only candidate validation boundary before live publication.
- forbidden_ownership: No live config, manifest, dependency, lockfile, source mutation, report submission, or lint parsing in presentation.
- temporary_seams: None.
- responsibility_acceptance_criteria: [RAC-004]
T5: Document bounded Ultracite workflows and close acceptance
- depends_on: [T1, T2, T3, T4]
- location: CLI overview, scaffolding runbook, implementation notes, routed wiki projection, and final validation evidence.
- owned_paths:
docs/README.mddocs/runbooks/hi-cli-scaffolding.mdapps/wiki/specs/cli/issue-181-lint-feedback-adoption/IMPLEMENTATION-NOTES.mdapps/wiki/content/docs/project/runbooks/hi-cli-scaffolding.mdapps/wiki/content/docs/project/specs/cli/issue-181-lint-feedback-adoptionapps/wiki/index.mdapps/wiki/log.md
- wave_boundary: W3
- description: Document automatic edited-file scope, provider differences,
manual Codex hook trust, adoption preview, and the four explicit Ultracite
commands. State that
fix --codexlaunches another process and is never the realtime hook. Validate target syntax against installed 7.10.7 help and pinned source. Keep rules, skill, and generated hooks out of default context packs. Record implementation and runtime evidence, close every architecture criterion, synchronize wiki output, and classify release impact without publishing. - validation: Docs match pinned help/source; source and routed wiki agree; every task has evidence; all RACs are green; the live fixture ledger entry is closed; formatting, content, sync, diff, and release-classification checks run.
- status: Completed
- log: Runbooks and routed wiki source document bounded
check,doctor,fix, andfix --codex, native provider feedback, manual Codex hook trust, and context-pack exclusions. Validation includes pinned CLI help/source checks, wiki content/sync checks, formatting, and release classification without publication. - files edited/created:
docs/README.md,docs/runbooks/hi-cli-scaffolding.md,apps/wiki/content/docs/project/runbooks/hi-cli-scaffolding.md,IMPLEMENTATION-NOTES.md. - task_identity_mode: planning-only
- backlog_item_id: not_applicable
- backlog_item_url: not_applicable
- relation_mode: unprojected
- backlog_sync_skip_reason: Issue 181 is planning context; no provider Task projection was requested.
- assigned_skills: [
writing-for-agents] - implementation_skill_guidance:
- skill:
writing-for-agentsapplicable_behavior: Write short trigger-to-action instructions; keep command and trust facts authoritative in one runbook and link elsewhere.
- skill:
- tdd_status: not_applicable
- tdd_target: Documentation and evidence closeout; T1 through T4 own runtime behavior tests.
- red_command:
- expected_red_failure:
- green_command:
set -euo pipefail bunx --no-install ultracite --version bunx --no-install ultracite check --help | \ rg 'Usage: ultracite check \[options\] \[files\.\.\.\]' bunx --no-install ultracite fix --codex --help | \ rg 'Usage: ultracite fix \[options\] \[files\.\.\.\]' bunx --no-install ultracite fix --codex --help | rg -- '--codex' bunx --no-install ultracite doctor --help bunx oxfmt --check docs/README.md docs/runbooks/hi-cli-scaffolding.md \ apps/wiki/specs/cli/issue-181-lint-feedback-adoption node apps/wiki/scripts/sync-content.mjs --check bun run --cwd apps/wiki check:content git diff --check bun run release:classify -- --base main --head HEAD - reason_not_testable: Documentation-only closeout; behavior is covered by T1 through T4.
- red_evidence:
- green_evidence:
- codebase_design_notes: Documentation consumes the implemented seams and remains outside runtime ownership.
- review_mode: cli
- runtime_validation: not_required
- runtime_target: not_applicable
- runtime_evidence: not_applicable
- runtime_cleanup: not_applicable
- architecture_wave: A3
- behavior_owner: Operator guidance and implementation evidence.
- integration_surface: CLI docs, wiki source/projection, and release classification.
- public_seam: Bounded Ultracite and hook-trust runbook [RAC-005].
- topology_delta: Makes automatic and deliberate workflows discoverable without adding context-pack assets.
- forbidden_ownership: No new lint policy, provider behavior, backlog mutation, release publication, or unverified capability claim in docs.
- temporary_seams: Close the T3 live-fixture ledger entry; add none.
- responsibility_acceptance_criteria: [RAC-005]
Testing Strategy
- T1 and T2 begin with separate public RED cases and advance in vertical slices.
- A1 closes only after the exact tuple loads both Ultracite and Effect configuration and the hook proves safe file-only behavior.
- T3 uses Codex as the tracer bullet, then adds Claude, Cursor, and OpenCode one response at a time over the same normalized facts.
- T4 tests through public
hi updatewith injected process capture. It does not mock the classification boundary that decides publication. - Manual Codex App trust and same-turn
/hooksobservation remain required because projection fixtures cannot prove desktop hook delivery or trust behavior. No disposable fixture is created by automated delivery. - Each architecture checkpoint reruns all criteria due in earlier waves.
- Final validation moves from focused tests to CLI tests, types, lint/format, wiki sync, and diff checks. Unrelated failures are reported separately.
Validation Gates
Gate G1: T1
- Public scaffold/update hierarchy tests are green.
- The exact tuple appears in manifests, overrides, catalog, and lockfile.
- Frozen install and the lint-only Effect patch succeed.
- Combined Ultracite and Effect config emits a known type-aware diagnostic.
Gate G2: T2 and A1 checkpoint
- Real-process hook test is green.
- Safe fixes touch only accepted files.
- Remaining JSON diagnostics normalize correctly.
- Retry exhaustion occurs on the third unchanged fingerprint.
- Preview mode is read-only.
- RAC-001 and RAC-002 are green together.
Gate G3: T3 and T4
- All provider response fixtures are green.
- OpenCode invokes the runner once per edit.
hi updatewarns on findings and blocks operational failures before reconciliation.- Candidate dependencies and local plugins resolve only inside the disposable copy.
- Only allowlisted candidate processes execute.
- Live repository files and dependency state remain byte-identical.
- Candidate cleanup is proven for every exit path.
Gate G4: A2 runtime checkpoint
- Create one uniquely marked disposable Codex repository.
- Trust its generated hook through
/hooks. - Validate a non-autofixable finding reaches the same turn with actionable context and a repaired follow-up edit becomes silent.
- Remove the fixture and its matching temporary session state.
- Verify both paths are absent and RAC-001 through RAC-004 remain green.
Gate G5: Final closeout
set -euo pipefail
bun test apps/cli/src/data/hooks/format-edited-file.test.ts
bun test apps/cli/src/data/scripts/harness-projection/lint-feedback.test.ts
bun test packages/config/public-config-contract.test.ts \
apps/cli/src/cli/behavioral-portfolio.test.ts
bun run --cwd apps/cli check-types
bun run --cwd apps/cli check
node apps/wiki/scripts/sync-content.mjs --check
bun run --cwd apps/wiki check:content
git diff --check
bun run release:classify -- --base main --head HEADThis gate records local tests, live provider evidence, branch/PR state, and release/publication state separately. It makes no external claim without fresh readback.
Risks and Mitigations
| Risk | Mitigation |
|---|---|
| Automatic project-wide fix creates an uncontrolled diff. | Automatic execution uses exact edited paths; Ultracite commands require bounded targets. |
| Safe fixes race with a second writer. | Preserve descriptor fingerprints, staged bytes, and atomic publication checks. |
| Root execution changes typed lint behavior. | Resolve owning workspace and test cwd-sensitive config with a known typed finding. |
| Loose upgrade reaches unsupported Oxlint 1.81.0. | Pin exact root overrides and require frozen install plus Effect runtime proof. |
| Migration removes a project-owned exception. | Mutate only new, receipt-owned, or exact recognized legacy output. |
| Provider feedback loops forever. | Stop repair requests after three unchanged fingerprints. |
| Codex fixtures pass while Codex App ignores the hook. | Require live desktop trust and continuation evidence before A2 closes. |
| Candidate preview mutates live state or runs lifecycle code. | Use a marked isolated copy, reject live symlinks, disable lifecycle scripts, allowlist processes, and prove cleanup. |
| Large findings flood context. | Return counts and a deterministic capped sample; realtime context contains only edited-file findings. |
| Docs become policy authority. | Keep exact policy in compiler tests; docs describe commands and boundaries. |
Backlog Sync
Skipped. This is a planning-only handoff linked to GitHub issue 181. The user did not request provider Task creation or mutation, so T1 through T5 are the only execution identities and every dependency resolves inside this plan.
Unresolved Questions
None. Historical bulk cleanup and native Cursor/OpenCode continuation are explicitly parked in the approved spec and do not block delivery.
Implementation Status Corrections
The implementation status below is authoritative for delivery review:
- T1, T2, and T4 are met by focused automated evidence. T4 candidate preview evidence uses injected process capture; it does not claim a real dependency installation or live candidate process.
- T3 provider projection is automated-pass with its manual A2 gate outstanding.
Provider fixtures and the injected process-capture witness pass, but Codex
App hook trust and same-turn
/hooksdelivery were not observed. - No disposable Codex App fixture or matching session state was created. The manual gate must not be recorded as completed until a trusted App observation exists.