Repository navigation
feat(governance): route review by what a diff does — TX-path ack, red-main attribution, intent-first review (RFC #6435) #6436
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| # The transmit surface. Principle VI: AetherSDR never transmits without | ||
| # operator intent. A PR whose diff reaches anything listed here must say so: | ||
| # tools/check_tx_surface.py fails Static checks until the PR adds | ||
| # .github/tx-acks/<PR number>.md stating what changes on the TX path and how it | ||
| # was verified. That directory is owned by @aethersdr/reviewers, so any code | ||
| # owner's approval covers it. See GOVERNANCE.md §Transmit-path changes. | ||
| # | ||
| # This list is Tier 1: shrinking it is how the gate would be bypassed, so the | ||
| # diff to this file is the review signal, the same as .github/ci-test-gate.txt. | ||
| # | ||
| # Two kinds of entry, one per line, `kind<space>regex`, trailing `# reason` | ||
| # not parsed: | ||
| # path — Python regex matched against the repo-relative path of any file | ||
| # the PR changes in a line that is not comment-only. The whole | ||
| # file is TX machinery. | ||
| # token — Python regex searched in every added or removed line under src/ | ||
| # that is not comment-only. The token is TX machinery wherever it | ||
| # appears, including inside RadioModel.cpp and MainWindow*.cpp, | ||
| # which are too large to gate by path. | ||
| # | ||
| # Comment-only lines never trigger either kind: a reworded comment is not a | ||
| # keying change. A user-visible string that merely names a token is not one | ||
| # either, which is why the env-var entry matches the read, not the name. | ||
|
|
||
| path ^src/models/TxController\.(h|cpp)$ # the TX permission object | ||
| path ^src/core/TxCoordinator\.(h|cpp)$ # arbitration between TX producers | ||
| path ^src/models/RadioModel_TxCoordinator\.cpp$ # RadioModel's half of the coordinator | ||
| path ^src/core/backends/flex/FlexPttWireSession\.(h|cpp)$ # writes `xmit 1` / `xmit 0` | ||
| path ^src/core/TxKeyingMarker\.h$ # which controls key, and the bridge's refusal | ||
|
|
||
| token "xmit\b # Flex MOX on the wire | ||
| token "transmit tune\b # Flex TUNE carrier | ||
| token "atu start\b # ATU tune keys a carrier | ||
| token \bcwx (macro )?send\b # CWX keys CW | ||
| token \bsetKeying\b # IRadioBackend keying entry point | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Replay over the PR's 381-commit window, per token set: list as it stands 13; plus K5PTB's |
||
| token \b(setMox|setPtt|requestMox)\b # backend and model keying | ||
| token \b(markTxKeying|registerTxKeyingAction|registerReceiveControlAction)\b # keying-control registration | ||
| token \b(transmitControlMatch|requiresTxPermission)\b # keyboard and bridge TX guards | ||
| token \b(qEnvironmentVariable\w*|qgetenv|getenv)\(\s*"AETHER_AUTOMATION_ALLOW_TX" # reading the bridge's TX opt-in | ||
| token \bm_txAllowed\b # the bridge's cached TX opt-in | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -30,9 +30,13 @@ on: | |||||
| # `github.run_id` in the group, which gave every run a group of its own and | ||||||
| # made the whole thing inert — the same behaviour, reached confusingly. | ||||||
|
|
||||||
| # actions: read and pull-requests: read are for the tracking issue's | ||||||
| # attribution lines (the parent commit's verdict, the commit's source PR). | ||||||
| permissions: | ||||||
| contents: read | ||||||
| issues: write | ||||||
| actions: read | ||||||
| pull-requests: read | ||||||
|
|
||||||
| jobs: | ||||||
| full-suite: | ||||||
|
|
@@ -318,13 +322,53 @@ jobs: | |||||
| const createLabels = [...labels, 'bug', 'priority: high']; | ||||||
| const sha = context.sha.substring(0, 7); | ||||||
| const date = new Date().toISOString().split('T')[0]; | ||||||
| const repo = { owner: context.repo.owner, repo: context.repo.repo }; | ||||||
|
|
||||||
| // Attribution, so a human can decide fix-forward vs revert from the | ||||||
| // issue alone (docs/PR-WORKFLOW.md §Recovering from a red main). | ||||||
| // Squash merges make the pushed commit the suspect, unless main was | ||||||
| // already red one commit earlier. Neither lookup may stop the issue | ||||||
| // from being filed, so each degrades to "unknown". | ||||||
| let sourcePr = 'unknown'; | ||||||
| try { | ||||||
| const prs = await github.rest.repos.listPullRequestsAssociatedWithCommit({ | ||||||
| ...repo, commit_sha: context.sha, | ||||||
| }); | ||||||
| const pr = prs.data.find(p => p.merged_at) || prs.data[0]; | ||||||
| sourcePr = pr ? `#${pr.number} by @${pr.user.login}` : 'none (direct push)'; | ||||||
| } catch (e) { | ||||||
| core.warning(`source PR lookup failed: ${e.message}`); | ||||||
| } | ||||||
| let parentVerdict = 'unknown'; | ||||||
| try { | ||||||
| const commit = await github.rest.repos.getCommit({ ...repo, ref: context.sha }); | ||||||
| const parent = commit.data.parents[0]?.sha; | ||||||
| if (parent) { | ||||||
| const runs = await github.rest.actions.listWorkflowRuns({ | ||||||
| ...repo, workflow_id: 'full-suite.yml', head_sha: parent, per_page: 10, | ||||||
| }); | ||||||
| const done = runs.data.workflow_runs.find(r => r.status === 'completed'); | ||||||
| const p7 = parent.substring(0, 7); | ||||||
| parentVerdict = | ||||||
| !done ? `no completed run for parent \`${p7}\`` | ||||||
| : done.conclusion === 'success' ? `green at parent \`${p7}\` — this commit is the first red one` | ||||||
| : `already ${done.conclusion} at parent \`${p7}\` (${done.html_url}) — look earlier`; | ||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [P2] Do not infer a new failure's origin from the parent's overall result A parent workflow conclusion of failure does not mean the tests failing at this commit already failed there. I independently checked the PR's example: d3ab349's parent is 0cce730; its completed run https://github.com/aethersdr/AetherSDR/actions/runs/38301867624 failed only radio_setup_headphone_output_gate_test (recorded on #6418). d3ab349's run https://github.com/aethersdr/AetherSDR/actions/runs/38302350478 adds fm_tone_presentation_contract, hl2_tci_signaling_test and icom_family_test (#6420). The extracted script still writes “already failure at parent ... — look earlier” for the new failures, directing investigation away from this commit. Compare signatures, or qualify the instruction without asserting attribution:
Suggested change
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agree with rfoust's comment on this line (same evidence: |
||||||
| } | ||||||
| } catch (e) { | ||||||
| core.warning(`parent verdict lookup failed: ${e.message}`); | ||||||
| } | ||||||
|
|
||||||
| const body = [ | ||||||
| `**Run:** ${process.env.RUN_URL}`, | ||||||
| `**Commit:** \`${sha}\``, | ||||||
| `**Source PR:** ${sourcePr}`, | ||||||
| `**Main before this commit:** ${parentVerdict}`, | ||||||
| `**Date:** ${date}`, | ||||||
| `**Failed:** ${process.env.FAILED}`, | ||||||
| '', | ||||||
| 'Before reverting, check the failing tests against the known-flake umbrella #4703 ' + | ||||||
| 'and re-run once; a revert is a human call (docs/PR-WORKFLOW.md §Recovering from a red main).', | ||||||
| '', | ||||||
| '<details><summary>ctest report</summary>', | ||||||
| '', | ||||||
| '```', | ||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[P2] Include existing keying entry points in the surface
Using this PR's
load_surface()andtriggers(), added calls undersrc/models/RadioModel.cpptosetTune,setAtu,setCwKeying,requestProducerPttOn, andstartTuneeach produced an empty hit list. The controlsendCmd("xmit 1");did trigger. These are existing keying paths:IRadioBackend.h:575,605,683declares the backend verbs, whileTciServer.cpp:2576,3418calls producer PTT and TUNE. The currentsetKeyingregex does not match them, and these call sites are not path-listed. Consequently an author can change those keying calls without the disclosure this PR promises. Add the missing entry points, survey the sibling key-on/wire APIs, and pin them with focused cases. The RFC triage already identifies the setTune/setAtu gap.