Skip to content

Replace docstring-coverage with a zero-tolerance TypeDoc gate#62

Open
leynos wants to merge 5 commits into
mainfrom
typedoc-rollout
Open

Replace docstring-coverage with a zero-tolerance TypeDoc gate#62
leynos wants to merge 5 commits into
mainfrom
typedoc-rollout

Conversation

@leynos

@leynos leynos commented Jul 17, 2026

Copy link
Copy Markdown
Owner

Summary

This branch replaces the threshold-based, allow-listed
docstring-coverage gate with a zero-tolerance TypeDoc documentation
gate, and gives the repository a CI workflow that runs the full
commit-gate suite. TypeDoc's notDocumented validation now runs over
the whole src/workflows/df12-build-odw module tree with
entryPointStrategy: "expand", emit: "none", and warnings treated as
errors: every module must open with a /** … @module */ block and every
exported declaration must carry a JSDoc comment. The gate reports the
qualified name of each undocumented declaration, writes no documentation
artefacts, and fails on a single omission — replacing the previous 80%
threshold over a three-module allow-list.

The branch lands in four commits after rebasing onto main: the first documents every exported declaration in the module tree (945 TypeDoc warnings' worth) while the old gate still runs; the second swaps the gate, converts @file headers to TypeDoc's @module form (preserving the file-level documentation rule rather than retiring it), and deletes the custom AST-counting script with its DOCSTRING_MODULES/DOCSTRING_MIN allow-list; the third adds the CI workflow, imported from leynos/agent-template-typescript and extended to this repository's aggregate; the fourth preserves main's advisory residual-risk recovery contract and documents the declarations introduced upstream.

Review walkthrough

  • Start with typedoc.json
    for the gate's configuration: the documentation surface, the
    exclusions (ambient odw-globals.d.ts, the verbatim meta.js
    banner), the required-kind list including "Module", and
    treatValidationWarningsAsErrors.
  • Then the Makefile
    and package.json:
    docs-check (wrapping bun run docs:check) replaces
    docstring-coverage inside make all.
  • .github/workflows/ci.yml
    runs make all then make verify-modules-strict with pinned installs
    of markdownlint-cli2, nixie-cli, and Dafny 4.10.0, honouring the
    Makefile's requirement that CI runs the strict Dafny proof rather than
    the lenient skip.
  • The documentation pass is best sampled via
    src/workflows/df12-build-odw/config.ts
    (the largest surface: every run-configuration knob, default, and
    clamp) and
    src/workflows/df12-build-odw/recovery-decision.ts
    (the decision-table docs mirror the Dafny-verified twin under
    verify/).
  • src/workflows/df12-build-odw/schemas.ts
    shows the *_SCHEMA treatment: documented /** … @internal */ blocks
    so TypeDoc does not recurse into the JSON Schema literals (module
    tests pin deep literal paths, so the constants keep their inferred
    types); their description fields remain the per-field documentation.
  • Finish with AGENTS.md,
    docs/developers-guide.md,
    and docs/architecture.md
    for the updated conventions and verification contract.

Validation

  • make all (check-fmt, lint, typecheck, markdownlint, nixie,
    docs-check, module and artefact test suites, workflow-freshness,
    verify-modules with Dafny on PATH): exit 0 on each commit, run
    sequentially via the scrutineer gate-runner. Module tests: 360
    pass, 0 fail; artefact tests: 124/124; operator-script tests: 21/21;
    Dafny: 4 verified, 0 errors.
  • Mutation check: deleting the JSDoc block from an exported function
    makes docs:check exit non-zero with
    exec.shellQuote (CallSignature) … does not have any documentation;
    restoring it returns the gate to green.
  • A clean docs:check run emits no files and no output; the regenerated
    workflows/df12-build-odw.js artefact is committed alongside the
    source (workflow-freshness green).

Notes

  • Three deliberate non-comment touches were needed so TypeDoc can attach
    comments to anonymous object types: three single-line return-type
    literals in
    src/workflows/df12-build-odw/run-task.ts
    are reflowed to multiline, and two return { … } shorthands are
    expanded, with shapes unchanged.
  • The CI workflow is this repository's first full-gate workflow; the
    pre-existing spelling.yml remains untouched even though make all
    also covers spelling.

References

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @leynos, your pull request is larger than the review limit of 150000 diff characters

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Review Change Stack

Summary

  • Replaced the allow-listed, threshold-based docstring gate with a zero-tolerance TypeDoc check covering src/workflows/df12-build-odw.
  • Added strict TypeDoc configuration, pinned CI tooling, and docs-check to make all; removed the custom coverage script and tests.
  • Documented exported declarations and module contracts, including ADR 002 and JSON Schema internals.
  • Preserved and clarified recovery, remediation, roadmap, host-probe, and workflow artefact contracts.
  • Added validation for malformed roadmap ranges, remediation titles/source aggregation, CodeScene probe failures, and FIFO write probes.
  • Updated generated workflow output and repository documentation.

Validation

  • make all
  • Module, artefact, operator-script, and Dafny checks
  • Strict Dafny verification in CI
  • Mutation test confirming undocumented declarations fail the TypeDoc gate

Walkthrough

Adds a strict TypeDoc documentation gate, replaces the former coverage check, introduces CI workflow automation, and expands ODW module documentation and selected exported contracts.

Changes

Documentation and CI validation

Layer / File(s) Summary
CI workflow execution
.github/workflows/ci.yml
Adds pull-request and main push validation with pinned tool installation, make all, and strict module verification.
Documentation gate configuration
Makefile, package.json, typedoc.json, AGENTS.md, docs/*
Replaces docstring coverage with zero-tolerance TypeDoc validation and updates the documented verification contract.
Workflow public contracts
src/workflows/df12-build-odw/{assessment,execplan-durability,recovery-decision,types}.ts
Expands JSDoc and adds the withInfraRetry, detail, recentCommits, and authFaults contract fields.
Execution and evidence behaviour
src/workflows/df12-build-odw/{config,exec,faults,git-evidence,write-preflight}.ts
Documents execution and evidence semantics, updates CodeScene probe handling, and validates write-probe edge cases.
Orchestration and pipeline documentation
src/workflows/df12-build-odw/*
Adds module, interface, return-shape, schema, and factory-property documentation.
Remediation and roadmap helpers
src/workflows/df12-build-odw/{remediation,roadmap}.ts, tests/modules/*
Validates remediation titles and source aggregation, and adds roadmap range expansion and identifier extraction.
Generated runtime annotations
workflows/df12-build-odw.js
Updates generated helper validation, probe flags, CodeScene handling, metrics, and factory return annotations.

Possibly related PRs

  • leynos/df12-build#50: Updates the related infrastructure-retry and fault-metrics wiring.
  • leynos/dakar#5: Implements the same TypeDoc-based docs-check gate pattern across CI and project tooling.

Suggested reviewers: pandalump

Poem

TypeDoc lights the gate,
JSDoc blooms across the flow,
CI checks each step,
Schemas sleep behind internal,
Roadmap helpers neatly grow.

🚥 Pre-merge checks | ✅ 19 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 65.63% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (19 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarises the main change from docstring-coverage to a zero-tolerance TypeDoc gate.
Description check ✅ Passed The description directly matches the changeset and explains the new TypeDoc gate, CI workflow, and documentation updates.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Testing (Overall) ✅ Passed The changed behaviours are covered by focused property/integration tests across roadmap, remediation, host-review, write-preflight, faults and assessment; I found no vacuous or mock-only oracles.
User-Facing Documentation ✅ Passed PASS: docs/users-guide.md already covers the operator-visible behaviours this PR touches; the remaining changes are internal or developer-facing.
Developer Documentation ✅ Passed PASS: docs/developers-guide and docs/architecture now cover docs-check/CI, ADR 002 records the decision, and the related execplan is already COMPLETE.
Module-Level Documentation ✅ Passed Every TypeScript module in src/workflows/df12-build-odw starts with a JSDoc module block; the only non-doc files there are excluded d.ts/meta.js helpers.
Testing (Unit And Behavioural) ✅ Passed New tests cover edge cases and real boundaries: malformed ranges, blank proposal titles, FIFO/symlink probes, gate timeouts, and CodeScene skip/fail paths.
Testing (Property / Proof) ✅ Passed PASS: The broad range/containment invariants added here are covered by fast-check property tests in roadmap and execplan durability; no new lemma/proof assumption appears.
Testing (Compile-Time / Ui) ✅ Passed PASS: The repo already has a TypeScript compile-fail contract suite (tests/modules/compile-time-contract.test.ts) and the changed behaviour is covered by focused module/property tests.
Unit Architecture ✅ Passed Changed code keeps queries pure and pushes I/O/side-effects behind explicit command seams (withInfraRetry, runCodeSceneCheck, write probes); tests pin the boundaries.
Domain Architecture ✅ Passed Boundary helpers stay injectable and testable; the PR mainly adds docs/CI and keeps domain decisions free of transport or storage concerns.
Observability ✅ Passed Bounded metrics and decision-point logs cover retries, gates, CodeScene, salvage and recovery, with operator-facing detail surfaced in summaries.
Security And Privacy ✅ Passed The diff keeps CI read-only, uses no secrets, and only tightens probe/path handling; it adds no new auth, permission, or data-exposure surface.
Performance And Resource Use ✅ Passed No material regressions found: new loops and retries are bounded, probes are capped to two targets, and gate logs are cached with controlled I/O.
Concurrency And State ✅ Passed Concurrency is explicit: CI uses cancel-in-progress, host gates are serialized by hostGateLock, and the shared counters are bounded, owned, and tested.
Architectural Complexity And Maintainability ✅ Passed Approve: keep the new helpers local and justified; they replace bespoke parsing/coverage logic, and no extra layer, cycle, or hidden hook appears.
Rust Compiler Lint Integrity ✅ Passed No Rust sources changed; the PR only touches TypeScript, docs, workflow, and generated JS, with no lint suppressions or suspicious clone patterns to assess.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch typedoc-rollout

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 Biome (2.5.3)
workflows/df12-build-odw.js

File contains syntax errors that prevent linting: Line 4037: Illegal return statement outside of a function


Comment @coderabbitai help to get the list of available commands.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @leynos, your pull request is larger than the review limit of 150000 diff characters

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
src/workflows/df12-build-odw/host-review.ts (1)

484-499: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Fail closed when the CodeScene probe itself fails.

runCodeSceneCheck maps every probe.ok === false to “binary not on PATH” and skipped: true, but ExecStatus.ok is also false for spawn, timeout, signal, and other probe faults. Skip only on a confirmed command-not-found result; surface other probe failures as gate failures so a broken host cannot silently disable an enabled check.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/workflows/df12-build-odw/host-review.ts` around lines 484 - 499, Update
runCodeSceneCheck to distinguish a confirmed command-not-found probe result from
other ExecStatus failures: set skipped only for the specific missing-binary
condition, and treat spawn, timeout, signal, and other probe faults as clean:
false with actionable detail. Preserve the existing skip behavior for
environments where the CodeScene binary is genuinely absent.
src/workflows/df12-build-odw/remediation.ts (2)

102-106: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Do not silently drop title-less proposals.

RemediationProposal.title is optional, but if (!key) continue removes such proposals before triage. Make the title mandatory at the boundary and reject invalid input explicitly, or preserve it in an explicit invalid-proposal result; never discard a review or audit finding without recording it.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/workflows/df12-build-odw/remediation.ts` around lines 102 - 106, Update
dedupeProposals so title-less proposals are not silently discarded by the if
(!key) continue branch. Enforce a mandatory title at the input boundary and
explicitly reject invalid proposals, or preserve them as an explicit
invalid-proposal result; ensure every review or audit finding remains recorded.

107-117: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Preserve merged source metadata across deduplication passes.

dedupeProposals writes sources but returns RemediationProposal[], whose contract does not expose that field. Re-running the exported helper then rebuilds sources only from source or rationale, so a proposal carrying ['review:1', 'audit:2'] can lose an origin and make triageNeedsEscalation select the medium model. Return a named deduped type and merge existing sources before adding the legacy fallback.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/workflows/df12-build-odw/remediation.ts` around lines 107 - 117, The
dedupeProposals result must preserve all existing source metadata across
repeated deduplication passes. Introduce and return a named deduped proposal
type that exposes sources, then update the source aggregation around the
source/rationale fallback to merge proposal.sources first and add the fallback
only when it is not already present; keep deduplication and triage behavior
unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/ci.yml:
- Around line 11-13: Add workflow-level concurrency configuration near the top
of the CI workflow, using a group that identifies the workflow or branch and
setting cancel-in-progress to true. Keep the existing test job and its
sequential gate execution unchanged.
- Line 33: Update the CI Markdown validation setup around the markdownlint-cli2
installation to use a repository-managed, lockfile-backed dependency instead of
global npm installation. Add or reuse the project binary and committed npm
lockfile, then invoke the locked dependency without allowing transitive
resolution to occur outside version-controlled files.

In `@docs/developers-guide.md`:
- Around line 513-522: Update the documentation description near the docs-check
target to reflect the expanded configured entry-point scope rather than claiming
validation covers the entire src/workflows/df12-build-odw tree. Explicitly name
the typedoc.json exclusions for declaration files, meta.js, and internal,
private, and protected reflections, while preserving the remaining validation
behavior.

In `@src/workflows/df12-build-odw/config.ts`:
- Around line 278-286: The makeConfig documentation incorrectly describes
WorkflowConfig as immutable despite exposing mutable collections. Change the
wording in the makeConfig JSDoc from “immutable” to “fully resolved” and leave
the existing configuration behavior unchanged.

In `@src/workflows/df12-build-odw/git-evidence.ts`:
- Around line 199-205: Update the file-reading implementation documented by the
JSDoc above to eliminate the parent-symlink TOCTOU window, preferably by
resolving and opening each path component through race-resistant directory
handles while retaining final-component protection and worktree containment
checks. If that cannot be implemented safely, narrow the JSDoc guarantee so it
no longer claims untrusted content cannot redirect the read.

In `@src/workflows/df12-build-odw/recovery-decision.ts`:
- Around line 70-71: Align the exported `validation` contract and
`recoveryResumeEligibility` behavior: either update the documentation to
describe the actual missingEvidence-only downgrade rule, or restore validation’s
non-blank requirement in the eligibility logic. Ensure the documented contract
and runtime decision table express the same resume behavior.

In `@src/workflows/df12-build-odw/roadmap.ts`:
- Around line 71-76: Update expandStepRange to validate both start and end
arguments against the roadmap step-ID grammar before converting them to numbers,
returning [] for empty, negative, malformed, or otherwise invalid IDs while
preserving valid same-phase range expansion. Keep the existing cross-phase,
non-integer, and reversed-range handling and ensure the JSDoc contract remains
accurate.

In `@src/workflows/df12-build-odw/write-preflight.ts`:
- Around line 113-125: Update verifyWriteProbe so special files, including
FIFOs, are rejected before any potentially blocking fs.open call. Inspect the
path without opening it, or use non-blocking open with a bounded fail-closed
read, while preserving the documented regular-file and token-match checks.

---

Outside diff comments:
In `@src/workflows/df12-build-odw/host-review.ts`:
- Around line 484-499: Update runCodeSceneCheck to distinguish a confirmed
command-not-found probe result from other ExecStatus failures: set skipped only
for the specific missing-binary condition, and treat spawn, timeout, signal, and
other probe faults as clean: false with actionable detail. Preserve the existing
skip behavior for environments where the CodeScene binary is genuinely absent.

In `@src/workflows/df12-build-odw/remediation.ts`:
- Around line 102-106: Update dedupeProposals so title-less proposals are not
silently discarded by the if (!key) continue branch. Enforce a mandatory title
at the input boundary and explicitly reject invalid proposals, or preserve them
as an explicit invalid-proposal result; ensure every review or audit finding
remains recorded.
- Around line 107-117: The dedupeProposals result must preserve all existing
source metadata across repeated deduplication passes. Introduce and return a
named deduped proposal type that exposes sources, then update the source
aggregation around the source/rationale fallback to merge proposal.sources first
and add the fallback only when it is not already present; keep deduplication and
triage behavior unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: a35c3e19-849b-4a0a-943f-b7fcfb06c95d

📥 Commits

Reviewing files that changed from the base of the PR and between c34fa0c and d4d660c.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (27)
  • .github/workflows/ci.yml
  • AGENTS.md
  • Makefile
  • docs/architecture.md
  • docs/developers-guide.md
  • package.json
  • scripts/docstring-coverage.mjs
  • src/workflows/df12-build-odw/assessment.ts
  • src/workflows/df12-build-odw/config.ts
  • src/workflows/df12-build-odw/exec.ts
  • src/workflows/df12-build-odw/execplan-durability.ts
  • src/workflows/df12-build-odw/faults.ts
  • src/workflows/df12-build-odw/git-evidence.ts
  • src/workflows/df12-build-odw/host-review.ts
  • src/workflows/df12-build-odw/main.ts
  • src/workflows/df12-build-odw/prompts.ts
  • src/workflows/df12-build-odw/recovery-decision.ts
  • src/workflows/df12-build-odw/recovery-discovery.ts
  • src/workflows/df12-build-odw/remediation.ts
  • src/workflows/df12-build-odw/roadmap.ts
  • src/workflows/df12-build-odw/run-task.ts
  • src/workflows/df12-build-odw/schemas.ts
  • src/workflows/df12-build-odw/types.ts
  • src/workflows/df12-build-odw/write-preflight.ts
  • tests/modules/docstring-coverage.test.ts
  • typedoc.json
  • workflows/df12-build-odw.js
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • leynos/nixie (auto-detected)
💤 Files with no reviewable changes (2)
  • tests/modules/docstring-coverage.test.ts
  • scripts/docstring-coverage.mjs

Comment thread .github/workflows/ci.yml
Comment on lines +11 to +13
jobs:
test:
runs-on: ubuntu-latest

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀 Performance & Scalability | 🔵 Trivial

Cancel superseded CI runs.

Add a workflow-level concurrency group with cancel-in-progress: true; each push currently leaves obsolete make all and strict Dafny jobs running, wasting runners and allowing stale results to complete.

As per coding guidelines, keep gate execution sequential; the supplied static analysis identifies the missing concurrency limit.

🧰 Tools
🪛 zizmor (1.26.1)

[info] 12-12: workflow or action definition without a name (anonymous-definition): this job

(anonymous-definition)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci.yml around lines 11 - 13, Add workflow-level
concurrency configuration near the top of the CI workflow, using a group that
identifies the workflow or branch and setting cancel-in-progress to true. Keep
the existing test job and its sequential gate execution unchanged.

Sources: Coding guidelines, Linters/SAST tools

Comment thread .github/workflows/ci.yml Outdated
- name: Install Markdown and Mermaid validators
run: |
set -euo pipefail
npm install --global "markdownlint-cli2@${MARKDOWNLINT_CLI2_VERSION}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Make the Markdown validator installation lockfile-backed.

npm install --global pins only the direct package and resolves transitive dependencies outside a committed lockfile. Move markdownlint-cli2 into a lockfile-backed project binary, or install it from a committed npm lockfile, so the CI toolchain cannot change without a repository diff.

As per coding guidelines, keep dependency resolution reproducible through committed lockfiles; the supplied static analysis identifies this installation as ad hoc.

🧰 Tools
🪛 zizmor (1.26.1)

[warning] 33-33: ad-hoc installation of packages (adhoc-packages): installs a package outside of a lockfile

(adhoc-packages)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci.yml at line 33, Update the CI Markdown validation setup
around the markdownlint-cli2 installation to use a repository-managed,
lockfile-backed dependency instead of global npm installation. Add or reuse the
project binary and committed npm lockfile, then invoke the locked dependency
without allowing transitive resolution to occur outside version-controlled
files.

Sources: Coding guidelines, Linters/SAST tools

Comment thread docs/developers-guide.md Outdated
Comment on lines +513 to +522
The `docs-check` target (run by `make all`, wrapping `bun run docs:check`) is
the zero-tolerance documentation gate: TypeDoc's `notDocumented` validation
over the whole `src/workflows/df12-build-odw/` tree, configured by
`typedoc.json`. Every module must open with a `/** … @module */` block and
every exported declaration must carry a JSDoc block; validation warnings are
errors, the run emits no documentation artefacts, and a failure prints the
qualified name and location of each undocumented declaration. JSON Schema
constants are tagged `@internal` (their `description` fields are the
per-field documentation), so TypeDoc does not recurse into the schema
literals:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

State the TypeDoc exclusions accurately.

Replace “over the whole src/workflows/df12-build-odw/ tree” with the expanded entry-point scope and name the configured exclusions: declaration files, meta.js, and internal/private/protected reflections. The current wording overstates the enforced scope and conflicts with typedoc.json.

As per path instructions, keep documentation accurate and current.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/developers-guide.md` around lines 513 - 522, Update the documentation
description near the docs-check target to reflect the expanded configured
entry-point scope rather than claiming validation covers the entire
src/workflows/df12-build-odw tree. Explicitly name the typedoc.json exclusions
for declaration files, meta.js, and internal, private, and protected
reflections, while preserving the remaining validation behavior.

Source: Path instructions

Comment on lines +278 to +286
/**
* Resolve raw workflow overrides into the immutable {@link WorkflowConfig} used
* throughout the run: applies every default, clamps numeric bounds, coerces
* string-typed args, and precomputes the derived guidance strings. Pure and
* side-effect free — the `projectRoot` chdir is left to the caller — so it is
* safe to build once and share. A null or missing argument yields the full
* default configuration. Throws when `resumeMode` is not one of `assess`,
* `review`, or `continue`.
*/

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Stop advertising a mutable configuration as immutable.

WorkflowConfig exposes mutable Set<string>, Record<string, string>, and string[] properties, so makeConfig does not provide an immutable TypeScript contract. Change “immutable” to “fully resolved”, or mark the relevant fields and containers readonly and avoid mutating them.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/workflows/df12-build-odw/config.ts` around lines 278 - 286, The
makeConfig documentation incorrectly describes WorkflowConfig as immutable
despite exposing mutable collections. Change the wording in the makeConfig JSDoc
from “immutable” to “fully resolved” and leave the existing configuration
behavior unchanged.

Source: Coding guidelines

Comment on lines +199 to +205
/**
* Read a worktree file without letting untrusted content redirect the read
* outside the checkout (see write-preflight.ts). O_NOFOLLOW rejects a symlink
* at the FINAL component; when a worktree root is given, realpath containment
* additionally rejects a symlinked PARENT directory that would resolve the
* ancestry outside the root. Callers treat any failure as an unreadable file.
*/

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

Close the parent-symlink TOCTOU window or narrow the guarantee.

The new comment claims untrusted content cannot redirect the read, but the implementation checks realpath(path.dirname(filePath)) and then opens filePath; an attacker can swap a parent symlink between those operations because O_NOFOLLOW protects only the final component. Use a race-resistant directory-handle approach, or remove the absolute guarantee from the JSDoc.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/workflows/df12-build-odw/git-evidence.ts` around lines 199 - 205, Update
the file-reading implementation documented by the JSDoc above to eliminate the
parent-symlink TOCTOU window, preferably by resolving and opening each path
component through race-resistant directory handles while retaining
final-component protection and worktree containment checks. If that cannot be
implemented safely, narrow the JSDoc guarantee so it no longer claims untrusted
content cannot redirect the read.

Comment on lines 70 to 71
/** Free-text validation evidence; a non-blank value is required to resume. */
validation?: string

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Align the validation documentation with the decision table.

Line 71 says non-blank validation is required to resume, but recoveryResumeEligibility explicitly makes missingEvidence the sole evidence-based downgrade gate and does not reject blank validation. Update the contract text or restore the check; do not leave the exported documentation inconsistent with runtime behaviour.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/workflows/df12-build-odw/recovery-decision.ts` around lines 70 - 71,
Align the exported `validation` contract and `recoveryResumeEligibility`
behavior: either update the documentation to describe the actual
missingEvidence-only downgrade rule, or restore validation’s non-blank
requirement in the eligibility logic. Ensure the documented contract and runtime
decision table express the same resume behavior.

Comment on lines +71 to +76
/**
* Expand a `steps X.Y-X.Z` range into its constituent ids. Returns `[]` for a
* malformed or cross-phase range (differing phase numbers, non-integer
* steps, or a start after the end) rather than throwing, so a caller parsing
* free text can simply skip the phrase.
*/

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Make the malformed-range contract true.

The new JSDoc promises [] for malformed inputs, but the implementation only checks numeric integrality; direct calls such as expandStepRange('', '') or expandStepRange('-1.2', '-1.3') return invalid roadmap IDs. Validate both arguments against the roadmap-ID grammar before numeric conversion, or narrow the JSDoc to callers that already matched STEP_RANGE_RE.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/workflows/df12-build-odw/roadmap.ts` around lines 71 - 76, Update
expandStepRange to validate both start and end arguments against the roadmap
step-ID grammar before converting them to numbers, returning [] for empty,
negative, malformed, or otherwise invalid IDs while preserving valid same-phase
range expansion. Keep the existing cross-phase, non-integer, and reversed-range
handling and ensure the JSDoc contract remains accurate.

Comment on lines +113 to +125
/**
* Host-side verification of one adapter's write probe. Opens the probe
* path with `O_NOFOLLOW` so the existence check and the content read
* target the same inode, closing the symlink-swap window between a
* separate stat and a path-based read; a symlink or non-regular file is
* treated as a rejected probe, not a pass.
*/
export async function verifyWriteProbe(probeFile: string, token: string): Promise<{
/** True only when the probe file existed, was a regular file, and its content matched the expected token. */
ok: boolean
/** Human-readable failure reason; empty when `ok` is true. */
detail: string
}> {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

Reject special files before a blocking open.

verifyWriteProbe opens the path before calling handle.stat(). A planted FIFO can block fs.open indefinitely, so the documented “non-regular file rejected” path never runs. Inspect without a blocking open, or open non-blocking and enforce a bounded, fail-closed probe.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/workflows/df12-build-odw/write-preflight.ts` around lines 113 - 125,
Update verifyWriteProbe so special files, including FIFOs, are rejected before
any potentially blocking fs.open call. Inspect the path without opening it, or
use non-blocking open with a bounded fail-closed read, while preserving the
documented regular-file and token-match checks.

leynos added 4 commits July 24, 2026 23:41
Bring the whole `src/workflows/df12-build-odw/` tree up to the
declaration-level documentation standard ahead of replacing the
threshold-based docstring-coverage gate with a zero-tolerance TypeDoc
gate: every exported function, interface, type alias, variable, and
property now carries a JSDoc block, and modules that opened with `//`
line-comment headers now open with `/** @file … */` blocks.

Documentation is comment-only, with three deliberate exceptions needed
so TypeDoc can attach comments to anonymous object types: three
single-line return-type literals in `run-task.ts` are reflowed to
multiline, and two `return { … }` shorthands are expanded, with shapes
unchanged. The JSON Schema constants (`*_SCHEMA`) keep their inferred
literal types (module tests pin deep paths into them) and are tagged
`@internal` as machine seams — their `description` fields remain the
per-field documentation.

Regenerate `workflows/df12-build-odw.js` from the annotated tree.
Swap the threshold-based, allow-listed `docstring-coverage` gate for
`docs-check`: TypeDoc's `notDocumented` validation over the whole
`src/workflows/df12-build-odw/` tree (`entryPointStrategy: "expand"`,
`emit: "none"`, warnings as errors). The gate requires 100%
documentation of the selected surface, reports the qualified name of
each undocumented declaration, writes no documentation artefacts, and
runs through `make all` via `bun run docs:check`.

- Convert every module's leading `/** @file … */` block to TypeDoc's
  `/** … @module */` form and require `"Module"` documentation, so the
  existing file-level documentation rule is preserved, not retired.
- Delete `scripts/docstring-coverage.mjs`, its test, and the
  `DOCSTRING_MODULES`/`DOCSTRING_MIN` allow-list — the custom
  AST-counting gate and its percentage threshold are superseded.
- Exclude `*.d.ts` (ambient ODW globals) and `meta.js` (verbatim
  artefact banner) from the documentation surface.
- Update AGENTS.md, the developers' guide, and the architecture
  verification contract to name the new gate and local command.

Verified: removing a JSDoc block from an exported function fails
`docs:check` with the symbol's qualified name and a non-zero exit;
restoring it returns the gate to green; a clean run emits no files.
Import the CI shape from `leynos/agent-template-typescript` (pinned
`checkout`/`setup-bun`/`setup-uv` actions, read-only token) and extend
it to this repository's aggregate gate: `bun install`, pinned
`markdownlint-cli2` and `nixie-cli` installs, a pinned Dafny 4.10.0
.NET tool install, then `make all` followed by
`make verify-modules-strict` so the LemmaScript/Dafny proof is a real
PR gate rather than a silent local skip. The checkout fetches full
history because `check-fmt` diffs back to the merge-base with
`origin/main`.

This also gives the new `docs-check` documentation gate a CI path
through the same aggregate command used locally.
Restore the advisory residual-risk channel added on `main` while retaining
the zero-tolerance TypeDoc coverage introduced by this branch.

Document the upstream declarations that entered the documentation surface
and regenerate the compiled ODW workflow from the resolved source tree.
@leynos
leynos force-pushed the typedoc-rollout branch from 94965dc to bcb1978 Compare July 24, 2026 21:43
@leynos

leynos commented Jul 24, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai resume

@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown
✅ Action performed

Reviews resumed.

Harden roadmap ranges, write probes, CodeScene probing, and remediation
proposal handling where review found live correctness gaps.

Make CI dependency installation and concurrency deterministic, align the
documentation contracts with the configured behaviour, and keep the
generated ODW artefact synchronized with the source.
@lodyai
lodyai Bot force-pushed the typedoc-rollout branch from bcb1978 to 1c8c67f Compare July 24, 2026 21:49

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/workflows/df12-build-odw/roadmap.ts (1)

77-85: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Bound accepted range sizes before materializing ids.

Reject oversized but syntactically valid ranges before Array.from; a Requires
range spanning millions of steps allocates millions of strings during roadmap
parsing and can stall or terminate the workflow. Define and document a maximum
range length, return [] beyond it, and add a boundary test.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/workflows/df12-build-odw/roadmap.ts` around lines 77 - 85, Update
expandStepRange to define and document a maximum allowed range length, validate
the calculated lastStep - firstStep + 1 before Array.from, and return [] when
the length exceeds that limit. Add a boundary test covering the maximum accepted
length and the first rejected oversized range.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/ci.yml:
- Around line 39-40: Update the “Install Dafny” workflow step to append
$HOME/.dotnet/tools to $GITHUB_PATH after installing the global tool, then run
dafny --version in that step to validate the executable is available. Preserve
the existing DAFNY_VERSION installation and ensure the later
verify-modules-strict command can resolve dafny via PATH.
- Around line 29-32: Update the oven-sh/setup-bun step to specify a fixed
bun-version or bun-version-file, ensuring CI uses a deterministic Bun release
before the Install JavaScript dependencies step runs.

In `@src/workflows/df12-build-odw/execplan-durability.ts`:
- Around line 72-79: Update execplanRelPath to enforce the normalized path
against the task-scoped docs/execplans/*.md predicate before returning ok: true.
Reject paths such as docs/execplans/../../README.md with the existing detail
failure shape, and ensure run-task.ts receives ok only for valid ExecPlan paths
before performing filesystem checks or calling commitExecplanDraft.

In `@tests/modules/remediation.test.ts`:
- Around line 56-70: Create a deterministic proposal() fixture factory in the
remediation tests with stable default proposal fields, then replace the repeated
inline proposal object literals in the titleless and repeated-deduplication
tests with factory calls and overrides for title, source, and sources. Preserve
the existing test scenarios and expected aggregation behavior.

---

Outside diff comments:
In `@src/workflows/df12-build-odw/roadmap.ts`:
- Around line 77-85: Update expandStepRange to define and document a maximum
allowed range length, validate the calculated lastStep - firstStep + 1 before
Array.from, and return [] when the length exceeds that limit. Add a boundary
test covering the maximum accepted length and the first rejected oversized
range.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 89c1fd6b-fd6f-4d28-86ee-6686ed24f370

📥 Commits

Reviewing files that changed from the base of the PR and between 478b6b7 and 1c8c67f.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (31)
  • .github/workflows/ci.yml
  • AGENTS.md
  • Makefile
  • docs/architecture.md
  • docs/developers-guide.md
  • package.json
  • scripts/docstring-coverage.mjs
  • src/workflows/df12-build-odw/assessment.ts
  • src/workflows/df12-build-odw/config.ts
  • src/workflows/df12-build-odw/exec.ts
  • src/workflows/df12-build-odw/execplan-durability.ts
  • src/workflows/df12-build-odw/faults.ts
  • src/workflows/df12-build-odw/git-evidence.ts
  • src/workflows/df12-build-odw/host-review.ts
  • src/workflows/df12-build-odw/main.ts
  • src/workflows/df12-build-odw/prompts.ts
  • src/workflows/df12-build-odw/recovery-decision.ts
  • src/workflows/df12-build-odw/recovery-discovery.ts
  • src/workflows/df12-build-odw/remediation.ts
  • src/workflows/df12-build-odw/roadmap.ts
  • src/workflows/df12-build-odw/run-task.ts
  • src/workflows/df12-build-odw/schemas.ts
  • src/workflows/df12-build-odw/types.ts
  • src/workflows/df12-build-odw/write-preflight.ts
  • tests/modules/docstring-coverage.test.ts
  • tests/modules/host-review.test.ts
  • tests/modules/remediation.test.ts
  • tests/modules/roadmap.property.test.ts
  • tests/modules/write-preflight.test.ts
  • typedoc.json
  • workflows/df12-build-odw.js
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • leynos/nixie (auto-detected)
💤 Files with no reviewable changes (2)
  • tests/modules/docstring-coverage.test.ts
  • scripts/docstring-coverage.mjs

Comment thread .github/workflows/ci.yml
Comment on lines +29 to +32
- uses: oven-sh/setup-bun@735343b667d3e6f658f44d0eca948eb6282f2b76
- uses: astral-sh/setup-uv@c5680ec91f7b9b91406fab4ded5d45245abf7b67
- name: Install JavaScript dependencies
run: bun install --frozen-lockfile

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== ci.yml relevant section =="
nl -ba .github/workflows/ci.yml | sed -n '1,120p'

echo
echo "== bun lock/package hints =="
rg -n --hidden -S 'bun-version|setup-bun|bun install|bun.lock|packageManager|tool-versions' .github . || true

Repository: leynos/df12-build

Length of output: 225


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== .github/workflows/ci.yml (top 120 lines) =="
sed -n '1,120p' .github/workflows/ci.yml

echo
echo "== workflow references to bun-version/setup-bun/bun install =="
rg -n -S 'bun-version|setup-bun|bun install|bun.lock|packageManager|tool-versions' .github . || true

Repository: leynos/df12-build

Length of output: 1974


🌐 Web query:

oven-sh/setup-bun bun-version default latest documentation

💡 Result:

For the oven-sh/setup-bun GitHub Action, the default behavior for the bun-version input is determined by a hierarchical check [1][2]. If no version is explicitly provided, the action will resolve the version in the following order of priority: 1. package.json: It first checks the packageManager field (e.g., "packageManager": "bun@1.0.25") [1][2]. 2. package.json: If the packageManager field is not present, it checks the engines.bun field [1][2]. 3. latest: If neither of the above fields exists or if no package.json file is found, it defaults to the latest version of Bun [1][2]. You can also override this behavior by explicitly setting the bun-version input in your workflow YAML: - uses: oven-sh/setup-bun@v2 with: bun-version: latest Additionally, the action supports a bun-version-file input (e.g., pointing to.bun-version or.tool-versions) which provides further flexibility for managing versions [1][3].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== package metadata =="
if [ -f package.json ]; then
  sed -n '1,120p' package.json
fi

echo
echo "== version files =="
find . -maxdepth 2 \( -name '.bun-version' -o -name '.tool-versions' -o -name 'package.json' \) -print | sort

Repository: leynos/df12-build

Length of output: 624


Pin Bun in CI. Set bun-version (or a bun-version-file) on oven-sh/setup-bun in .github/workflows/ci.yml:29-32; this repo has no packageManager, engines.bun, or version file, so the action resolves to the latest Bun release on every run.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci.yml around lines 29 - 32, Update the oven-sh/setup-bun
step to specify a fixed bun-version or bun-version-file, ensuring CI uses a
deterministic Bun release before the Install JavaScript dependencies step runs.

Comment thread .github/workflows/ci.yml
Comment on lines +39 to +40
- name: Install Dafny
run: dotnet tool install --global dafny --version "${DAFNY_VERSION}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## ci.yml around dafny install\n'
grep -n -A6 -B6 'dotnet tool install --global dafny' .github/workflows/ci.yml || true

printf '\n## search for dafny usage / verify-modules-strict\n'
rg -n 'verify-modules-strict|command -v dafny|dafny --version|dotnet tool install --global dafny|GITHUB_PATH|\.dotnet/tools' -S . || true

printf '\n## relevant Makefile lines if present\n'
fd -a 'Makefile|makefile|GNUmakefile' . -t f | while read -r f; do
  echo "--- $f"
  rg -n 'verify-modules-strict|command -v dafny|dafny' "$f" || true
done

Repository: leynos/df12-build

Length of output: 2348


Add $HOME/.dotnet/tools to PATH before the strict Dafny gate. Update the Install Dafny step in .github/workflows/ci.yml to write the global tool directory to $GITHUB_PATH and run dafny --version there; make verify-modules-strict later calls command -v dafny, and the global .NET install lands under ~/.dotnet/tools on Linux.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci.yml around lines 39 - 40, Update the “Install Dafny”
workflow step to append $HOME/.dotnet/tools to $GITHUB_PATH after installing the
global tool, then run dafny --version in that step to validate the executable is
available. Preserve the existing DAFNY_VERSION installation and ensure the later
verify-modules-strict command can resolve dafny via PATH.

Comment on lines +72 to +79
export function execplanRelPath(worktree: string, planPath: unknown): {
/** True when the path resolves inside the worktree. */
ok: boolean
/** The path relative to the worktree; empty when `ok` is false. */
relPath: string
/** Empty when `ok`; otherwise why the path was rejected. */
detail: string
} {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Path Traversal (CWE-22): Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')

Reachability
● Entry
  src/workflows/df12-build-odw/main.ts:268
  makeAssessment
│
▼
● Hop
  src/workflows/df12-build-odw/assessment.ts:47
  SalvageRecord: The assessment classification that triggered (or skipped) the salvage.
│
▼
● Sink
  src/workflows/df12-build-odw/execplan-durability.ts

Enforce the ExecPlan scope before accepting ok.

execplanRelPath accepts any path inside the worktree, so docs/execplans/../../README.md normalises to README.md and returns ok: true. src/workflows/df12-build-odw/run-task.ts then passes that path into file checks and commitExecplanDraft, allowing an arbitrary in-worktree file to be treated and committed as the ExecPlan. Reuse the task-scoped docs/execplans/*.md predicate after normalisation, before any filesystem or Git operation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/workflows/df12-build-odw/execplan-durability.ts` around lines 72 - 79,
Update execplanRelPath to enforce the normalized path against the task-scoped
docs/execplans/*.md predicate before returning ok: true. Reject paths such as
docs/execplans/../../README.md with the existing detail failure shape, and
ensure run-task.ts receives ok only for valid ExecPlan paths before performing
filesystem checks or calling commitExecplanDraft.

Comment on lines +56 to +70
test('rejects titleless proposals explicitly', () => {
expect(() => dedupeProposals([{ title: '', rationale: 'audit:1.1.1' }])).toThrow(/non-blank string/)
})

test('preserves aggregated sources across repeated deduplication', () => {
const first = dedupeProposals([
{ title: 'Fix flaky teardown', source: 'audit:1.2.3' },
{ title: 'fix flaky teardown', source: 'review:1.2.4' },
])
const second = dedupeProposals([
...first,
{ title: ' FIX FLAKY TEARDOWN ', sources: ['audit:1.2.3', 'expert:1.2.5'], source: 'review:1.2.4' },
])
expect(second).toHaveLength(1)
expect(second[0].sources).toEqual(['audit:1.2.3', 'review:1.2.4', 'expert:1.2.5'])

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Replace repeated proposal literals with a fixture factory.

Create a deterministic proposal() factory and use overrides for title, source,
and sources variations. This keeps the revised contract tests concise and
prevents fixture defaults from drifting.

As per coding guidelines, “Keep module tests deterministic and use fixtures and
factories instead of ad hoc object literals.”

Also applies to: 123-125

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/modules/remediation.test.ts` around lines 56 - 70, Create a
deterministic proposal() fixture factory in the remediation tests with stable
default proposal fields, then replace the repeated inline proposal object
literals in the titleless and repeated-deduplication tests with factory calls
and overrides for title, source, and sources. Preserve the existing test
scenarios and expected aggregation behavior.

Source: Coding guidelines

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant