Skip to content

fix(hydra-gates): step over whole PHP attributes when walking up to a docblock - #900

Open
rubenvdlinde wants to merge 1 commit into
mainfrom
fix/gates-docblock-walk-attribute-blocks
Open

rubenvdlinde wants to merge 1 commit into
mainfrom
fix/gates-docblock-walk-attribute-blocks

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

Seven gates walk up from a method declaration to its docblock and skip PHP attributes on the way by line prefix (#[, in some also ] or )]). That only recognises a one-line attribute. A multi-line attribute, several stacked ones, or a closing line with a trailing comment stops the walk, and an existing docblock reads as missing.

dossiq#5151 reported this as a gate 16 false red on #[McpTool(...)]. On current main, gate 16 does not produce that finding: #811 already steps over one multi-line attribute, and running check_spec_coverage.py from main on the dossiq branch gives # count=0. The lane ran its local diff check against the vendor/ copy, conduction/hydra-gates v1.16.1 (7 Sep), which predates #811. The gap is real all the same. Gate 16 still stopped on attributes stacked on one line and on comments inside or after an attribute, and the other six walkers had no handling at all.

What changes

  • New scripts/lib/php_attributes.py. attribute_block_start(lines, end) finds the nearest #[ line at or above end. It accepts the span only when, read as PHP, it is one or more complete attributes followed by nothing but whitespace or comments, with the last attribute closing on line end. "Complete" means brackets and parentheses are balanced, with strings (escapes included) and //, # and /* */ comments skipped. Anything else returns None, and the caller's walk stops as before.
  • These walkers use it: gate 16 check_spec_coverage, gate 6 check_orphan_auth, gate 25 check_contract_coverage (both the docblock walk and the auth preamble), gate 17 detect-redundant-controllers, gate 61 check_listener_placement, gate 57 check_orphaned_write_capability, and the gate 3 caller-identity arm check_caller_identity_exempt.
  • Gate 16's own bracket counter from fix(gate-16): step over a multi-line PHP attribute to reach the docblock #811 is replaced by the shared reader. The loose ] and )] prefix skips are gone: those lines are now judged structurally.

Verified

  • New fixtures in test_check_spec_coverage.py:
    • the dossiq #[McpTool(...)] with @spec passes, and without @spec still fails;
    • a string holding )] on its own line;
    • stacked multi-line attributes, including )] #[NoCSRFRequired] on one line;
    • inner and trailing //, # and /* */ comments;
    • a control that still fails without @spec.
  • New test_php_attributes.py runs every walker over the same four shapes, plus a no-docblock control for each. Its reader controls cover an array close, an unclosed attribute, a one-line /** @var int[] */ below an attribute, and code after a close.
  • Red before the fix: against main's walkers the new suite fails 27 subtests, and the two new gate 16 fixtures (stacked, comments) fail.
  • Green after: test_php_attributes 14, test_check_spec_coverage 90, test_check_contract_coverage 23, test_check_orphaned_write_capability 72, test_check_listener_placement 50, test_check_orphan_auth 29, test_detect_redundant_controllers 10, test_check_stub_run_body 20, test_checker_patterns_match_documented_shapes 13, and test_exclusion_reason{,_adjacent}. All exit 0.
  • Shell suites that run these checkers, all exit 0: test_gate16_spec_coverage_scope, test_gate_3_contract_param, test_gate_3_bodiless_declaration, test_gate_3_external_contract_and_tabs, test_gate_3_14_comment_evidence, test_gate_crashed_checker_is_not_a_finding, test_gate_1_11_honest_verdicts, test_gate_or_objectservice_surface.
  • Not run locally: the other helper suites. CI's Package invariants runs them all.

Not handled: an attribute whose closing line is also the declaration line ()] public function f()), and attributes longer than 200 lines. In both cases the walk stops as it did before.

AI disclosure: prepared with Claude Code (Opus 5.5).

🤖 Generated with Claude Code

… docblock

Seven docblock walks skipped only lines starting with `#[` (some also `]`
or `)]`). A multi-line attribute, stacked attributes, or a closing line
with a trailing comment stopped the walk, so an existing docblock read as
missing. Gate 16 already had a bracket-counting step for one multi-line
attribute (#811); it did not handle comments or attributes stacked on one
line, and the other six walkers had nothing.

php_attributes.attribute_block_start reads the span as PHP: it finds the
nearest `#[` line, requires one or more complete attributes (brackets
balanced outside strings and comments) with only whitespace or comments
after them, and the last one closing on the line the walk is at. All seven
walkers (gates 16, 6, 25, 17, 61, 57 and the gate 3 caller-identity arm)
use it.

Refs ConductionNL/dossiq#5151

Assisted-by: ClaudeCode:claude-opus-5-5

This branch has not been deployed

No deployments
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