Repository navigation
governance: contribution harness, decisions register and Watchdog - #38
Conversation
…drift check The shared block now states every rule with its enforcement (gate, template or named decider), covering sources of record, contracts, tests, evidence, dependencies, safety, publication, agents, failure and learning. Internal document links and personal names are removed from AGENTS.md. check_agent_rules.py reads the marker version from the canonical file so repositories on v1 fail with a version message. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TPiK6pUmmjNhPceECkKpR2 Signed-off-by: Alex Reznichenko <info@botshare.ai>
decisions.yaml holds decided values with source, supersedes history, applies_to globs, machine checks and an owner role. It is seeded from P-03 rev18.1, P-00 rev18.1 and the BOM as quoted in the 28 September alignment audit and from P-03 rev18.2 as cited by the docs site. maintainers.yaml maps roles to handles, audit prefixes and safety paths. check_decisions.py validates the schema, scans Markdown, YAML, launch, URDF/Xacro, package.xml and README files and reports file, line, found and decided value; tested against a fixture repository. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TPiK6pUmmjNhPceECkKpR2 Signed-off-by: Alex Reznichenko <info@botshare.ai>
Fails on Google Drive and Docs links, e-mail addresses, phone numbers, prices with currency symbols or codes and credential-like strings in docs/, assets/, README.md and any path containing public. Allowlist entries need a rule, a match, optional path and repository scope and a reason. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TPiK6pUmmjNhPceECkKpR2 Signed-off-by: Alex Reznichenko <info@botshare.ai>
The template carries the sections the checker reads: work package, Integration Gate, tests, evidence with base and head SHA and commands, dependencies, safety impact, STATE.md, Not verified and AI disclosure. The checker fails on missing or empty sections, a test change without a non-zero reported run, a dependency manifest change without a Dependencies entry, an unexplained STATE.md, and safety-path changes without two human reviewers including the platform lead or with AI authorship. It keeps one summary comment per PR, updated in place. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TPiK6pUmmjNhPceECkKpR2 Signed-off-by: Alex Reznichenko <info@botshare.ai>
Follows openamrobot-interfaces/tools/verify.sh (clean environment, run directory, result file) and delegates to a repository's own tools/verify.sh when one exists. Adds project detection, a zero-tests executed failure, a rule that skip, xfail and importorskip name a tracking issue, and summary.json evidence with SHAs and test counts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TPiK6pUmmjNhPceECkKpR2 Signed-off-by: Alex Reznichenko <info@botshare.ai>
…rkflow Pull requests check changed files and block. Pushes scan the full checkout and report warnings; the weekly audit owns the backlog. The harness ref is an input so callers can pin it with the uses: line. This repository also runs every checker's tests through verify.sh. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TPiK6pUmmjNhPceECkKpR2 Signed-off-by: Alex Reznichenko <info@botshare.ai>
Bug report asks for repository, SHA, exact commands and Not verified. The interface change request becomes the contract change request and covers topic names, launch argument names and configuration IDs. New forms: harness mistake (label harness, feeds the monthly retro) and good first issue (area, done-when, verify command, reviewer role). agent-prompts/ holds read-only audit, push from bundle, docs fix and evaluator pass, each with a precondition block, an expected outcome and the failure rule. Structural tests cover all of them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TPiK6pUmmjNhPceECkKpR2 Signed-off-by: Alex Reznichenko <info@botshare.ai>
Plans issues from an audit ISSUES.csv: one issue per Blocker or Major finding without an issue, in the repository named in file_to_change, owner from maintainers.yaml by ID prefix; closes open audit issues whose finding is resolved or absent. Public issues carry only ID, severity, area, paths and owner handle; full text goes only to the private fallback repository. Dry run on the 28 September audit plans 82 issues, 45 in public repositories. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TPiK6pUmmjNhPceECkKpR2 Signed-off-by: Alex Reznichenko <info@botshare.ai>
…flows pr-assistant.yml runs check_decisions.py and check_pr_evidence.py on the diff under pull_request_target, never executing PR code, and keeps one summary comment; it never approves or merges. The weekly audit, docs sync (sender and receiver) and monthly retro run the Claude Code action pinned to v1.0.236 by commit SHA with restricted tools. SETUP.md lists secrets, App permissions, labels and branch protection for the organization owner and states which parts ran here. The reusable workflow gains an opt-in quality/test job that calls verify.sh; VERIFY.md documents it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TPiK6pUmmjNhPceECkKpR2 Signed-off-by: Alex Reznichenko <info@botshare.ai>
CONTRIBUTING.md is the contributor path: finding a task, fork and branch per work package, DCO, the draft PR, what each check verifies, draft to ready and who reviews what. rollout/README.md gives adoption order per repository, the release-manifest interaction and the CODEOWNERS proposal. agent-runs.md records the audit and its follow-ups with the harness change that now catches each mistake class. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TPiK6pUmmjNhPceECkKpR2 Signed-off-by: Alex Reznichenko <info@botshare.ai>
check_decisions.py flagged rollout/README.md for quoting the legacy compute name as found text; refer to the decision ID instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TPiK6pUmmjNhPceECkKpR2 Signed-off-by: Alex Reznichenko <info@botshare.ai>
decisions.yaml is the register of approved technical decisions; process stays in AGENTS.md. Each entry now states kind (value, configuration, limit, exclusion, distinction), scope as repositories and file globs, provenance, supersession and a verification method: what the text scan detects and which human reviewer checks what evidence. Adds the distinction and exclusion entries: 1700 mm is the assembled-height envelope, no suspension, no RS485, no dock contacts or pilot, no lift, docking never establishes charging, telemetry is never safety evidence. P-03 rev18.2 and BOM Issue 7 are recorded as seed evidence only; CI reads only the pinned register and fetches nothing. check_decisions.py validates the new fields, detects text that still cites a superseded source, counts files it did not scan, states that a clean result is textual consistency only, and never writes. Fixtures cover a matching value, a contradicting value, an unlisted file type and a superseded citation. Test strings are synthetic. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TPiK6pUmmjNhPceECkKpR2 Signed-off-by: Alex Reznichenko <info@botshare.ai>
The check reports "safety path touched, two human approvals required", fails only when fewer than two human reviewers (including the platform lead) are requested, and counts approvals for information. Approvals themselves are a ruleset requirement. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TPiK6pUmmjNhPceECkKpR2 Signed-off-by: Alex Reznichenko <info@botshare.ai>
…tices Replaces the path-wide vendored-file entry with a line condition: an e-mail address is allowed only on a licence, copyright or author notice line, plus the organization contact and placeholders. Handles are not e-mail addresses. Test URLs are assembled at run time. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TPiK6pUmmjNhPceECkKpR2 Signed-off-by: Alex Reznichenko <info@botshare.ai>
sync_audit_issues.py no longer closes issues. For a finding a run no longer reports, it comments "no longer detected" once and leaves closure to the owner. Tests use synthetic IDs. Every file under rollout/workflows states that it is an example or design, not installed and not run. SETUP.md classifies every check and workflow as implemented and tested here, rollout example, or human gate, and lists the per-repository rulesets that supply safety-path approvals. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TPiK6pUmmjNhPceECkKpR2 Signed-off-by: Alex Reznichenko <info@botshare.ai>
Existing callers reference @main. The decisions, public-extract and drift steps now run only with harness_checks: true, so merging this changes nothing in other repositories until each opts in during rollout. This repository's own caller opts in. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TPiK6pUmmjNhPceECkKpR2 Signed-off-by: Alex Reznichenko <info@botshare.ai>
AGENTS.md separates process from the decisions register and adds "Changing a decision": change request, source document first, one reviewed PR for register and consumers, owner approval, no tool rewriting either side. Labels now say check only where a checker detects the violation, and human with the reviewer and evidence otherwise. The contract change request form asks for the register entry and points to that process. CONTRIBUTING.md and the rollout plan say checks block merges only once installed and required. agent-runs.md records sanitized failure categories only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TPiK6pUmmjNhPceECkKpR2 Signed-off-by: Alex Reznichenko <info@botshare.ai>
Running the check on this PR's own description reported a fixture package.xml under tests/fixtures as a dependency change. Paths under fixtures/ or testdata/ are now ignored for the Dependencies rule. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TPiK6pUmmjNhPceECkKpR2 Signed-off-by: Alex Reznichenko <info@botshare.ai>
- decisions.yaml: P-03 rev18.2 is the addendum in force. BOM-ISSUE-IN-FORCE is recorded as Issue 7 (P-03 rev18.2 item 7), superseding Issue 6 (P-03 rev18.1 line 7) and B-01, with checks for Issue 6 or B-01 presented as canonical and for citations of the superseded line. - ROADMAP.md: the 2.0 compute is the Jetson Orin NX on the reComputer Robotics J401; the Raspberry Pi is legacy, Gate A only. - profile/README.md: fixed mast, lift deferred to OpenAMRobot 3.0; the imprint uses the organization contact address. - public-extract-allowlist.yaml: documented entries for the public sponsorship tiers in README.md and the robot prices in the profile, scoped to this repository and those files. - maintainers.yaml: ci-owner, release-owner and docs-owner handles left empty, filled by the organization owner. - Tests for the BOM entry and the pricing entries; agent-runs.md and SETUP.md updated to match. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TPiK6pUmmjNhPceECkKpR2 Signed-off-by: Alex Reznichenko <info@botshare.ai>
Sets release-owner to KARTHIKEYAN124 as instructed by the platform lead. ci-owner and docs-owner stay empty until their handles are supplied. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TPiK6pUmmjNhPceECkKpR2 Signed-off-by: Alex Reznichenko <info@botshare.ai>
…ity/test quality/test failed in the lint stage of rollout/verify.sh: the runner image ships shellcheck, which flagged the unquoted assignment stage=test (SC2209). The local session had no shellcheck, so the stage was skipped there. Quote the assignment and install shellcheck in the job when missing so the lint stage runs the same way everywhere. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TPiK6pUmmjNhPceECkKpR2 Signed-off-by: Alex Reznichenko <info@botshare.ai>
…tatus On the runner (Python 3.12+) unittest exits 5 when no tests run, and the test stage aborted under set -e before the zero-tests check, so an empty suite failed as "FAIL: test (exit 5)" instead of "zero tests executed" and test_zero_tests_fail failed. The stage now records the command's status, applies the zero-tests rule first, then fails on any non-zero status. Adds a test that a failing test fails the stage. Checked with Python 3.11, 3.12 and 3.13. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TPiK6pUmmjNhPceECkKpR2 Signed-off-by: Alex Reznichenko <info@botshare.ai>
panthera-momagdii
left a comment
There was a problem hiding this comment.
Reviewed the software-lead sections: shared agent rules, decisions register, PR assistant/evidence checker and reviewer roles. The overall model is useful and the current repository-quality checks are green, but I found two fail-open cases in the proposed PR assistant that should be fixed before adoption.
-
rollout/workflows/pr-assistant.ymlbuildschanged.txtwithselect(.status != "removed"). That means deleted files disappear fromcheck_pr_evidence.py. A PR deleting a dependency manifest or a safety-path file can therefore bypass the dependency/safety-path review rules. Keep all changed filenames for evidence/safety/dependency checks. Ifcheck_decisions.pyonly wants files that still exist in the PR head, use a second filtered list for that checker. Add regression coverage for deletion of a safety-path file and a dependency manifest. -
The decision-check step uses
set +e, writes only stdout todecisions.txt, prints the exit code, and then continues.check_pr_evidence.pyonly fails onCONTRADICTIONorINVALID decisions filetext. Ifcheck_decisions.pycrashes or exits unexpectedly with no recognized stdout, the PR assistant can still PASS. Capture the exit status explicitly and make any unexpected/non-policy checker failure fail closed. Add a regression for a checker error/exception path.
The pull_request_target design itself is appropriately cautious: trusted harness checkout, PR head treated as data, no PR code execution, and only the repository token is used. The current software-lead reviewer assignments in decisions.yaml for IMU topic ownership, NAV-LIDAR, docking semantics and camera integration are reasonable.
Please fix the two fail-open cases and tag me again.
The workflow built changed.txt with select(.status != "removed"), so a PR that only deleted a dependency manifest or a safety-path file never reached check_pr_evidence.py. It now writes two lists from the PR files API: changed_all.txt (every filename, including removed files and the previous name of a rename) for the evidence, safety-path and dependency rules, and changed_existing.txt (files present at the PR head) for the decisions scan only. Regression tests: deleting a safety-path file and deleting a dependency manifest are both flagged, and a test runs the workflow's own jq commands on a sample payload and checks which list each checker gets. The wiring test fails against the previous workflow. Reported by the software lead in review. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TPiK6pUmmjNhPceECkKpR2 Signed-off-by: Alex Reznichenko <info@botshare.ai>
The decisions step ran check_decisions.py under set +e, kept only stdout and continued; check_pr_evidence.py failed only on CONTRADICTION or INVALID decisions file lines, so a crash, an empty output or an unexpected exit code produced PASS. The workflow now records the exit status in decisions-status.json and captures stdout and stderr. check_pr_evidence.py takes --decisions-status and accepts only the two documented outcomes: exit 0 with a clean result line, and exit 1 with CONTRADICTION lines matching the reported count. Everything else (traceback, exit 2, any other code, empty output, a missing or unreadable status or report file) is a checker error: the summary comment says CHECKER ERROR and the check exits 1. Regression tests: a real check_decisions.py exception, a synthetic traceback, non-zero exit with empty output, exit 0 without a result line, exit 2, mismatched counts, missing status file, missing report file, and the workflow's own decisions step run with a crashing checker. They fail against the previous checker, which returned PASS for a crash and for empty output. Reported by the software lead in review. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TPiK6pUmmjNhPceECkKpR2 Signed-off-by: Alex Reznichenko <info@botshare.ai>
|
@panthera-momagdii thanks for the review (#38 (review)). I fixed both fail-open cases in new commits; nothing was rebased or squashed. 1. Deleted files bypassed the checks. Fixed in ac95067.
2. Checker errors passed silently. Fixed in a49c513.
Verification
The PR body's Evidence and What changed sections are updated. Generated by Claude Code |
|
Reviewed the release/installation sections at a49c513.
|
…pilot Review by the release and installation owner: SETUP section 1 enabled harness_checks: true while rollout step 2 required the shared rules v2 first, so the prerequisites contradicted each other. Per repository the order is now (a) shared rules v2, (b) pin the harness, (c) warn-only on main until a green run, (d) harness_checks: true, (e) require the checks in the ruleset. SETUP section 1 no longer enables the checks; it points to that order. Step (c) needed a mechanism: the reusable workflow gains harness_warn (default false), which runs the decisions, public-extract and drift steps and reports every finding as a warning without failing. harness_checks stays the enforcing switch and wins if both are set. The check steps take event, repository and mode from environment variables, and a new test runs the workflow's own step scripts in both modes. openamrobot-interfaces is the pilot: it completes (a) to (e) before any other repository enables the harness, with eight recorded exit criteria accepted by the CI owner and the release owner. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TPiK6pUmmjNhPceECkKpR2 Signed-off-by: Alex Reznichenko <info@botshare.ai>
Exercise the issue-only publisher's PATCH/ comment path and ensure it never closes issues automatically. Signed-off-by: Alex Reznichenko <info@botshare.ai>
The repository variable WATCHDOG_ISSUE_MODE selects what the organization scan writes. Unset or "dashboard" (default): only the single "[watchdog] Organization dashboard" issue, edited in place when its content changes, listing every active group with repository, check, group, finding count, owner and file links. "groups": today's behaviour, one deduplicated issue per active group plus the dashboard. Scan-blocked repositories always appear on the dashboard. Any other value stops the sync with exit 2. The workflow passes vars.WATCHDOG_ISSUE_MODE; WATCHDOG.md explains how to turn on per-group issues and that the platform lead decides when. Tests cover both modes and the unset default; with the default flipped to groups 5 tests fail, against the previous tool 13 fail. Signed-off-by: Alex Reznichenko <info@botshare.ai> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DeSLcD827exxSw3xL9zyiU
2829903 to
43f2804
Compare
Review-gate refresh — current head
|
Signed-off-by: Alex Reznichenko <info@botshare.ai>
Signed-off-by: Alex Reznichenko <info@botshare.ai>
WATCHDOG.md, rollout/workflows/SETUP.md and the workflow header comment now say the organization scan runs every Thursday at 14:00 Europe/Berlin (following daylight saving time) plus manual dispatch. SETUP.md also states that only the dashboard issue is written while WATCHDOG_ISSUE_MODE is unset. Signed-off-by: Alex Reznichenko <info@botshare.ai> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DeSLcD827exxSw3xL9zyiU
b562360 to
18d8a2b
Compare
Current-head review gate —
|
The job summary said findings are synchronized to deduplicated issues, which is wrong in the default dashboard mode. It now says results are published to the [watchdog] Organization dashboard issue in the harness repository, with per-group issues only when WATCHDOG_ISSUE_MODE is groups. The scan-step test asserts the new line and the absence of the old one; against the previous workflow it fails (1 failed, 5 passed). Signed-off-by: Alex Reznichenko <info@botshare.ai> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DeSLcD827exxSw3xL9zyiU
|
Platform-lead source reconciliation, head 8ecda44. This is the final head for review. I checked every decisions.yaml entry against P-03 Decision Addendum rev18.7 (6 October 2026), the addendum in force, with BOM Issue 7.3 as the canonical BOM. LIFT, the three superseded mast entries, MAX-ASSEMBLED-HEIGHT, DATUM-HEIGHT-STACK, FRAMES-REP105, BATTERY-PLACEMENT, BASE-CONTROLLER-IO, CAMERAS, HEAD-CAMERA-IDENTITY and BOM-ISSUE-IN-FORCE match rev18.7. NAV-LIDAR (item 13) and RELEASE-MILESTONES (item 12) are unchanged and current. The register checks textual consistency only; it is not mechanical, electrical, safety or release evidence. Merging activates the Watchdog scan (Thursday 14:00 Berlin) in dashboard-only mode, which I accept. As the author, this is my statement, not an approval. |
panthera-momagdii
left a comment
There was a problem hiding this comment.
Software-lead final review on current head 8ecda442f0d7dfcfa4b48b4258386efdb52bd44c: APPROVE for the software-lead scope.
I re-read agent-rules/SHARED_RULES.md and the current decisions.yaml against the current platform baseline. The source-of-truth boundary remains clear: process rules live in the harness, approved technical values live in the register, contract changes stay proposed until owner acceptance, safety/telemetry boundaries remain human-gated, and the earlier deleted-file / fail-closed evidence-check fixes remain intact.
The current register is aligned with the supplied P-03 rev18.7 baseline, including the lift replacing the fixed mast, datum/frame updates, battery placement, STM32H723ZG base-controller I/O, ZED Mini / Gemini camera decisions, RPLIDAR S3 and the release milestones. The checks explicitly claim textual consistency only, not mechanical, electrical, safety or physical acceptance.
I also inspected current-head Repository quality run 37703495722, which is green. GitHub's current Actions documentation supports the IANA timezone field used for the Thursday Europe/Berlin schedule. The installed Watchdog is deterministic/read-only with respect to product repositories and does not activate the AI workflows; #43 remains the separate activation gate.
This approval does not replace the current-head CI/CD, documentation or release-owner reviews and is not an organization-wide rollout or physical-acceptance approval. No merge performed.
KARTHIKEYAN124
left a comment
There was a problem hiding this comment.
Release-owner review at 0329752: APPROVE / ADOPT for my scope.
I reconfirm the Thursday 14:00 Europe/Berlin Watchdog schedule with manual dispatch, the interfaces-first pilot, staged rollout, matching full-SHA harness pins, and release evidence requirements. Historical evidence remains preserved.
This approval covers 0329752 only. Fresh CI-owner approval, required checks, DCO/CLA, source reconciliation, and final platform-lead sign-off remain separate merge gates.
wikki26
left a comment
There was a problem hiding this comment.
CI/CD owner review — ADAPT / REQUEST CHANGES on head 8ecda44.
I reviewed the Watchdog scan workflow and its reporting/issue-sync integration. Good boundaries: read-only product repository checkouts; only central issues:write; pinned external actions; dashboard-only default; explicit handling of clone failures; tests for issue deduplication and the clone-failure path.
One reliability issue to address before my CI approval:
In .github/workflows/watchdog-org-scan.yml, the "Scan repositories" bash step uses set -uo pipefail (no errexit). Failures in initialization/list generation or in the JSON enrichment, total calculation, and summary-writing commands are not all explicitly checked. For example, if generating $WORK/list.txt fails, the loop can execute zero times, blocked stays 0, and the step can finish successfully. The subsequent if: always() issue-sync step accepts an empty set of reports/blocked records and may replace the dashboard with an apparently empty result. That is not a trustworthy complete 14-repository scan.
Please fail closed for setup/report-generation errors (use guarded commands and robust error handling), and ensure an incomplete scan is explicitly marked BLOCKED/INCOMPLETE rather than published as a clean complete result. Add regression coverage for a failed repository-list generation and a report-generation/enrichment failure; verify the job fails and dashboard reporting never silently treats missing repositories as clean.
This is scoped to the installed Watchdog workflow. I have inspected the code and relevant tests, but have not independently executed the hosted scan or full ROS suite. After this fix and green current-head evidence, I can re-review promptly. I am not authorizing a merge or AI-workflow activation.
Resolves the CI/CD owner review of 8 October on 8ecda44. Scan step: set -euo pipefail with an EXIT trap that marks any unexpected stop INCOMPLETE. Repository list generation (tools/watchdog_scan_support.py list) stops the step on failure, always writes expected.json first, and the step fails when list.txt is empty or shorter than repositories.yaml. Clone, rev-parse, watchdog.py, report enrichment and the finding total are guarded per repository: a failure records the repository in blocked.json with its reason, sets the report aside and continues. After the loop every expected repository without a report or blocked entry is BLOCKED as "no report produced". The summary heading says COMPLETE only when every expected repository was scanned, otherwise "INCOMPLETE: N of M repositories scanned", and the job fails. Issue sync: new --expected (passed by the workflow). Missing repositories and malformed reports are BLOCKED, never clean; the dashboard opens with the INCOMPLETE banner; findings and issues of repositories that were not scanned are never cleared (last known rows stay on the dashboard); an unreadable expected list posts only an INCOMPLETE notice without overwriting the dashboard. The sync exits non-zero on any incomplete run. Tests: 14 new regression tests (scan step with the fake-git harness, sync planning and API calls); 15 tests fail on 8ecda44. WATCHDOG.md gains an "Incomplete scans" section; the workflow header comment matches. Schedule (Thursday 14:00 Europe/Berlin) and default issue mode (dashboard) are unchanged; no decisions.yaml value changed. Signed-off-by: Alex Reznichenko <info@botshare.ai> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DeSLcD827exxSw3xL9zyiU
37896d3
… scan With repositories: [] the scan step writes an INCOMPLETE summary and exits non-zero, expected.json is an empty list, and the issue sync treats that empty expected list as unreadable (exit 1, no clean dashboard). On 8ecda44 the same step exited 0 (assertion 0 == 0). Signed-off-by: Alex Reznichenko <info@botshare.ai> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DeSLcD827exxSw3xL9zyiU
|
Current-head gate, 2151010: the CI/CD review of 8 Oct (fail-closed scan) is addressed. An incomplete or failed scan is now marked BLOCKED/INCOMPLETE, the job fails, and the dashboard never treats missing repositories as clean. The mapping from review requirement to change and test is in the PR description under "CI/CD review of 8 Oct". Approvals on earlier heads do not carry over, so fresh reviews are needed on this head from @wikki26 (CI/CD), @panthera-momagdii (software lead, required for platform-lead-authored PRs), @anandgawai123456-glitch (docs) and @KARTHIKEYAN124 (release). |
panthera-momagdii
left a comment
There was a problem hiding this comment.
Fresh software-lead review on current head 21510107706bae7893d22c79038529d27ec54e48: approved for the software-lead scope. Since my prior approval at 8ecda44, the new commits are confined to the Watchdog workflow/support/reporting/tests; agent-rules/SHARED_RULES.md and decisions.yaml are unchanged. The current repository-quality run is green. CI/CD owner re-review of the fail-closed scan remains a separate required gate, along with release/platform sign-off. No merge performed.
KARTHIKEYAN124
left a comment
There was a problem hiding this comment.
I reconfirm the interfaces-first pilot, staged enforcement, matching full-SHA harness pins, and traceable release evidence. Incomplete scan evidence must not satisfy release acceptance, and historical evidence must remain preserved.
Independent inspection of the current-head changes, regression tests, and hosted checks is still pending, so this comment does not constitute a fresh approval. Earlier approvals do not carry over. Required owner reviews, checks, DCO/CLA, source reconciliation, and platform-lead sign-off remain merge gates.
wikki26
left a comment
There was a problem hiding this comment.
Re-reviewed the updated implementation at commit 2151010.
The changes address my previous fail-open concerns around incomplete organization scans and misleading clean results.
Independent verification completed:
- Watchdog issue-sync: 24/24 tests passed (Python 3.11).
- Organization-scan regression tests: 12/12 passed (Ubuntu WSL2, Python 3.12).
- Confirmed handling of missing/invalid repository lists, incomplete scans, blocked repositories, and preservation of existing findings.
The earlier review concerns are resolved based on the implementation and regression tests. Approved from the CI/CD and quality perspective.
Summary
This PR adds the OpenAMRobot contribution and agent harness to openAMRobot/.github:
It follows the principle agent = model + harness. Every rule is labelled in one of three ways:
The checks block a merge in another repository only after that repository opts in (
harness_warn, thenharness_checks) and its ruleset requires them, which is the rollout described inrollout/README.md. What merging this PR changes elsewhere without any opt-in is listed under "Repositories affected on merge".The OpenAMRobot Watchdog
The Watchdog is the deterministic check layer of this harness: it compares every repository with the approved decisions in
decisions.yamland with the public-extract, shared-rules and workflow-pinning rules, and tells the contributor what was found, why it matters and exactly how to fix it. It uses no AI, reads files only, and proves textual consistency only, never safety, electrical, mechanical or release correctness.tools/watchdog_scan_support.pyholds the fail-closed steps of the organization scan (repository list, BLOCKED records, report enrichment, completeness check);tools/watchdog.pyruns every repository check against one checkout (python3 tools/watchdog.py --root ../openamrobot-docs);tools/watchdog_report.pyis the shared output (guidance once per decision, then each finding asfile:line; inline annotations and a Markdown job summary in GitHub Actions; full detail per finding in JSON);tools/watchdog_issue_sync.pypublishes the organization result as GitHub issues..github/ISSUE_TEMPLATE/decision_review.yml("Decision register review") for confirming or changing onedecisions.yamlentry after a review reminder; the register is still changed only through a reviewed pull request..github/workflows/watchdog-org-scan.yml:cron: "0 14 * * 4"withtimezone: "Europe/Berlin", so it follows daylight saving time) plus manual dispatch;--depth 1clones of the default branch of each repository inrollout/repositories.yaml(14 repositories);contents: readandissues: writeonly;decisions.yaml;WATCHDOG_ISSUE_MODEunset, it creates or updates in place only the single "[watchdog] Organization dashboard" issue, which lists every active group (repository, check, group, finding count, owner, file links) and every scan-blocked repository.WATCHDOG_ISSUE_MODE=groupsadds one deduplicated issue per group; the platform lead decides when to switch;A dashboard row group reads like the terminal output:
Work package
No work-package issue exists. The task came directly from the platform lead and is scoped to openAMRobot/.github; changes needed in other repositories are delivered as files under
rollout/.What this closes
The table lists the recurring failure classes in the 28 September alignment audit, grouped by ID prefix. None of the audit's content was copied into this repository. For each class the table gives the rule and the state of the mechanism that addresses it:
A text check proves textual consistency with the register only, never mechanical, electrical or safety correctness.
harness_refpinning (b); licence map (c)verify.shzero-test and skip-issue rules (a); thequality/testjob in callers (b)verify.sh(a);check_pr_evidence.pyfor sections, SHAs, commands and counts (a) as installed bypr-assistant.yml(b); whether commands were really run: reviewer (c)maintainers.yaml(a); CODEOWNERS proposal inrollout/README.md(b); drift check (a)check_public_extract.py(a) under the canonical documentation policy in openamrobot-docs; SAFETY-PROCUREMENT wording check (a) plus platform lead (c); register provenance (a) with owner confirmation (c); docs-fix prompt separates verified from planned content (template)What changed
75 files change against main (61 added, 13 modified, 1 renamed).
.github/CODEOWNERSis not among them.summaryandfix_hintused in findings.Every entry has kind, scope (repositories and file globs), owner, provenance, supersession and a verification method: what the scan detects, and which reviewer checks what evidence.
Sources: P-03 rev18.7 (6 October 2026) is the addendum in force; revisions 18.6, 18.5, 18.4, 18.3 and 18.2 are earlier revisions. BOM Issue 7.3 is canonical; Issue 7 is the earlier issue. All are provenance only; CI reads only the pinned register.
LIFT (P-03 rev18.7 item 8) replaces LIFT-REMOVED.
Superseded entries: MAST-INSTALL-HEIGHT, MAST-POSITIONS and MAST-TOP-HEIGHT are superseded by item 8. Only their citation patterns are scanned, for text still presenting the fixed-mast value as current. MAX-ASSEMBLED-HEIGHT stays 1700 mm (item 8).
DATUM-HEIGHT-STACK (item 15):
FRAMES-REP105 (item 15): base_footprint on the floor under the drive-axle midpoint; base_link at the axle midpoint and axle height, x forward, z up; imu_link on the centreline away from motor magnetic fields.
BATTERY-PLACEMENT (item 9): as close to the rear edge as practical while preserving enclosure, service and safety clearances; the 25 percent position is superseded.
BASE-CONTROLLER-IO (item 14):
HEAD-CAMERA-IDENTITY is recorded (item 15): Stereolabs ZED Mini, SKU ZED-121210, supplied with the OpenArm 2.0 set, on the lift carriage, pitch 15 to 35 degrees down in 5 degree steps, baseline 25.
CAMERAS: the base Gemini 336L sits about 243 mm above the floor, with up-tilt positions 5, 10 and 15 degrees, baseline 10 (item 15).
NAV-LIDAR: the SLAMTEC RPLIDAR S3 (S3M1-R2) on USB and the regulated 5 V rail (P-03 rev18.4 item 13).
RELEASE-MILESTONES (P-03 rev18.6 item 12):
Its checks also flag a v0.2 release and a development cycle ending 13 November 2026 without a superseded label.
Unchanged in this round: the distinctions and exclusions (the 1700 mm envelope, no suspension, no RS485, no dock contacts or pilot, docking never establishes charging, telemetry never safety evidence).
supersededstatus (superseded_bywith document, item, optional decision and citation).openamrobot-docs/docs/DOCUMENTATION_STANDARD.md. The allowlist is an implementation detail that separates intentional public content (contact, licensing, documentation) from accidental leakage.changed_all.txt).summary.json, also for delegated runs.env -iwith a freshHOME. The caller's rosdep sources list and cache are copied in, andROSDEP_SOURCE_PATHis passed through.rosdep checkscans only the ROS source packages, neverbuild/,install/,log/orCOLCON_IGNOREfolders.VERIFY_ROS_SETUPcan replace the ROS setup file.*.shand*.bash.rollout/STATE.md.example.docs-fix.md(template version 2) separates verified facts, which carry a source reference in the owning repository, from labelled planned or experimental content, and forbids inventing a technical claim.tools/sync_audit_issues.pynever closes an issue.tools/watchdog.py,tools/watchdog_report.py,tools/watchdog_issue_sync.py,WATCHDOG.md,public-extract-allowlist.yaml(approved public contacts),rollout/repositories.yamland the installed.github/workflows/watchdog-org-scan.yml, described above.repository-quality-reusable.ymlgains the decisions, public-extract and drift steps behindharness_checks: true(blocking) orharness_warn: true(warnings only), both off by default.fetch-depth: 0only when one of them is true; default callers keep the shallow checkout.quality/testjob.Repositories affected on merge
Without any opt-in, merging changes these organization-wide defaults. The repositories were checked on fresh main checkouts on 7 October.
.github/workflows/watchdog-org-scan.ymlruns from this repository's default branch every Thursday at 14:00 Europe/Berlin and on manual dispatch. It clones the 14 repositories inrollout/repositories.yamlread-only and does not change them. In this repository it creates thewatchdog-reportlabel if missing and creates, then edits in place, the "[watchdog] Organization dashboard" issue. WithWATCHDOG_ISSUE_MODEunset no other issue is written. It needs no secret beyond the workflow'sGITHUB_TOKEN.repository-quality-reusable.yml@main, and none sets the new inputs.repository-qualityjob runs the new file. The harness steps stay off, the quality/test job stays off, and the checkout stays shallow. The governance-baseline steps are unchanged..github/ISSUE_TEMPLATEof their own; only openamr-platform-sw has one. Those 12 get the changed defaults:Integration Gate
Reused and extended:
check_agent_rules.py, extended to read the marker version.repository-quality-reusable.yml, with its steps kept.tools/verify.shdesign, delegated to rather than copied.run_verification_tests.py.check_docs.sh, called throughVERIFY_TEST.Rejected:
@maincallers on merge: that would change other repositories without their owners.push: the action does not support that event.Changes after review
Round 1, commit e86f68c: merge with main (already up to date);
.github/CODEOWNERSrestored to main's version; NAV-LIDAR is the RPLIDAR S3 (P-03 rev18.4 item 13) with Hokuyo and A1 superseded; POWER-RAILS on the regulated 5 V rail; RELEASE-MILESTONES added; COMPUTE source item fixed; maintainers ci-owner wikki26 and docs-owner anandgawai123456-glitch; register tests that fail against the previous register.Round 2, commit 0fa9b64: P-03-rev18.4 in force; the maintainers.yaml header describes main's CODEOWNERS; rollout/README.md handles filled in; description rewritten.
Round 3, commit 066f580: Gate B is the STM32H723ZG on the NUCLEO-H723ZG; P-03-rev18.5 added; new entry BASE-CONTROLLER-IO.
Round 4, commit cc02725: P-03-rev18.5 in force; register test for BASE-CONTROLLER-IO.
Round 5, commit fcf3d8ae7e73: P-03-rev18.6 in force; RELEASE-MILESTONES versions v2.0.0-rc.1 and v2.0.0 (P-03-rev18.6 item 12).
Round 6, commits 4a88e50 to 458ea3b (20 commits, each signed off). Every register commit carries a register test that fails against the previous register; the failure is quoted in its commit message.
supersededstatus..gitattributeskeeps LF.fetch-depth: 0only with the harness checks.Round 7, commits after 458ea3b (head
774f2ad). This review pass closes the concrete pre-merge findings and keeps activation gated:<HARNESS_SHA>in live workflows;AGENTS.mdis missing unless they provide a non-empty, summarized exception reason;review_bydates, with non-blocking audit warnings after expiry;id-token: writefor the official Claude GitHub App path; Anthropic OIDC federation is a separately documented alternative and remains gated by issue Activation gate for AI workflows (docs-sync, weekly audit, monthly retro) #43.micro_ros_agentverifier blocker in openamr-platform-sw#50.Round 8, the Watchdog (commits 3110898 to e75c3b5, six commits, each signed off). No decision value changed.
3110898, friendly output.
check_decisions.py,check_public_extract.py,check_agent_rules.pyandcheck_workflow_policy.pyprint each finding as label: file:line: ID found 'text' plus Decision (or Rule), Why, Fix and More (links to WATCHDOG.md and the register entry's line), grouped by decision with counts, then a closing summary and the next step. Labels: "Mismatch with approved decision", "Should not be public", "Shared agent rules out of date", "Workflow not pinned", "Placeholder left in workflow". What they detect, their exit codes and theresult:lines are unchanged. New shared moduletools/watchdog_report.py. Inside GitHub Actions each finding is also a workflow annotation (warning, or error when enforcing on a pull request) and a Markdown job summary with the grouped table and collapsible details; the reusable workflow setsWATCHDOG_ANNOTATIONinstead of the oldgrep/sedannotation lines.check_pr_evidence.pyparses the new header. Two optional register fields,summaryandfix_hint(one line, at most 120 characters, schema-validated), are filled for all 27 entries from the existing value and message text; the long value stays in the register and is no longer printed per finding.bcbc07a, false-positive review. Every one of the 193 decision findings in the scan below was read on its source line. Only two lines clearly label historical material, and only their
unlesspatterns changed, each with a regression test (fails before, passes after; a current-tense line still fails):outdatedandolder revision(s): openamr-platform-hwelectrical/sensors/imu.md:31, "Older revisions of this doc said the firmware publishes/imu/datadirectly — that is outdated".legacy: openamr-platform-swros2/src/openamrobot_docking/config/dock_trigger.yaml:25, "# Legacy fields read by opennav_docking::SimpleChargingDock".Not adjusted, because the line does not label history or 3.0 (reported for the decision owners): MPU6050 lines that explain the board is really an MPU6500 (BASE-CONTROLLER-GATES, 7 lines); the upstream Nav2 class name
SimpleChargingDock(DOCKING-NOT-CHARGING, 10 lines); "RealSense ... an anticipated direction ... not a committed change" (CAMERAS); "wireless charging ... not on the base build" (DOCK-NO-CONTACTS). Every LIFT, MAST-* and "fixed mast" finding is a real mismatch under rev18.7 item 8 (lift approved in principle for 2.0).cf77d4c,
tools/watchdog.py. Runs decisions of record, public extract, shared agent rules (when AGENTS.md exists), workflow policy and decision freshness against one checkout with this harness's register, then prints one summary grouped by decision.--report-only,--json,--markdown,--accepted-words. Exit 0 clean, 1 findings, 2 configuration error.87e9561,
.github/workflows/watchdog-org-scan.yml. Deterministic, no AI,permissions: contents: read, weekly (Monday 06:17 UTC) and manual dispatch, actions pinned to full SHAs. Clones the 14 repositories in the newrollout/repositories.yamlon their default branch, runstools/watchdog.py --report-only, and writes one job summary with a table per repository and a link to WATCHDOG.md. Findings never fail the job; it never pushes, opens issues or comments. A clone failure is shown as BLOCKED and fails the job after the summary, so an incomplete scan is not shown as complete.b406a5a, WATCHDOG.md, linked from README.md and CONTRIBUTING.md: what it is and is not, the checks table (what, why, typical finding, fix, owner), a real finding before and after the fix, how to fix (correct the line, label history with the words each decision accepts, or open a contract change request; never weaken a check), local and CI use, the adoption checklist (interfaces pilot first), AI-workflow status (design only until Activation gate for AI workflows (docs-sync, weekly audit, monthly retro) #43 closes) and an FAQ. The accepted-words table is generated by
tools/watchdog.py --accepted-wordsand a test keeps it identical to the register. The register's globalexcludegains the rootWATCHDOG.mdonly, because the guide quotes findings and register messages; a test showsdocs/WATCHDOG.mdelsewhere is still scanned.e75c3b5, test isolation. The first CI run of this round (run 37661236604, green) showed three spurious
##[error]annotations from the formatter tests in its quality/test log, and checker tests could append to the real job summary. Test modules that exercise the output now drop the GitHub Actions variables, and a new test runs the whole suite as a child withGITHUB_ACTIONS=trueand fails on any annotation line or summary write.Round 9, approved public contacts and compact output (commits 48519d5 to 4ea9bd4, three commits, each signed off; head
4ea9bd4). No decision value changed.48519d5, compact output.
tools/watchdog_report.pyprints one block per decision (or rule): label, ID and count, then Decision, Why (one line per distinct reason), Fix and More once, then every finding asfile:line: found '...'. Annotations and the JSON output keep full detail per finding.check_pr_evidence.pyreads the grouped report and produces the same failure lines as before; a new test feeds it the realcheck_decisions.pyoutput. Detection, exit codes andresult:lines are unchanged.172f9c6, approved public contacts in
public-extract-allowlist.yaml, each entry with its reason; existing entries kept, no price entry added:botshare.aidomain (or a subdomain);Signed-off-by:orCo-authored-by:line, and any address inCONTRIBUTORS.md,MAINTAINERS.mdormaintainers.yaml(publication agreed through the DCO, CLA and contributor privacy notice);datasheets/**only, local partsales,info,support,service,contact,export,trade,officeormarketing, optionally followed by digits.Regression tests: each allowed case passes; a personal supplier address in
datasheets/, the lookalike domainsbotshare-ai.com,botshare.ai.example.organdnotbotshare.ai, a role address outsidedatasheets/and prices indatasheets/are still flagged. The existing assertion thatsomeone@botshare.aiis flagged was changed to allowed, as item (a) requires.4ea9bd4, WATCHDOG.md: new section "Approved public contacts" (the four kinds: organisation, contributors and maintainers, supplier role addresses in
datasheets/only, third-party licence notices; prices never public except the approved organisation pricing; the docs owner decides entries for published pages, the platform lead for company or commercial information). "How to read a finding" and the checks table show the grouped format with the real COMPUTE group from the openamr-platform-hw scan.Related, separate repository: openAMRobot/openamr-platform-hw#17 (open) removes the ZLTech supplier price list and personal supplier contact data from
datasheets/; with this round's allowlist itsdatasheets/folder has no public-extract findings.Round 10, Watchdog issue publication, dashboard-only default and Berlin schedule (head
8ecda44). No decision value changed.tools/watchdog_issue_sync.pyturns the organization scan into GitHub issues in openAMRobot/.github: stable deduplication per repository, check and group; redaction of URLs, e-mail addresses and credential-shaped text; comments only when the evidence changes; "no longer detected" comments instead of closing; reopening when a closed finding returns; review reminders for duereview_bydates; BLOCKED handling; the label vocabulary created on demand; thedecision_review.ymlissue form; the dashboard's shared-rules enrolment column (pass, drift, not enrolled). The workflow moved to Thursday withissues: write; this supersedes the Round 8 description of a Monday, issue-free scan.WATCHDOG_ISSUE_MODE, read by the workflow (vars.WATCHDOG_ISSUE_MODE) and bytools/watchdog_issue_sync.py: unset ordashboard(default) creates or edits in place only "[watchdog] Organization dashboard", listing every active group with repository, check, group, finding count, owner and file links (at most five links per group, then "and N more");groupskeeps the per-group issues; any other value stops the sync with exit 2. Scan-blocked repositories always appear on the dashboard. Documented in WATCHDOG.md ("Watchdog issue mode": how to turn on per-group issues, and that the platform lead decides when) and in the workflow comments.cron: "0 14 * * 4"withtimezone: "Europe/Berlin"(was17 6 * * 4, 06:17 UTC); 5a8b313 updates the workflow test to the new cron and timezone; 18d8a2b updates WATCHDOG.md,rollout/workflows/SETUP.md(which also says that only the dashboard issue is written whileWATCHDOG_ISSUE_MODEis unset) and the workflow header comment.git rebase --signoff 12a64bc(the parent of 9aaae03) rewrote only the six commits after it, with no merge commit in that range, keeping authors, content and order, and the branch was pushed with--force-with-lease: 9aaae03 → 2dd01e1, 3e6ac3c → cdbdb22, 50a4747 → 0449955, b2b209f → f3c2fb8, 3bd038f → 07e3f50, 2829903 → 5039b53. The two schedule commits arrived on the branch without sign-off (0329752, b562360) and were signed off the same way (git rebase --signoff 43f2804, no merge commit in range, authors and content kept,--force-with-leaseagainst b562360): 0329752 → f7c6d96, b562360 → 5a8b313; the tree of 5a8b313 equals b562360. Checked afterwards: all 126 non-merge commits inorigin/main..HEADcarrySigned-off-by: Alex Reznichenko <info@botshare.ai>; the tree of 5039b53 equals the tree of 2829903, and 43f2804 differed from 2829903 only by the issue-mode commit (6 files).WATCHDOG_ISSUE_MODEisgroups. The scan-step test asserts the new line and the absence of the old one (1 failed, 5 passed against the previous workflow).CI/CD review of 8 Oct: fail-closed scan (commits 37896d3 and 2151010; current head
2151010)Review requirement (CI/CD owner, 8 October, on 8ecda44): "Please fail closed for setup/report-generation errors (use guarded commands and robust error handling), and ensure an incomplete scan is explicitly marked BLOCKED/INCOMPLETE rather than published as a clean complete result. Add regression coverage for a failed repository-list generation and a report-generation/enrichment failure; verify the job fails and dashboard reporting never silently treats missing repositories as clean."
Resolved in 37896d3 and 2151010 (two signed-off commits; schedule, default issue mode and
decisions.yamlunchanged). Copied onto a checkout of 8ecda44, the new and changed scan and sync tests of 37896d3 fail there (15 failed, 20 passed: 13 new tests, the reworked clone-failure scan test and one adjusted dashboard assertion), and the empty-list test of 2151010 fails there too (the step exits 0); all pass on 2151010. The new guide test covers the WATCHDOG.md section.An empty or unreadable expected list is INCOMPLETE, never a valid zero-repository scan. An empty
repositories:list makes the scan step write an INCOMPLETE summary and exit non-zero; an expected list that is missing, unreadable, not a list or empty makes the issue sync refuse to publish results and exit non-zero.set -euo pipefailand an EXIT trap that writes an INCOMPLETE summary and::error::on any unexpected stop; clone,rev-parse,watchdog.py, enrichment and the finding total are guarded per repository withif !or a captured statustest_org_scan.py::FailClosed::test_step_runs_with_errexit_and_pipefailtools/watchdog_scan_support.py liststops the step on failure;expected.jsonis written beforelist.txt; an empty list or a list shorter thanrollout/repositories.yamlwrites "Scan INCOMPLETE: repository list could not be generated", emits::error::and exits non-zerotest_broken_repository_list_stops_the_scan(broken and missing file),test_short_repository_list_fails_and_missing_repositories_are_blockedwatchdog.pyexit or a corrupt report records the repository inblocked.json("watchdog exit N at ", "report enrichment failed at "), sets the report aside and continues with the next repositorytest_watchdog_and_enrichment_failures_block_only_their_repositorytest_scan_reports_every_repository_and_blocks_on_clone_failure,test_watchdog_issue_sync.py::FailClosed::test_command_line_exit_codeswatchdog_issue_sync.py --expected(passed by the workflow, step keepsif: always()): missing repositories and malformed reports are BLOCKED in both issue modes; the dashboard opens with "Scan INCOMPLETE on : N of M repositories scanned. Results below are partial; missing repositories are listed as BLOCKED and are not clean."; issues and dashboard rows of repositories that were not scanned are never cleared (rows stay as "last known")test_missing_report_is_blocked_with_banner,test_incomplete_run_never_clears_findings_of_unscanned_repositories,test_incomplete_dashboard_keeps_last_known_rows_of_unscanned_repositories,test_malformed_report_is_blocked_not_skippedtest_unreadable_expected_list_refuses_to_publish,test_unreadable_expected_list_posts_only_the_bannerload_expectedrejects a missing, unreadable, non-list or empty expected list; nothing is published as clean and the sync exits non-zerotest_org_scan.py::FailClosed::test_empty_repository_list_is_incomplete_not_a_zero_repository_scan,test_unreadable_expected_list_refuses_to_publish(missing file, invalid JSON,[])test_org_scan.py::FailClosed::test_happy_path_is_complete_and_passes,test_complete_run_has_no_bannertest_watchdog.py::Guide::test_incomplete_scans_sectionLocal dry run on 8 October (the real "Scan repositories" step script, real
git, fresh clones of the 14 repositories; sync planned without--apply):Evidence
Base SHA: ce39a17
Head SHA: 2151010
GitHub Actions on this head, run https://github.com/openAMRobot/.github/actions/runs/37770189553:
PASS: all detected verification stages; register27 loaded, 23 recorded and scanned, 1 open, 3 supersededCommands run on this head:
Watchdog scan of every active repository (Round 9, head 4ea9bd4; not re-run in Round 10, which changed issue publication and the schedule only).
python3 tools/watchdog.py --root <clone> --report-onlyran on fresh--depth 1clones of the default branch (main) of all 14 repositories inrollout/repositories.yaml, on 7 October 2026, with the Round 9 allowlist. Report only: nothing was enforced, pushed or commented. The.githubrow is this repository'smain; this PR's head scans clean (0 findings). "not run (no AGENTS.md)" means the repository has no AGENTS.md yet (rollout step (a)). Compared with Round 8, public extract fell from 55 to 52: the organisation address in.githubprofile/README.mdand the supplier role addressessales@andtrade26@in openamr-platform-hwdatasheets/ZDmotor/README.mdare now approved; the personal supplier address indatasheets/ZLTech/README.mdis still flagged (removed by openamr-platform-hw#17).ce39a1712de3ef732f002169a613f18c7e263c0925671b2657795047795143e8b981ad1c55292654078f8111c48b9f4a9dTests
236 tests, 0 skipped:
Deliberate faults and regressions for the CI/CD review (37896d3, 2151010). The new and changed tests of 37896d3 were copied onto a checkout of 8ecda44: 15 failed, 20 passed. The empty-list test of 2151010 also fails there:
AssertionError: 0 == 0, because 8ecda44 finished an empty scan with exit 0. For example, on 8ecda44 a corrupt report for openamrobot-docs was not recorded as BLOCKED ({'repository': 'openamrobot-docs', 'reason': 'report enrichment failed at abc1234'} not found), the summary heading never said INCOMPLETE, and the step ran withset -uo pipefail(no errexit).Deliberate faults and regressions in Round 10.
watchdog_issue_sync.pytests/test_watchdog_issue_sync.pygroupsand the dashboard short-circuit removedFAILED test_unset_or_empty_switch_means_dashboard,test_dashboard_mode_plans_no_group_issue_writes,test_dashboard_mode_creates_only_the_dashboard,test_dashboard_mode_updates_the_dashboard_in_place_once,test_command_line_reads_the_switch(5 failed, 11 passed)'0 14 * * 4' != '17 6 * * 4'intest_scans_on_thursday_and_writes_only_control_surface_issues, reproduced locally (2 failed, 219 passed); green after 5a8b313Deliberate faults and regressions in Round 9.
FAILED test_approved_public_contacts,FAILED test_organization_allowlist_loads_and_exempts_placeholders(2 failed, 17 passed)watchdog_report.pyFAILED test_grouped_blocks_and_closing_summary,test_distinct_reasons_in_one_group_are_each_printed_once,test_exit_one_on_contradiction,test_finding_explains_decision_why_fix_and_links,test_suite_does_not_leak_into_the_ci_run(5 failed, 56 passed)check_pr_evidence.pyFAILED test_contradictions_become_failures,test_long_reports_are_truncated,test_reads_the_real_grouped_checker_output(3 failed, 42 passed)Deliberate faults and regressions in Round 8.
unlessadjustments (bcbc07a)FAILED test_imu_topic_history_label_is_accepted,FAILED test_legacy_charging_dock_fields_are_accepted(2 failed, 50 passed)FAILED test_all_checks_run_and_summary_groups_by_decision,FAILED test_json_and_markdown_outputsFAILED test_scan_reports_every_repository_and_blocks_on_clone_failuretest_annotation_level_follows_enforcementrequires::errorfor an enforced pull request and::warningfor warn-only and push scanstest_accepted_words_table_matches_registerfails when WATCHDOG.md and the register disagreeFAILED test_suite_does_not_leak_into_the_ci_run(1 failed, 6 passed); before e75c3b5 a local run withGITHUB_ACTIONS=trueprinted 2 annotation lines and wrote 353 lines into the job summaryNot verified
watchdog-org-scan.ymlhas not run on GitHub yet (it runs on schedule or manual dispatch only from the default branch, so first after merge); its scan step was run locally with a fakegitin the tests, and the real scan above was run locally with the same command. Thetimezone: "Europe/Berlin"schedule key is accepted by actionlint; the first scheduled run time has not been observed.watchdog_issue_sync.pywas exercised only with a fake API in tests. Not verified: that the organization's default token settings allowissues: writeand label creation, that assigningBotshareAIsucceeds, and how the first dashboard looks on GitHub. With the 8 October dry-run data the dashboard body is 40,855 characters for 68 groups, plus the banner when incomplete; GitHub's limit is 65,536, and there is no truncation guard yet. Inline annotations and the Markdown job summary are covered by unit tests only: this PR's own repository-quality run has 0 findings, so it shows none, and no pull request in another repository has shown them yet. Warn-only mode has not run on GitHub.CONTRIBUTORS.md,MAINTAINERS.mdandmaintainers.yaml: none of these files lists an address today, and those files are outside the public-extract scope unless they sit underdocs/or apublicpath, so that entry is tested with a synthetic file only.ros:jazzy-ros-basecontainer against pinnedopenamrobot-interfaces, with a clean HOME, source-only rosdep scan, generated workspace directories, and both Fast DDS and Cyclone DDS. The unresolvedmicro_ros_agentkey inopenamr-platform-swremains tracked separately in #50.<HARNESS_SHA>placeholder, and weekly-alignment-audit.yml has one info-level SC2012. Neither is installed anywhere.Setup required
For the organization owner; details and the (a)/(b)/(c) classification are in
rollout/workflows/SETUP.md.Merge, then roll out per repository, openamrobot-interfaces first as the pilot (rollout/README.md):
uses:andharness_refto the merge SHA;harness_warn: trueuntil a successful run on main;harness_checks: true;Record the pilot's exit criteria before the next repository starts.
Decide when to set
WATCHDOG_ISSUE_MODE=groups(platform lead); until then the Watchdog writes only the dashboard issueReplace
<HARNESS_SHA>in any workflow copied fromrollout/workflows/Secret
ANTHROPIC_API_KEYfor audits, openamrobot-docs and .github (only when the designs are adopted)Secrets
AUDIT_APP_ID/AUDIT_APP_PRIVATE_KEY,DOCS_SYNC_APP_ID/DOCS_SYNC_APP_PRIVATE_KEY,RETRO_APP_ID/RETRO_APP_PRIVATE_KEYClaude GitHub App on audits, openamrobot-docs and .github only; a harness App with Issues read/write, Pull requests read, Contents read/write, Metadata read
Actions settings: read-only default token, Actions PR approval off, allow-list the four pinned actions, approval for first-time fork workflows
Labels: harness, good first issue, contract-change, audit-finding, blocker, major, area:*
Rulesets per repository: PR required, CODEOWNERS review, conversation resolution, required checks once passing on main, no force push
Safety paths: two human approvals via ruleset and a CODEOWNERS entry for the platform lead, per the SETUP.md section 6 table
Step (a) is still open in openamrobot-manifest, openamrobot-manipulation and openamrobot-ui (shared block v1)
Confirm write access for the proposed CODEOWNERS handles before those lines are added in other repositories
jq wherever the harness suite runs as evidence (Harness tests: jq is required for the PR-assistant wiring test #42)
Resolve the real Jazzy rosdep blocker in openamr-platform-sw#50
Complete the AI-workflow activation checklist in .github#43; the workflows remain design-only
Earlier reviews (history)
These reviews were given on earlier heads. GitHub now shows the earlier approvals as dismissed, and none of them covers the current head.
The platform lead's source-reconciliation comments on 774f2ad and 8ecda44 are author statements, not approvals. Earlier rounds of this work posted reply and review-gate comments on this pull request; this round posted none and requested no reviews.
Current head state
21510107706bae7893d22c79038529d27ec54e48.Contribution terms
AI disclosure
This PR was prepared with Claude Code (AI-assisted). Claude Code helped with repository research,
governance text, workflow/checker implementation, tests and review reconciliation. In Round 8 it wrote the Watchdog output format,
tools/watchdog_report.py,tools/watchdog.py, the organization scan workflow,rollout/repositories.yaml, WATCHDOG.md, the registersummaryandfix_hinttexts, the twounlessadjustments and their tests, and ran the scans. In Round 9 it wrote the compact output, the approved-contact allowlist entries and their tests, the WATCHDOG.md section, and openamr-platform-hw#17. For the 8 October CI/CD review it wrote the fail-closed scan step,tools/watchdog_scan_support.py, the sync changes, the regression tests and the WATCHDOG.md section, and ran the dry runs. In Round 10 it wrote the issue-mode switch, its tests and documentation, the schedule documentation commit 18d8a2b, performed the sign-off rewrites and wrote this description; the issue publication commits (e87f75a to 5039b53) and the schedule commits (f7c6d96, 5a8b313) were pushed to the branch outside this session and are described from their diffs and messages. A humanreviewer remains responsible for source reconciliation, owner approvals, security decisions,
physical/electrical/safety evidence and merge. The PR adds no new runtime dependency; checker
code uses PyYAML (MIT), and rollout examples reference
anthropics/claude-code-actionpinned bycommit SHA. No safety implementation is authored or modified here.
🤖 Generated with Claude Code
https://claude.ai/code/session_01DeSLcD827exxSw3xL9zyiU