Skip to content

Docs: reconcile published v1.4.2 guidance and the post-release Graphify boundary - #1009

Merged
jeffhuber merged 6 commits into
mainfrom
claude/1008-v142-docs-audit
Sep 17, 2026
Merged

jeffhuber merged 6 commits into
mainfrom
claude/1008-v142-docs-audit

Conversation

@jeffhuber

@jeffhuber jeffhuber commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Closes #1008.

What this is

One repository-wide documentation audit after the v1.4.2 publication, rebased
onto main at b863e638 so it reconciles against the current tree rather than
the pre-#1007 base.

v1.4.2 is published from release commit 55339bf1acf76d33be5937e80bdaad772e0b2bf5
under the annotated v1.4.2 tag, and release #952 is closed -- but current-facing
docs still described it as an unpublished source candidate pending #952. Separately,
PR #1007 has since merged to main at b863e638, so the published package and
main are no longer the same Graphify integration, and several pages still called
#1007 an open, unmerged pull request.

No source behaviour changes here beyond the release-readiness README link check
-- widened to accept the absolute spelling, then tightened until it resolves a
destination to the one document it addresses -- and two test-harness portability
fixes.

Published v1.4.2 versus current main

This is the distinction the rebase forced, and it is now stated explicitly rather
than left to the reader:

  • The published v1.4.2 package contains the optional Graphify integration
    exactly as it originally shipped. That claim is scoped to the base setup and
    ramp-up
    -- acquisition, the separate contained offline build, and steps 1
    through 7. It is not "everything above": Fix Graphify inventory limits and frontend test discovery #1007's language-extras and
    runtime-ownership paragraphs sit above that section, so they now carry an
    explicit post-v1.4.2 marker where a reader meets them, and the boundary
    section names them as the only paragraphs so marked.
  • main additionally carries Fix Graphify inventory limits and frontend test discovery #1007's real-pilot compatibility fixes: a bounded
    16 MiB provider-manifest reader separate from the 256 KiB compact
    generation-manifest bound, explicit refusal of an oversized provider manifest,
    doc_ref nodes accepted as declared non-code exclusions, and related_tests
    recognition of JavaScript/TypeScript .test/.spec and __tests__ conventions
    plus imports relationships. These are intended for the next appropriate release
    and are in no published package.
  • The accepted Graphify 0.9.58 pin and wheel digest are unchanged. Fix Graphify inventory limits and frontend test discovery #1007 is a
    Code Mower compatibility fix, not a provider upgrade.
  • Upgrading repairs no generation already built -- a published generation is
    never rewritten in place. That matters only for the generations Fix Graphify inventory limits and frontend test discovery #1007's
    compatibility gaps actually affected: most often an older frontend generation
    left partial
    , one whose oversized provider manifest was refused or whose
    inputs a missing language parser could not process. Those are rebuilt explicitly
    with code-mower context-graph refresh, then confirmed usable rather than
    partial. This is not a blanket rebuild of everything built before that
    future release: ask code-mower context-graph status --json first, and a
    generation it already reports usable needs no rebuild.

#1007's own Unreleased changelog entry and its documentation changes are preserved
verbatim through the rebase.

Changes

Published identity. README, install, quickstart, try-in-10-minutes, the
public-release and OSS checklists, the early-adopter runbooks, sessions,
github-setup, builders-grok-cursor, the PyPI runbook, and release history now state
v1.4.2 as the published package-index baseline. README, current-state, and the
rollout plan use versioning.public_baseline_sentence() verbatim so the next release
moves them together.

Release records. docs/v142-release-notes.md and docs/v142-qualification.md
become final records. Only proven outcomes are PASS, each bound to its evidence: the
independent Codex audit of PR #1006 head 32706cf5, CI run 35188065537, publish run
35189302150, the wheel/sdist digests, and both verified local Board restarts. Run
35189721623's skipped publish jobs are recorded as the intended posture, not a
failure. Metadata upload is marked not required and no cloud aggregate check is
claimed. Both pages note that the immutable v1.4.2 tag still carries the
prepublication snapshots; the tag is not touched.

Roadmap. v1.4.0/v1.4.1/v1.4.2 recorded as shipped, Board complete at 55339bf,
#951 kept explicit as the separately pending hosted Devin canary that this release
does not claim and does not close
, #1007 recorded as merged-on-main awaiting the
next release, and v1.5.0 Slack as the active phase. Merged PRs now use /pull/ URLs
while issues use /issues/.

Graphify. README navigation to setup/lifecycle/queries, a ramp-up flow in
graphify-setup.md with the excluded inputs and the absence of a working-tree
watcher, a new "Published v1.4.2 versus current main" section, a dated historical
banner on graphify-evaluation.md that preserves its benchmark record, and
version-boundary notes in context-graph-lifecycle.md and context-graph-queries.md
so a reader on the published package is not told #1007's behaviour is available to
them. Four ramp-up commands got their lost backslash continuations back.

The boundary section states its claim precisely rather than as "everything above",
which was false: #1007 added two paragraphs to
Separate acquisition environment
that sit above it. Those paragraphs now carry an explicit post-v1.4.2 marker in
place, and the rebuild guidance in graphify-setup.md, README, and the roadmap is
narrowed to the generations those compatibility gaps affected rather than every
generation built before the next release.

Board and install. The persistent Board service and its macOS/launchd boundary
surfaced from README and docs navigation; board-demo browser wording fixed; the
stranded delayed_health_failed row moved into the delayed-health section. Official
pipx/uv installation links and command -v preflight checks, with no curl-pipe-shell,
plus the install boundaries adoption feedback keeps returning to.

Portability and consistency. The installed-lineage harness canonicalizes its temp
root and both sides of every provenance assertion, so the documented replay is
portable on macOS where temp dirs arrive through the /var -> /private/var symlink.
templates/lanes/README.md synced with the packaged copy. README links made absolute
so the built PyPI long description resolves, with release_readiness accepting either
spelling -- and resolving the destination to the document it actually addresses, so
the allowance cannot be satisfied by a lookalike file or a foreign URL (see below).

CHANGELOG. Unreleased moved to the top. It is not empty: it carries #1007's
Fixed entry and states the boundary directly. The entries previously listed there
shipped in v1.4.1 and are recorded under that release.

Tests. tests/test_release_v142.py rewritten away from candidate-state
enforcement onto the published identity, README link behaviour, packaged-template
consistency, issue-vs-pull URLs, and the repaired lifecycle table. The assertion that
#1007 was absent from the changelog -- which encoded the now-false claim that it is
unmerged -- is replaced by coverage that Unreleased carries the merged entry, that
the setup and roadmap pages state the boundary in both directions including the
rebuild requirement, that no current page still calls #1007 open, and that the pin
stays at 0.9.58.

Two further tests enforce the precise boundary. One rejects any "everything above
describes that package" spelling, requires the scoped claim, and requires the
post-v1.4.2 marker to appear above the boundary section with both #1007 paragraphs
still under the acquisition heading that section names. The other rejects blanket
rebuild-everything-built-before wording in graphify-setup.md, README, and the
roadmap, and requires all three to tie the rebuild to the partial state, name the
frontend generation, and record that a generation status already reports usable
needs none. Both were verified to fail against the pre-fix text.

Release-readiness link check: resolve the destination, do not match its suffix

This gate took two review rounds. Both findings were real, and the second superseded
the first fix.

Round 1 (Gitar, on 4129cb65). _links_to_repository_doc compared destinations
with a bare endswith(relative_path), so any path merely ending in the required
filename satisfied the requirement: [Support](docs/OTHER_SUPPORT.md) passed the
public-docs-linked-from-readme check while never linking SUPPORT.md. Fixed in
58976cc7 by requiring a path-segment boundary.

Round 2 (Codex exact-head audit of 58976cc7, P2 --
audit comment).

The boundary rule was still a suffix test, and two false positives survived it:

  • [Support](docs/SUPPORT.md) passed, because the path ends at a /SUPPORT.md
    boundary -- even though no such file exists in this tree.
  • [Support](https://example.com/SUPPORT.md) passed, as did
    https://github.com/someone-else/code-mower/blob/main/SUPPORT.md. Any unrelated URL
    ending in the required filename satisfied a check about this repository's docs.

The fix in 05b01f5c. The destination is now resolved to the single
repository-relative path it addresses, and that path has to equal the required
document. A new _repository_destination_path helper does the resolving:

  • a relative destination is normalized against the repository root, where
    README.md sits (posixpath.normpath). SUPPORT.md, ./SUPPORT.md and
    docs/../SUPPORT.md all resolve to SUPPORT.md; docs/SUPPORT.md resolves to
    docs/SUPPORT.md and no longer matches; ../SUPPORT.md escapes the root and
    resolves to nothing.
  • an absolute destination resolves only when it is this repository's own GitHub
    URL. A single anchored pattern -- https://github.com/codemower-ai/code-mower/
    then blob or raw, then the ref segment -- yields the path under that ref. The
    owner and repository come from a named REPOSITORY_SLUG constant, so a different
    host, owner, or repository resolves to nothing however its URL ends. blob and
    raw are the two views that address a file; nothing narrower would accept the
    README's own links, and nothing broader is used.
  • anything else carrying a URI scheme (mailto:, http:, …), a scheme-relative
    //host/..., or a site-root /SUPPORT.md resolves to nothing.

Query strings and fragments are still dropped before resolving, since neither changes
which file a destination addresses; …/SUPPORT.md?plain=1 and …/SUPPORT.md#anchor
both still pass.

One intended spelling was deliberately dropped: site-root /SUPPORT.md, which
58976cc7 accepted. GitHub does not resolve a site-root path against the repository,
so that was a broken link the check was passing. Nothing in this repository uses it,
and migration release-readiness --json is still 20/20 with
public-docs-linked-from-readme pass on the real README.

Regression tests. The unit test over _links_to_repository_doc now runs 11
accepted and 14 rejected destinations as named subtests. Accepted: the relative form,
./-prefixed, a traversal that lands on the file, a trailing slash, fragment and
query variants, and the absolute blob URL on both a branch and a tag, the raw URL,
and its fragment and query variants. Rejected: both flagged false positives
(docs/SUPPORT.md and https://example.com/SUPPORT.md), plus the nested absolute
path, another owner, another repository, a nested foreign host, the scheme-relative
form, site-root, four sibling-suffix spellings, and parent traversal. The end-to-end
test drives render_release_readiness over five synthetic READMEs and asserts
public-docs-linked-from-readme is fail for the lookalike, the nested path, and
the foreign URL, and pass for the exact relative and absolute forms.

Both tests were run against the 58976cc7 implementation and fail there -- 11 subtest
failures across the two, including one for each flagged false positive at both the
unit and end-to-end level -- so neither assertion is vacuous.

This touches src/code_mower/release_readiness.py and tests/test_release_hygiene.py
only. No documentation and no product behaviour outside this one gate.

Validation

Rebased onto b863e638 (exact current origin/main); one CHANGELOG conflict resolved
by this writer. Final head 05b01f5c698c16669912ac5dfaa0d19721e02408.

The Codex P2 fix above landed in 05b01f5c on top of 58976cc7. It touches
src/code_mower/release_readiness.py and tests/test_release_hygiene.py only -- 2
files, +142/-37, no documentation and no other product code. The validation below was
re-run at 05b01f5c. The earlier heads stand as reported: 58976cc7 carried the
Gitar fix (2 files, +86/-1) and 4129cb65 the two P2 documentation corrections
(4 files, +104/-13, no product code).

Check Result
test_release_hygiene.py at 05b01f5c pass -- 363 tests (361 + the 2 link-resolution tests)
test_release_v142.py at 05b01f5c pass -- 50 tests (48 + the 2 boundary tests from 4129cb65)
Focused release/docs suites at 05b01f5c pass -- 498 tests, 1 skipped, 1414 subtests, 0 failures, across test_release_v142 (50), test_release_hygiene (363), test_documentation (2), test_documented_commands (7), test_release_v141 (7), test_release_qualify (70, 1 skipped)
Focused release/graph/docs suites at 4129cb65 pass -- 982 tests, 2 skipped, 0 failures, across test_release_v142 (50), test_release_hygiene (361), test_documentation (2), test_documented_commands (7), test_context_graph_lifecycle (269), test_context_graph_query (132), test_context_graph (25), test_context_graph_connection (42), test_context_readiness (12), test_lineage_producer_artifacts (5), test_release_v141 (7), test_release_qualify (70)
Link-resolution tests fail against the 58976cc7 code verified -- 11 subtest failures across the two, including docs/SUPPORT.md and https://example.com/SUPPORT.md at both the unit and end-to-end level
New doc boundary tests fail against pre-fix text verified -- both fail when the docs are reverted, so neither assertion is vacuous
ruff check . pass
scripts/privacy_scan.py pass -- privacy scan passed
git diff --check clean
compileall src scripts at 05b01f5c pass
migration release-readiness --json at 05b01f5c pass -- 20/20 checks, 0 failed, 0 warnings; public-docs-linked-from-readme still pass, since the README's links are this repository's own blob/main/ URLs. No-publish posture, next action is the publish_testpypi=false publish_pypi=false dry run
scripts/guard_package_workflows.py pass
scripts/smoke_easy_mode.py pass
python -m build + twine check --strict pass -- wheel and sdist both PASSED
Wheel METADATA 75 long-description links, 0 relative; Project-URL set intact; new graphify-setup.md#published-v142-versus-current-main anchor verified to resolve
Stale-language / private-path / secret scans clean -- no #1007-open phrasing outside the test guard lists, no personal paths, no private repo name, no token-shaped values in the branch diff
Full python -m unittest discover -s tests exit 1 -- 4503 tests, 4 failures + 1 error, 18 skipped (see below)

The full suite was run without a pipeline so the Python exit code survived; stdout and
stderr were captured to files and the exit code read back from disk.

ruff check ., scripts/privacy_scan.py, and git diff --check were re-run at
05b01f5c and are clean there. Rows not marked with a commit were run at 4f4a5456
and are unaffected by the later commits: 4129cb65 changes three Markdown pages and
one test module, and 58976cc7 and 05b01f5c change one gate function and its tests.
None touches packaging inputs, workflows, or the long description, so the build,
twine, METADATA, and workflow-guard rows still hold; the 05b01f5c re-run above
covers every suite that reads the changed code.

The 5 full-suite failures are pre-existing and unrelated

All five are macOS lane-runner tests whose fake Codex CLI exits 2:

  • test_devin_builder_lane.DevinMacLaneRunnerFunctionalTests.test_devin_lane_auto_selects_and_targets_correctly_prefixed_local_branch (error)
  • test_branch_policy.GeneratedRunnerTests.test_fix_round_guards_exactly_the_policy_compliant_target
  • test_branch_policy.GeneratedRunnerTests.test_fix_round_without_a_policy_keeps_the_lane_prefix_target
  • test_branch_policy.GeneratedRunnerTests.test_generated_devin_to_codex_takeover_and_replay_need_no_prefix_patch
  • test_branch_policy.GeneratedRunnerTests.test_handoff_runner_without_ambient_tmpdir_keeps_guard_exit_and_replay_contracts

They touch no file this PR changes. Reproduced identically in a clean detached
worktree at unmodified origin/main b863e638 (4 failures + 1 error) and at the
published release commit 55339bf (4 failures + 1 error) -- the commit whose full CI
run was green. This is a condition of this macOS host, not a regression from #1007 or
from this branch. Linux CI on this PR is the authority for them.

Live-issue follow-up

Boundaries

No product or cloud schema expansion. No paid hosted session. No private repository
name, graph/index content, raw provider log, personal path, or source appears in any
changed file. Archived transcripts and historical release runbooks are preserved as
historical records with framing added only where needed; the immutable v1.4.2 tag is
not touched.

🤖 Generated with Claude Code

jeffhuber and others added 3 commits September 17, 2026 00:16
v1.4.2 is published from 55339bf under the
annotated v1.4.2 tag, and release #952 is closed, but current-facing docs on
main still described it as an unpublished source candidate pending #952.

- State v1.4.2 as the published package-index baseline across README, install,
  quickstart, try-in-10-minutes, the public-release and OSS checklists, the
  early-adopter runbooks, sessions, github-setup, builders-grok-cursor, the
  PyPI runbook, and release history. README, current-state, and the rollout
  plan now use versioning.public_baseline_sentence() verbatim.
- Convert docs/v142-release-notes.md and docs/v142-qualification.md into final
  records. Only proven outcomes are PASS, each bound to its evidence: the
  independent Codex audit of PR #1006 head 32706cf, CI run 35188065537,
  publish run 35189302150, the wheel/sdist digests, and both verified local
  Board restarts. Run 35189721623's skipped publish jobs are recorded as the
  intended posture. Metadata upload is marked not required; no cloud aggregate
  check is claimed. Both pages note that the immutable v1.4.2 tag still carries
  the prepublication snapshots; the tag is not touched.
- Record v1.4.0/v1.4.1/v1.4.2 as shipped in the roadmap, Board complete at
  55339bf, #951 as the separately pending hosted canary, and v1.5.0 Slack as
  the active phase. Historical PR mapping moves to past tense and merged PRs
  now use /pull/ URLs while issues use /issues/.
- Surface Graphify as shipped optional functionality: README navigation to
  setup/lifecycle/queries, a ramp-up flow in graphify-setup.md, the excluded
  inputs and the absence of a working-tree watcher, and a dated historical
  banner on graphify-evaluation.md that preserves its benchmark record.
- Surface the persistent Board service and its macOS/launchd boundary from
  README and docs navigation, fix the board-demo browser wording, and move the
  stranded delayed_health_failed row into the delayed-health section where its
  post-apply semantics belong.
- Add official pipx/uv installation links and command -v preflight checks
  without any curl-pipe-shell, and record the install boundaries adoption
  feedback keeps returning to.
- Sync templates/lanes/README.md with the packaged copy so both document the
  supported `never` token expiry.
- Make README links absolute so the built PyPI long description resolves, and
  teach release_readiness to accept either link spelling.
- Canonicalize the installed-lineage harness temp root and both sides of every
  provenance assertion so the documented replay is portable on macOS, where
  temporary directories arrive through the /var -> /private/var symlink.
- Move CHANGELOG Unreleased to the top and empty it; its entries shipped in
  v1.4.1 and are recorded there.
- Rewrite tests/test_release_v142.py away from candidate-state enforcement onto
  the published identity, README link behavior, packaged-template consistency,
  issue-vs-pull URLs, and the repaired lifecycle table.

Refs #1008.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Four multi-line commands in the new ramp-up flow lost their trailing
line-continuation, joining each command onto one line with stray whitespace.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
PR #1007 merged to main at b863e63 after v1.4.2 was published, so the two are
no longer the same integration. Current docs still described #1007 as an open,
unmerged pull request and left its entry out of the changelog entirely.

- CHANGELOG: Unreleased is no longer empty. It carries #1007's Fixed entry and
  states the boundary directly -- accepted on main, in no published package,
  intended for the next appropriate release. The v1.4.1 shipped entries and the
  immutable 1.4.2 section are unchanged, and the Graphify fix is not
  double-booked into 1.4.2.
- graphify-setup.md: replace the stale "separate open pull request ... not
  merged and not released" paragraph with a "Published `v1.4.2` versus current
  `main`" section naming what merged, that the accepted 0.9.58 pin and wheel
  digest are untouched because this is a Code Mower fix rather than a provider
  upgrade, and that a generation built before the next release must be rebuilt
  with `context-graph refresh`. A published generation is never rewritten in
  place, so upgrading alone does not repair an older partial frontend
  generation.
- current-state-and-roadmap.md: the published package carries the originally
  shipped integration; the merged compatibility fixes are recorded as on main
  awaiting the next appropriate release, in the Graphify phase and in the
  delivery-order note about merged-but-unpublished work.
- README, context-graph-lifecycle.md and context-graph-queries.md: state where
  the #1007 behaviour does and does not apply, so a reader on the published
  package is not told the separate provider-manifest budget, `doc_ref`
  exclusions, or JavaScript/TypeScript test conventions are available to them.
- graphify-evaluation.md: point the historical banner at that boundary section.
- test_release_v142.py: drop the assertion that #1007 is absent from the
  changelog, which encoded the now-false claim that it is unmerged. Replace it
  with coverage that Unreleased carries the merged entry, that the setup and
  roadmap pages state the boundary in both directions including the rebuild
  requirement, that no current page still calls #1007 open, and that the pin
  stays at 0.9.58.

Rebased onto b863e63 with #1007's changelog entry and documentation preserved.

Refs #1008.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@jeffhuber jeffhuber added builder:claude Code Mower generated label needs-codex-audit labels Sep 17, 2026
Comment thread src/code_mower/release_readiness.py Outdated
Comment on lines +107 to +121
def _links_to_repository_doc(markdown: str, label: str, relative_path: str) -> bool:
"""Whether ``markdown`` links ``label`` at ``relative_path``.

README.md is also the built package's long description, where a relative
destination resolves against the package index rather than the repository,
so repository links there are absolute GitHub URLs. Both spellings satisfy
this check; only the label and the file it lands on are required.
"""

pattern = re.compile(
r"\[" + re.escape(label) + r"\]\(\s*<?([^)\s>]+)>?[^)]*\)"
)
for destination in pattern.findall(markdown):
if destination.partition("#")[0].rstrip("/").endswith(relative_path):
return True

@gitar-bot gitar-bot Bot Sep 17, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Bug: _links_to_repository_doc matches path via endswith, allowing false positives

In src/code_mower/release_readiness.py:107-122, _links_to_repository_doc checks destination.partition("#")[0].rstrip("/").endswith(relative_path). Because this is a suffix check rather than an exact match, a link to an unrelated file like docs/OTHER_SUPPORT.md or vendor/SECURITY.md would incorrectly satisfy the check for label "Support"/SUPPORT.md or "Security Policy"/SECURITY.md. This weakens the release-readiness gate that is supposed to verify README links point at the real top-level SUPPORT.md/SECURITY.md/CODE_OF_CONDUCT.md files; a rename or the addition of a similarly-suffixed file elsewhere in the repo would make the check pass without those exact docs being linked.

Require the match to be the whole path or preceded by a path separator, not an arbitrary suffix.:

def _links_to_repository_doc(markdown: str, label: str, relative_path: str) -> bool:
    pattern = re.compile(
        r"\[" + re.escape(label) + r"\]\(\s*<?([^)\s>]+)>?[^)]*\)"
    )
    for destination in pattern.findall(markdown):
        cleaned = destination.partition("#")[0].rstrip("/")
        if cleaned == relative_path or cleaned.endswith("/" + relative_path):
            return True
    return False

Was this helpful? React with 👍 / 👎

@gitar-bot

gitar-bot Bot commented Sep 17, 2026

Copy link
Copy Markdown

Note

Automatic reviews are paused because your team has used its included automatic processing for this billing period (headroom scales with your seat count). You can still comment "Gitar review" to run one anytime, and automatic reviews resume on their own by October 1. Add seats for more headroom.
Learn more

Code Review 👍 Approved with suggestions 0 closed / 1 findings

Documentation audit reconciling v1.4.2 published guidance with current main post-#1007 merge, including Graphify boundary clarification, release records, roadmap updates, and Board/install improvements. Test coverage expanded to 48 tests with 241 subtests, all validation passing. Consider tightening _links_to_repository_doc suffix matching to exact paths to prevent false positives when similarly-named files exist elsewhere in the repository.

💡 Bug: _links_to_repository_doc matches path via endswith, allowing false positives

📄 src/code_mower/release_readiness.py:107-121

In src/code_mower/release_readiness.py:107-122, _links_to_repository_doc checks destination.partition("#")[0].rstrip("/").endswith(relative_path). Because this is a suffix check rather than an exact match, a link to an unrelated file like docs/OTHER_SUPPORT.md or vendor/SECURITY.md would incorrectly satisfy the check for label "Support"/SUPPORT.md or "Security Policy"/SECURITY.md. This weakens the release-readiness gate that is supposed to verify README links point at the real top-level SUPPORT.md/SECURITY.md/CODE_OF_CONDUCT.md files; a rename or the addition of a similarly-suffixed file elsewhere in the repo would make the check pass without those exact docs being linked.

Require the match to be the whole path or preceded by a path separator, not an arbitrary suffix.
def _links_to_repository_doc(markdown: str, label: str, relative_path: str) -> bool:
    pattern = re.compile(
        r"\[" + re.escape(label) + r"\]\(\s*<?([^)\s>]+)>?[^)]*\)"
    )
    for destination in pattern.findall(markdown):
        cleaned = destination.partition("#")[0].rstrip("/")
        if cleaned == relative_path or cleaned.endswith("/" + relative_path):
            return True
    return False
🤖 Prompt for agents
Code Review: Documentation audit reconciling v1.4.2 published guidance with current `main` post-#1007 merge, including Graphify boundary clarification, release records, roadmap updates, and Board/install improvements. Test coverage expanded to 48 tests with 241 subtests, all validation passing. Consider tightening `_links_to_repository_doc` suffix matching to exact paths to prevent false positives when similarly-named files exist elsewhere in the repository.

1. 💡 Bug: _links_to_repository_doc matches path via endswith, allowing false positives
   Files: src/code_mower/release_readiness.py:107-121

   In src/code_mower/release_readiness.py:107-122, _links_to_repository_doc checks `destination.partition("#")[0].rstrip("/").endswith(relative_path)`. Because this is a suffix check rather than an exact match, a link to an unrelated file like `docs/OTHER_SUPPORT.md` or `vendor/SECURITY.md` would incorrectly satisfy the check for label "Support"/`SUPPORT.md` or "Security Policy"/`SECURITY.md`. This weakens the release-readiness gate that is supposed to verify README links point at the real top-level SUPPORT.md/SECURITY.md/CODE_OF_CONDUCT.md files; a rename or the addition of a similarly-suffixed file elsewhere in the repo would make the check pass without those exact docs being linked.

   Fix (Require the match to be the whole path or preceded by a path separator, not an arbitrary suffix.):
   def _links_to_repository_doc(markdown: str, label: str, relative_path: str) -> bool:
       pattern = re.compile(
           r"\[" + re.escape(label) + r"\]\(\s*<?([^)\s>]+)>?[^)]*\)"
       )
       for destination in pattern.findall(markdown):
           cleaned = destination.partition("#")[0].rstrip("/")
           if cleaned == relative_path or cleaned.endswith("/" + relative_path):
               return True
       return False

Review coverage

Rules No rules evaluated

Functional validation Not enabled · Set up

Options

Display: compact → Counting what did not apply, without listing it.

Comment with these commands to change the behavior for this request:

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

Two documentation inaccuracies found in root review, both in the
post-v1.4.2 Graphify guidance.

"Everything above describes that package" was false. PR #1007 added the
language-extras and runtime-ownership paragraphs to "Separate acquisition
environment", which sits above the boundary section, so part of "above"
describes current main rather than the published v1.4.2 package. The
claim is now scoped to the base setup and ramp-up -- acquisition, the
separate contained offline build, and steps 1 through 7 -- and the two
#1007 paragraphs carry an explicit post-v1.4.2 marker where a reader
meets them, which the boundary section names.

The rebuild guidance implied every generation built before the next
release must be rebuilt. It is narrowed to the generations #1007's
compatibility gaps actually affected: most often an older frontend
generation left partial, whose oversized provider manifest was refused
or whose inputs a missing language parser could not process. A
generation "context-graph status --json" already reports usable needs no
rebuild. Applied in docs/graphify-setup.md, README.md, and
docs/current-state-and-roadmap.md; the changelog and release records
carried no equivalent claim.

Two tests in tests/test_release_v142.py enforce the boundary: one
rejects any "everything above describes that package" spelling and
requires the scoped claim plus the in-place post-v1.4.2 marker above the
boundary section, the other rejects blanket
rebuild-everything-built-before wording across all three pages and
requires each to tie the rebuild to the partial state and exempt a
generation status already reports usable. Both fail against the pre-fix
text.

No product code changed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@jeffhuber

Copy link
Copy Markdown
Contributor Author

Codex audit (merge-authority lane)

Head SHA: 4129cb65d81334be09451d99ef2c968599cf7d4f
Findings: P0=0, P1=0, P2=0, P3=0 (blocker policy: any P0/P1/P2 → BLOCKED)

Codex Audit: PASS

Summary:

No actionable regressions were identified. Test execution was blocked by the environment's missing PyYAML dependency.

Findings: none.

_links_to_repository_doc accepted any destination whose path ended with
the required relative path, so docs/OTHER_SUPPORT.md satisfied the
SUPPORT.md requirement and the public-docs-linked-from-readme check
could pass on a README that never links the real file.

Accept a destination only when its path is exactly the relative path or
ends with "/" + the relative path. Both spellings the check exists for
still pass: the relative form in the repository README and the absolute
GitHub blob URL the packaged long description needs. Query strings are
now dropped alongside fragments, since neither changes which file the
destination resolves to.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@jeffhuber

Copy link
Copy Markdown
Contributor Author

Codex audit (merge-authority lane)

Head SHA: 58976cc7700f354f7ad9a09de59cc25cbc39eec7
Findings: P0=0, P1=0, P2=1, P3=0 (blocker policy: any P0/P1/P2 → BLOCKED)

Codex Audit: BLOCKED

Summary:

The release-readiness change introduces a confirmed false-positive for broken documentation links. Focused tests could not run because PyYAML is unavailable in the environment.

Findings:

  • [P2] Validate the repository destination instead of its suffix -- /private/var/folders/f2/g9zqfdjx7z3ckcsx_f46htwm0000gn/T/codex-audit-y2g7nmpt/wt/src/code_mower/release_readiness.py:127
    Finding ID: codex:411aa6fbe75c24caa769
    A README link such as [Support](docs/SUPPORT.md) now passes this check even though that file does not exist; an unrelated website ending in /SUPPORT.md also passes. This lets public-docs-linked-from-readme report success without linking the required repository document. Normalize relative destinations and explicitly recognize the repository's absolute GitHub URLs rather than accepting any matching suffix.

The path-segment boundary added in 58976cc still let two destinations
satisfy the public-docs-linked-from-readme check without addressing the
required file: a nested relative path that does not exist in this tree,
such as docs/SUPPORT.md for SUPPORT.md, and any unrelated absolute URL
whose path ends in /SUPPORT.md, including another owner's or another
repository's GitHub URL.

Resolve the destination to the one repository-relative path it lands on,
then require that path to equal the required document. A relative
destination is normalized against the repository root, where README.md
sits, so docs/SUPPORT.md resolves to itself and no longer matches. An
absolute destination resolves only when it is this repository's own
GitHub URL -- github.com/codemower-ai/code-mower/{blob,raw}/<ref>/<path>
-- reduced to the path under its ref; every other host, owner, and
repository resolves to nothing. Query strings and fragments are still
dropped first, since neither changes which file is addressed.

A site-root /SUPPORT.md no longer passes. GitHub does not resolve a
site-root path against the repository, so that spelling was a broken
link the check was accepting; nothing in this repository uses it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@jeffhuber

Copy link
Copy Markdown
Contributor Author

Codex audit (merge-authority lane)

Head SHA: 05b01f5c698c16669912ac5dfaa0d19721e02408
Findings: P0=0, P1=0, P2=0, P3=0 (blocker policy: any P0/P1/P2 → BLOCKED)

Codex Audit: PASS

Summary:

No actionable regressions were identified. Test execution was blocked by sandbox restrictions and the missing PyYAML dependency.

Findings: none.

@jeffhuber

Copy link
Copy Markdown
Contributor Author

Owner gate reconciliation for exact head 05b01f5c698c16669912ac5dfaa0d19721e02408:

  • The independent full-diff Codex merge-authority audit passed with P0=0, P1=0, and P2=0: Docs: reconcile published v1.4.2 guidance and the post-release Graphify boundary #1009 (comment)
  • Code Mower CI run 35198726437 is fully green, including Python 3.12/3.13/3.14, Board qualification, release readiness and installation rehearsals, and Linux/macOS graph containment.
  • The operator-authored PR identity and builder:claude label leave the gate in identity_branch_conflict; the same authorized orchestrator supervised the Claude writer and the separate Codex exact-head audit, and a producer-backed lineage episode cannot be created retroactively for this immutable head.
  • No audit finding or failing check is being waived. The owner override reconciles this metadata-only lineage gap for the current immutable head only.

@jeffhuber jeffhuber added the gate:override Code Mower generated label label Sep 17, 2026
@jeffhuber
jeffhuber merged commit 5272bfe into main Sep 17, 2026
16 checks passed
@jeffhuber
jeffhuber deleted the claude/1008-v142-docs-audit branch September 17, 2026 08:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

builder:claude Code Mower generated label gate:override Code Mower generated label needs-codex-audit

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Docs: reconcile published v1.4.2 installation, roadmap, and qualification guidance

1 participant