Issue 224: Lint Scope and Hook Boundaries
Issue 224: Lint Scope and Hook Boundaries
The user subsequently accepted the proposals in this report and the follow-up policy report. The managed lint grill now records accepted decisions and delegated defaults. The observations and candidate/open-decision wording below retain the research-time history; they do not reopen choices settled in the grill. Compiled grill confirmation is pending.
Status and accepted bounds
Brainstorming evidence, not an accepted implementation specification. The user
requested a new PR stacked on #223, coverage of #224, exclusion of destination
wiki paths from linting and Lefthook, and lint/hook package discovery bounded to
one child under apps and packages. Candidate solutions below remain pending
acceptance. No production behavior changes in this research commit.
Accepted during the brainstorm: the same scope must apply to every managed lint
entry point, including edited-file feedback, Lefthook, and generated lint commands.
Explicitly declared workspace packages may also qualify beyond the conventional
apps/* and packages/* layout; the rule is not a strict conventional-path-only
allowlist.
Ordinary tests inside eligible applications/packages remain linted. The excluded
content is embedded example repositories, fixtures, and similar nested projects.
Research baseline: #223 head ecf2d68eb69f0bd2977baf13ced39f230bdccdea.
The issue reports CLI 5.1.1 behavior in another repository; that consumer has not
been reproduced here. The local release-preparation commit above #223 is not part
of this stack.
The operator is an agent running hi scaffold, hi update, lint, edited-file
feedback, and commits in a destination repository. apps/cli owns discovery,
selection, generation, reconciliation, and the shipped runners. Shared scaffold
contracts may be affected if the accepted design changes their shape. API and
backoffice changes have no established need. CI is an execution consumer of the
selected commands; rewriting destination workflows is an unresolved scope choice.
The private wiki owns this research; docs remains implemented-operation authority.
Evidence and uncertainty
| Observation | Primary evidence | Consequence / limit |
|---|---|---|
| Manifest discovery is recursive. | apps/cli/src/integrations/repository-detector.ts:172–197,321–365 unions recursive, declared, conventional, and top-level discoveries. | Workspace declarations do not currently bound the returned manifest set. |
| Some fixture names are ignored, but no general depth boundary exists. | repository-detector.ts:19–46 excludes test-fixtures, examples, and docs, but not ordinary test or fixtures names. | A name blacklist does not implement the requested package-root allowlist. |
| Wiki exclusion currently belongs to technology detection. | repository-detector.ts:71,159–170,554–582 recognizes wiki, app/wiki, and apps/wiki; only pack-detection manifests exclude them. | It does not establish a lint or hook exclusion. |
| Lint planning admits almost all discovered manifests. | apps/cli/src/scaffold/output.ts:1628–1643 conditionally removes only the repository-root manifest. | Nested projects can receive managed lint configuration. |
| Frontend naming can broaden workspace packs. | apps/cli/src/features/context-planning/compiler.ts:76–114,155–183 combines frontend heuristics, selected frontend packs, and direct dependency checks. output.ts:2015–2018 selects lint assets from compiled workspace packs. | frontend-shared can inherit selected Next/TanStack packs without those dependencies. The reported backend contamination is still unproven. |
| Wiki has two lint producers. | output.ts:2019–2044 retains wiki anti-slop assets and uses makeWikiOxlintConfig; apps/cli/src/content/wiki.ts:645 independently emits oxlint.config.ts. | Filtering manifests alone cannot remove wiki lint setup. |
| Parent configuration lacks the requested exclusions. | output.ts:874–878 combines .devpunks/** with existing and asset ignores. | Omitting a child config does not stop a parent lint command from visiting its files. |
| Existing scripts can select another configuration. | output.ts:2111–2114 merges defaults into existing scripts; #224 reports legacy JSON scripts/CI versus generated TypeScript autodiscovery. | The report's 41,955 diagnostics and exact consumer mismatch are issue evidence, not reproduced measurements. |
| Lefthook routes through a generated runner. | apps/cli/src/features/commit-gate/index.ts:58–59; apps/cli/src/data/scripts/commit-gate-runner.mjs:38–64,108–111,162–170. | All staged paths, including deletion and rename endpoints, participate in coverage; deleting contracts alone can cause uncovered-path failures. |
| Custom commands can exceed generated scope. | apps/cli/src/features/commit-gate/quality.ts:147–154; commit-gate-runner.mjs:95–99,116–119,141–148. | Owner commands execute verbatim; explicit repository commands supersede local checks and can scan excluded directories. |
| Agent edit feedback has independent discovery. | apps/cli/src/data/hooks/format-edited-file.mjs:39,113–117,183–201 skips a few generated directories, protects managed files, and finds the nearest manifest at arbitrary depth. | A Lefthook-only fix leaves another lint path into wiki and nested projects. |
| Retirement already has ownership safeguards. | apps/cli/src/update/run.ts:3716–3730,2879–2902 finds obsolete managed files and applies safe reconciliation. | Newly excluded paths must not cause deletion of unowned or user-modified configuration. |
Two readonly lanes covered discovery/technology selection and generation/runtime hooks respectively. The coordinator examined issue/PR evidence, established the stack base, consulted existing lint learnings and the scaffolding runbook, and consolidated this report. No lane ran a consumer reproduction or modified code.
Candidate coherent system
One lint-specific eligibility decision should precede lint asset selection. Keep
general repository discovery available for other consumers unless evidence shows
that its wider topology is itself unwanted. Existing nested-workspace detector
tests intentionally cover more than apps/* and packages/*.
destination manifests + source evidence + existing ownership
-> lint eligibility: package root, exclusions, reason
-> per-workspace technology evidence and lint assets
-> explicit lint config and command routing
-> scripts / Lefthook / edited-file feedback / update validation
-> findings and exclusions reported against the same scopeThis is a proposed relationship, not a new persisted schema. Reuse existing selection/contract artifacts where possible; a new independent registry would need justification.
User-proposed settings authority
The user subsequently proposed that the operating agent compile the actual
software-facing scopes while running the CLI and persist the list in
.devpunks/settings.json. The user accepted this architecture in the follow-up
discussion, including preserving incompatible custom commands and reporting their
routing conflict for deliberate migration. Exact field names remain proposed.
The current ProjectSettingsDocument contains commit-gate policy and repository
quality commands but no software/lint scope list
(apps/cli/src/features/project-settings/model.ts:20–51).
Recommended interpretation: discovery proposes candidate owners; the agent classifies real software versus embedded example/fixture projects; settings stores the explicit selection; the CLI validates it and generates every managed lint entry point from it. Keep inferred technologies derived per scope rather than storing a second copy of framework detection in settings.
Illustrative settings shape only; field names are not accepted API:
{
"lint": {
"scopes": ["apps/web", "app/backend/core", "packages/ui"],
"exclude": ["apps/web/test/fixtures/**"]
}
}This would make shallow conventional paths and declared workspaces inputs to initial scope selection rather than permanent competing runtime authorities. Saved paths should be repository-relative and validated; a moved/missing scope should yield actionable drift, not silently trigger recursive fallback. Adding a new fixture manifest must not silently grow the saved application list. Ordinary tests remain covered. Wiki stays excluded; nested fixture/example exclusions are still needed underneath selected owners.
Open consequences: who updates the list when real apps are added, migration for
settings without the field, whether root . is permitted for standalone apps,
and how exclusions are identified and persisted. An agent may author proposed
settings, but hook correctness cannot depend on an agent running at commit time.
Settings schema/service/initialization/update paths become additional
implementation owners, and the new spec/plan must cover persistence, drift, and
deterministic consumption as well as discovery depth.
The subsequent consumer policy investigation reproduces the reported entrypoint disagreement and proposes config-authority migration. Those additional migration details remain candidates.
| Candidate | Evidence and expected result | Unresolved tradeoff / document change |
|---|---|---|
Admit direct apps/<name>/package.json and packages/<name>/package.json, plus explicitly declared workspace packages, with wiki exclusion. | Recursive discovery and permissive lint targeting explain overreach. A positive eligibility rule gives the agent an inspectable boundary; the user accepted declared nonstandard workspaces. | Root single-package repositories and broad workspace globs need explicit treatment. New issue spec/plan must show examples, including app/backend/core. |
| Separate package eligibility from file traversal. | Parent lint, staged-path coverage, and edit hooks can still visit descendants. Route only eligible files and skip excluded-only commits successfully. Ordinary tests remain eligible, as accepted by the user. | Excluding nested example/fixture projects may still require cheap boundary detection; do not recursively analyze them as applications. Broad workspace glob precedence remains open. |
| Select lint assets from evidence local to the owning workspace. | Compiler frontend propagation can import unrelated framework packs. Retain evidence/reasons so an agent can explain each selected asset. | Hoisted shared tooling and deliberate overrides need a defined inheritance rule. Confirm the backend report with a focused public-interface reproduction. Reconcile context-compilation design. |
| Make generated entry points select the same configuration explicitly. | Script preservation, autodiscovery, and custom repository authority can disagree. | Existing custom commands and policy must be preserved or deliberately migrated; no safe automatic rewrite of arbitrary shell can be assumed. Decide whether incompatible commands block adoption or produce an explicit unresolved handoff. |
| Retire obsolete managed lint assets through existing update reconciliation. | Ownership-aware removal already exists. Repeated updates should converge without recreating excluded wiki/fixture assets. | Preserve modified/unowned configs and report unresolved ownership. Reconcile lint-baseline and update behavior docs. |
Intake is manifest/source evidence, not repository-wide technology union alone. State is the selected owner/config/command and its provenance. Control is the existing scaffold/update and quality command contract. Feedback must distinguish an excluded path, an eligible owner with findings, and a routing/configuration failure. Recovery uses ownership-aware update reconciliation; a narrowed scope must not silently erase custom policy. Handoff should name remaining command or ownership conflicts and the smallest validation that can resolve them.
Open decisions
- Accepted: explicitly declared nonstandard workspaces may qualify, including
app/backend/coreif declared. How broad workspace globs interact with excluded nested fixture projects remains unresolved. - Accepted: ordinary tests remain linted; embedded example repositories,
fixtures, and similar projects are excluded. A blanket
test/testsdirectory exclusion would contradict this decision. - Accepted: the same exclusions cover edited-file feedback, Lefthook, and all other managed lint entry points.
- Is the root an orchestrator in monorepos, while a root-only application remains supported? Root policy inheritance is not evidence that the root is another app.
- Does “wiki paths” mean the three established wiki roots and their descendants,
or every directory segment named
wiki? - How should existing custom root/owner commands be handled when their scanning scope or selected config contradicts the new generated policy?
The first three questions were presented to the user during research. The user accepted shared scope for every managed lint entry point, eligibility for explicitly declared workspace packages, and continued linting of ordinary tests while excluding embedded example/fixture projects. Other branches are explicit unknowns, not accepted defaults. A draft PR makes the evidence reviewable; it does not resolve #224.
Reconciliation required after acceptance
- Add the issue-specific accepted spec and execution plan; scope implementation workers by discovery/selection, generated runtime, ownership migration, and documentation only after shared contracts and dependencies are settled.
docs/runbooks/hi-cli-scaffolding.md:259explicitly describes wiki lint configs; its lint-feedback, workspace-validation, and commit-gate sections must reflect the accepted exclusions and command authority.docs/README.mdcurrently describes wiki exclusion from pack detection, not linting. Keep current-behavior prose unchanged until implementation proves the replacement; this PR only links the research.- Reconcile affected authority in the context-compilation, scaffold lint baseline, managed format hook, Lefthook commit gate, portable commit gate, and lint-feedback specs/plans. Mark superseded contracts explicitly rather than rewriting historic proof as though the new behavior already existed.
- Existing relevant artifacts are under
apps/wiki/content/docs/project/specs/cli/:IP-317-compile-context-once-and-project-it-truthfully,scaffold-lint-config-baseline,scaffold-managed-format-hook,lefthook-commit-gate,issue-204-portable-commit-gates, andissue-181-lint-feedback-adoption.
Proposed behavioral proof
Use the public scaffold/materialization seam to cover an eligible frontend, an
eligible backend, shared code, wiki, and nested fixture manifests. Assert exact
owners and framework assets, not only snapshots of generated text. Existing seams
include scaffold/output.test.ts, output-root-materialization.test.ts, detector
and compiler tests, features/commit-gate/quality.test.ts, and generated runner
and edited-file hook tests.
Run real representative commands to prove excluded files are never passed to managed tooling; cover excluded-only, mixed, delete, and cross-boundary rename staging. Prove script/hook config agreement and ownership-safe update convergence with unmodified managed, modified managed, and unowned old configuration. This is a proposed verification set, not evidence that implementation passes it.
Handoff work log and rule evaluation
HI-WIKI-001: pass by using the existing project research route and registering the page in its owning metadata; authored content check passed.HI-WIKI-003: pass; frontmatter, source evidence, authored content check, and public wiki contract (3 tests) passed. This is authored research, not raw source ingestion, so processed-source bookkeeping is not applicable.HI-DOCS-001: pass; research is private wiki material anddocs/README.mdonly indexes it. No claim of changed implemented behavior.HI-CLI-001,HI-CLI-003,HI-CLI-004: pass for readonly boundary inspection; implementation and generated-asset validation are not applicable to this diff.- Shared contracts, reusable skills, infrastructure, local URLs, auth, and UI runtime rules are not applicable to the authored research diff.
- Baseline
bun run --cwd apps/wiki check:content: passed before authoring. - Authored content check and public wiki contract: passed after installing the
frozen dependencies with lifecycle scripts disabled. The first test attempt
could not load
vitest/configbefore dependencies were installed. - No changelog is changed; this research selects no product release under the repository's changed-changelog rule.
- Commit attempt blocked by the existing pre-commit gate: wiki lint reports 456 errors in unchanged source and bundled plugin files. The documentation-only diff does not fix or introduce those errors.
- Existing pre-push gate also fails before publication: it calls the Candidate
Evidence CLI with unsupported
--base/--headarguments; the observed error isInvalid Candidate Evidence argument: --base. - The user explicitly authorized one-time pre-commit/pre-push bypass for this three-file documentation-only draft. Use per-command overrides; retain the repository hook configuration and both failures as unresolved evidence.