Skip to content
Closed
Show file tree
Hide file tree
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
29 changes: 29 additions & 0 deletions .github/workflows/gate-topology.yml
Original file line number Diff line number Diff line change
Expand Up @@ -136,3 +136,32 @@ jobs:
printf '#include "gen/c/claw/sarif_feed.c"\n#include <stdio.h>\n#include <stdlib.h>\nint main(void){size_t k=1<<22,n;uint8_t*b=malloc(k),*o=malloc(k);n=fread(b,1,k,stdin);size_t m=feed_sarif(b,n,o,k);if(n==k||m>k)return 3;fwrite(o,1,m,stdout);return 0;}\n' | cc -O1 -w -I . -x c -o /tmp/feed -
git diff --name-only --diff-filter=d HEAD^1 HEAD -- '*.t27' | while read -r f; do printf '%s\t%s\t%s\n' "$f" "$(/tmp/t27c spec-status "$f" 2>&1 </dev/null | tail -1)" "$(/tmp/t27c parse "$f" 2>&1 >/dev/null </dev/null | head -1)"; done | /tmp/feed > /tmp/claw.sarif
- {if: steps.have.outputs.ok, uses: github/codeql-action/upload-sarif@v4, with: {sarif_file: /tmp/claw.sarif, category: claw/sarif, token: "${{ steps.tok.outputs.token }}"}}

# claw/suggest: a changed .t27 spec that `t27c fmt` (specs/tri/fmt_source.t27, whitespace only) would reformat becomes a
# suggestion review from the TRI CLAW App. Placement is specs/claw/suggest.t27, the driver is specs/claw/suggest_feed.t27
# (gen/c/claw/suggest_feed.c); this job mints the token (pull_requests write + contents read, the pr-suggestions row of
# specs/claw/github_surface.t27), feeds the driver the head files and the diff headers, and posts the review it prints.
# Event COMMENT only, never an approval. Head files are read with git show, so a symlink in the PR is never followed.
claw-suggest:
if: github.event_name == 'pull_request'
runs-on: ubuntu-24.04
permissions: {contents: read}
steps:
- id: have
env: {K: "${{ secrets.CLAW_APP_PRIVATE_KEY }}", I: "${{ vars.CLAW_APP_ID || secrets.CLAW_APP_ID }}"}
run: if [ -n "$K" ] && [ -n "$I" ]; then echo ok=1 >> "$GITHUB_OUTPUT"; else echo "claw/suggest posted nothing - secret CLAW_APP_PRIVATE_KEY or CLAW_APP_ID (variable or secret) is not set (docs/claw/README.md)." >> "$GITHUB_STEP_SUMMARY"; fi
- {id: tok, if: steps.have.outputs.ok, uses: actions/create-github-app-token@v2, with: {app-id: "${{ vars.CLAW_APP_ID || secrets.CLAW_APP_ID }}", private-key: "${{ secrets.CLAW_APP_PRIVATE_KEY }}", owner: gHashTag, repositories: t27, permission-pull-requests: write, permission-contents: read}}
- {if: steps.have.outputs.ok, uses: actions/checkout@v6, with: {ref: "${{ github.event.pull_request.head.sha }}", persist-credentials: false}}
- if: steps.have.outputs.ok
env: {GH_TOKEN: "${{ steps.tok.outputs.token }}", R: "${{ github.repository }}", N: "${{ github.event.pull_request.number }}", S: "${{ github.event.pull_request.head.sha }}"}
run: |
printf '#include "gen/c/claw/suggest_feed.c"\n#include <stdio.h>\n#include <stdlib.h>\nint main(void){size_t k=1<<24,n;uint8_t*b=malloc(k),*o=malloc(k);uint32_t s[9];n=fread(b,1,k,stdin);if(n==k)return 3;size_t m=suggest_review(b,n,o,k,s);fprintf(stderr,"claw/suggest: posted %%u, outside the diff %%u, over the caps %%u, too big %%u, unreadable %%u, files %%u, refused %%u, bad input %%u, truncated %%u\\n",s[0],s[1],s[2],s[3],s[4],s[5],s[6],s[7],s[8]);if(m>k)return 4;fwrite(o,1,m,stdout);return 0;}\n' | cc -O1 -w -I . -x c -o /tmp/feed -
gh api --paginate "repos/$R/pulls/$N/files" > /tmp/files.json
{ printf 'S\t%s\n' "$S"; jq -r '.[]|select(.status!="removed" and (.filename|endswith(".t27")))|.filename' /tmp/files.json | while read -r f; do
case "$f" in *[!A-Za-z0-9_./-]*) continue;; esac
git show "$S:$f" > /tmp/blob 2>/dev/null </dev/null || continue
printf 'F\t%s\t%s\n' "$f" "$(wc -c < /tmp/blob)"; cat /tmp/blob
jq -r --arg f "$f" '.[]|select(.filename==$f)|.patch//empty' /tmp/files.json | { grep '^@@' || true; } | sed 's/^/H\t/'
done; } | /tmp/feed > /tmp/review.json 2> /tmp/stats || { echo "::warning::claw/suggest could not build a review"; exit 0; }
cat /tmp/stats >> "$GITHUB_STEP_SUMMARY"
if [ -s /tmp/review.json ]; then gh api -X POST "repos/$R/pulls/$N/reviews" --input /tmp/review.json -q .html_url >> "$GITHUB_STEP_SUMMARY"; fi
4 changes: 3 additions & 1 deletion .github/workflows/spec-guards.yml
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,10 @@ jobs:
./target/release/t27c gen-c specs/claw/gates.t27 > gen/c/claw/gates.c
./target/release/t27c gen-c specs/claw/t27f_gate.t27 > gen/c/claw/t27f_gate.c
./target/release/t27c gen-c specs/claw/sarif_feed.t27 > gen/c/claw/sarif_feed.c
./target/release/t27c gen-c specs/claw/suggest_feed.t27 > gen/c/claw/suggest_feed.c
./target/release/t27c gen-rust specs/tri/fmt_source.t27 > bootstrap/gen/rust/tri/fmt_source.rs
./target/release/t27c gen-json specs/igla/own_model_board.t27 > gen/json/igla/own_model_board.json
git diff --exit-code -- gen/c/claw/gates.c gen/c/claw/t27f_gate.c gen/c/claw/sarif_feed.c gen/json/igla/own_model_board.json
git diff --exit-code -- gen/c/claw/gates.c gen/c/claw/t27f_gate.c gen/c/claw/sarif_feed.c gen/c/claw/suggest_feed.c bootstrap/gen/rust/tri/fmt_source.rs gen/json/igla/own_model_board.json

# #7565: test only the specs this change can affect. specs/ci/affected.t27 picks them (the
# changed specs and every spec that imports one through `use`, transitively); the graph is the
Expand Down
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ reusable workflow. Epic #9271.
| The GitHub App | [github.com/apps/tri-claw](https://github.com/apps/tri-claw), id 5166765, installed on all repositories. It is the reviewer-bee identity ([`tools/bees/README.md`](tools/bees/README.md)): bees approve under its name, so a review is never the author approving itself. It also posts the `claw/t27f` check below |
| T27F check `claw/t27f` (#10268): changed specs and their direct importers, judged by their seals | law [`specs/claw/t27f_gate.t27`](specs/claw/t27f_gate.t27), lowered to `gen/c/claw/t27f_gate.c`; run every 10 minutes by the `claw-t27f` job of `.github/workflows/gate-topology.yml` |
| SARIF alerts `claw/sarif` (#10356): a changed spec that does not parse or is unwritten, as a code-scanning alert | adapter [`specs/claw/sarif_feed.t27`](specs/claw/sarif_feed.t27) over [`specs/claw/sarif.t27`](specs/claw/sarif.t27), lowered to `gen/c/claw/sarif_feed.c`; run on every pull request by the `claw-sarif` job of `.github/workflows/gate-topology.yml` |
| Suggestion review (#10365): a changed spec that `t27c fmt` would reformat, as a "Commit suggestion" review | driver [`specs/claw/suggest_feed.t27`](specs/claw/suggest_feed.t27) over [`specs/claw/suggest.t27`](specs/claw/suggest.t27) and the lossless formatter [`specs/tri/fmt_source.t27`](specs/tri/fmt_source.t27), lowered to `gen/c/claw/suggest_feed.c`; run on every pull request by the `claw-suggest` job of `.github/workflows/gate-topology.yml` |

The `claw/t27f` check: one scheduled job in this repository posts it on every
open pull request that touches `.t27`, in each repository the App is installed
Expand Down
110 changes: 110 additions & 0 deletions bootstrap/gen/rust/tri/fmt_source.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// Generated from .t27 spec
// DO NOT EDIT — generated by t27c
// NOT LOWERED BY THIS BACKEND: 15 test(s), 0 invariant(s), 0 function(s) with no body.
// This backend emits declarations only. The spec's checks live in
// the Zig and Verilog outputs; do not read this file as verified.

pub const TAB_WIDTH: usize = 4;

pub fn put_byte(dst: &mut [u8], cap: usize, w: usize, b: u8) -> usize {
if (w < cap) {
dst[(w) as usize] = b;
}
return (w + 1);
}

pub fn is_space(b: u8) -> bool {
return ((((b == b' ') || (b == b'\t')) || (b == b'\n')) || (b == 13));
}

pub fn line_stop(src: &[u8], n: usize, s: usize) -> usize {
let mut i: usize = s;
while (i < n) {
if (src[(i) as usize] == b'\n') {
return i;
}
i += 1;
}
return n;
}

pub fn trim_end(src: &[u8], s: usize, e: usize) -> usize {
let mut x: usize = e;
while (x > s) {
let b: u8 = src[((x - 1)) as usize];
if (((b != b' ') && (b != b'\t')) && (b != 13)) {
return x;
}
x -= 1;
}
return x;
}

pub fn fmt_source(src: &[u8], n: usize, out: &mut [u8], cap: usize) -> usize {
let mut w: usize = 0;
let mut pending: usize = 0;
let mut ls: usize = 0;
while (ls < n) {
let le: usize = line_stop(src, n, ls);
let ee: usize = trim_end(src, ls, le);
if (ee == ls) {
pending += 1;
} else {
while (pending > 0) {
w = put_byte(out, cap, w, b'\n');
pending -= 1;
}
let mut i: usize = ls;
while ((i < ee) && ((src[(i) as usize] == b' ') || (src[(i) as usize] == b'\t'))) {
if (src[(i) as usize] == b'\t') {
w = put_byte(out, cap, w, b' ');
w = put_byte(out, cap, w, b' ');
w = put_byte(out, cap, w, b' ');
w = put_byte(out, cap, w, b' ');
} else {
w = put_byte(out, cap, w, b' ');
}
i += 1;
}
while (i < ee) {
w = put_byte(out, cap, w, src[(i) as usize]);
i += 1;
}
w = put_byte(out, cap, w, b'\n');
}
ls = (le + 1);
}
return w;
}

pub fn next_solid(t: &[u8], n: usize, p: usize) -> usize {
let mut i: usize = p;
while (i < n) {
if (is_space(t[(i) as usize]) == false) {
return i;
}
i += 1;
}
return n;
}

pub fn fmt_exact(a: &[u8], an: usize, b: &[u8], bn: usize) -> bool {
let mut i: usize = next_solid(a, an, 0);
let mut j: usize = next_solid(b, bn, 0);
while ((i < an) && (j < bn)) {
if (a[(i) as usize] != b[(j) as usize]) {
return false;
}
i = next_solid(a, an, (i + 1));
j = next_solid(b, bn, (j + 1));
}
return ((i >= an) && (j >= bn));
}

pub fn fmt_accept(src: &[u8], n: usize, out: &[u8], m: usize, cap: usize) -> bool {
if (m > cap) {
return false;
}
return fmt_exact(src, n, out, m);
}

Loading
Loading