Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,25 @@
* Warn when a PHP class or public method lacks an @spec PHPDoc tag.
*
* ConductionNL ADR-003 (Backend rules) mandates that every class and public
* method MUST have one or more @spec PHPDoc tags linking back to the OpenSpec
* change that caused the code to exist:
* method MUST have one or more @spec PHPDoc tags linking back to the
* requirement the code exists to satisfy:
*
* @spec openspec/changes/{change-name}/tasks.md#task-N
* @spec openspec/specs/{capability}/spec.md#requirement-{slug}
*
* POINT AT THE CANONICAL SPEC, NOT AT A CHANGE DIRECTORY.
*
* This guidance used to read `openspec/changes/{change-name}/tasks.md#task-N`,
* and tags written to it dangle by construction: `openspec/changes/<name>/` is
* temporary — archiving moves it to `openspec/changes/archive/<date>-<name>/`,
* and renaming or dropping a change removes the target outright. Gate-46
* (spec-anchor-existence) then reports the tag, and the developer who wrote it
* had followed this sniff's own instruction. Measured on portaliq 2026-08-08:
* 100 unresolved targets, with 260 of its 385 live tags pointing into a change
* directory. The cross-repo measurement is in ConductionNL/.github#228.
*
* An `openspec/changes/...` target is still ACCEPTED — this sniff only checks
* that a tag is PRESENT, and gate-46 resolves archived paths — but it is no
* longer what this sniff tells you to write.
*
* This sniff emits warnings (not errors) so that CI surfaces the gap without
* blocking merges while teams backfill coverage. Tests files and magic
Expand Down Expand Up @@ -130,7 +145,7 @@ private function processClass(File $phpcsFile, int $stackPtr): void
return;
}

$message = 'Class %s is missing @spec PHPDoc tag — link back to openspec/changes/{name}/tasks.md#task-N';
$message = 'Class %s is missing @spec PHPDoc tag — link back to openspec/specs/{capability}/spec.md#requirement-{slug}, not a change dir';
$phpcsFile->addWarning($message, $stackPtr, 'MissingClassSpec', [$className]);

}//end processClass()
Expand Down Expand Up @@ -179,7 +194,7 @@ private function processFunction(File $phpcsFile, int $stackPtr): void
return;
}

$message = 'Public method %s::%s() is missing @spec PHPDoc tag';
$message = 'Public method %s::%s() is missing @spec PHPDoc tag — link back to openspec/specs/{capability}/spec.md#requirement-{slug}';
$phpcsFile->addWarning($message, $stackPtr, 'MissingMethodSpec', [$className, $methodName]);

}//end processFunction()
Expand Down
Loading