Repository navigation
build: make jaffascript's own justfile a jaffa just module - #79
Conversation
The root held both `Justfile` (the RSR template) and `justfile` (jaffascript's runner). A bare `just` refused with "multiple candidate justfiles", and a case-insensitive checkout keeps only one of them. The recipe names default, run, build and lint exist in both, so a plain `import` would collide. The owner chose a module (2026-10-09). - justfile -> jaffa.just (content unchanged apart from its header line and `default`, which now lists the module's own recipes). - Justfile and .machine_readable/contractiles/Justfile (still byte-identical): `mod? jaffa "jaffa.just"` after the existing `import? "contractile.just"`. Optional, as that import is, so the contractiles copy still parses where jaffa.just does not exist. - README.adoc, EXPLAINME.adoc, .github/CONTRIBUTING.md: `just jaffa <task>`. - .editorconfig and .gitattributes: the `justfile` entries become `*.just`, which also covers contractile.just. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GpUzjdhWFi26k6s7AWxYcf
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 53 minutes. View limit detailsLimit details: You’ve used the included review currently available. Review configuration: ⚙️ Run configuration
📒 Files selected for processing (8)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
🔍 Hypatia Security ScanFindings: 53 issues detected
View findings[
{
"reason": "Job `triage` in label-triage.yml has no `timeout-minutes:` declaration. Default is 6 hours — a stuck codeload fetch or runner hang can burn budget. Add `timeout-minutes: 10` (or proportional).",
"type": "missing_timeout_minutes",
"file": ".github/workflows/label-triage.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium",
"recipe_id": "recipe-add-workflow-timeout-minutes",
"job": "triage"
},
{
"reason": "Job `sync` in labels.yml has no `timeout-minutes:` declaration. Default is 6 hours — a stuck codeload fetch or runner hang can burn budget. Add `timeout-minutes: 10` (or proportional).",
"type": "missing_timeout_minutes",
"file": ".github/workflows/labels.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium",
"recipe_id": "recipe-add-workflow-timeout-minutes",
"job": "sync"
},
{
"line": 38,
"reason": "job in .github/workflows/labels.yml references `secrets.*` but does not install `step-security/harden-runner` — review outbound-egress monitoring",
"type": "RE001",
"file": ".github/workflows/labels.yml",
"action": "report",
"rule_module": "research_extensions",
"severity": "medium"
},
{
"line": 44,
"reason": "job in .github/workflows/push-email-notify.yml references `secrets.*` but does not install `step-security/harden-runner` — review outbound-egress monitoring",
"type": "RE001",
"file": ".github/workflows/push-email-notify.yml",
"action": "report",
"rule_module": "research_extensions",
"severity": "medium"
},
{
"line": 82,
"reason": "job in .github/workflows/hypatia-scan.yml references `secrets.*` but does not install `step-security/harden-runner` — review outbound-egress monitoring",
"type": "RE001",
"file": ".github/workflows/hypatia-scan.yml",
"action": "report",
"rule_module": "research_extensions",
"severity": "medium"
},
{
"line": 52,
"reason": "job in .github/workflows/label-triage.yml references `secrets.*` but does not install `step-security/harden-runner` — review outbound-egress monitoring",
"type": "RE001",
"file": ".github/workflows/label-triage.yml",
"action": "report",
"rule_module": "research_extensions",
"severity": "medium"
},
{
"line": 33,
"reason": "workflow .github/workflows/labels.yml:33 job `sync` has no `timeout-minutes:` — defaults to 360 min on hang",
"type": "WH006",
"file": ".github/workflows/labels.yml",
"action": "report",
"rule_module": "workflow_hardening",
"severity": "medium"
},
{
"line": 47,
"reason": "workflow .github/workflows/label-triage.yml:47 job `triage` has no `timeout-minutes:` — defaults to 360 min on hang",
"type": "WH006",
"file": ".github/workflows/label-triage.yml",
"action": "report",
"rule_module": "workflow_hardening",
"severity": "medium"
},
{
"line": null,
"reason": "workflow .github/workflows/hypatia-scan.yml uploads SARIF to code scanning but masks the scanner's failure (`|| true` / `|| echo 0`) and never asserts the findings artefact is a non-empty array. When the scanner fails, this uploads a SARIF with zero results, and GitHub AUTO-CLOSES every previously-open alert for that category — silently, with the job green.",
"type": "WH014",
"file": ".github/workflows/hypatia-scan.yml",
"action": "report",
"rule_module": "workflow_hardening",
"severity": "high"
},
{
"reason": "Code scanning (Hypatia): hypatia/workflow_audit/missing_timeout_minutes -- Hypatia workflow_audit: missing_timeout_minutes -- 7 day(s) old",
"type": "CSA001",
"file": ".github/workflows/labels.yml",
"action": "review",
"rule_module": "code_scanning_alerts",
"severity": "medium"
}
]Powered by Hypatia Neurosymbolic CI/CD Intelligence |
|
🔍 Hypatia Security ScanFindings: 53 issues detected
View findings[
{
"reason": "Job `triage` in label-triage.yml has no `timeout-minutes:` declaration. Default is 6 hours — a stuck codeload fetch or runner hang can burn budget. Add `timeout-minutes: 10` (or proportional).",
"type": "missing_timeout_minutes",
"file": ".github/workflows/label-triage.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium",
"recipe_id": "recipe-add-workflow-timeout-minutes",
"job": "triage"
},
{
"reason": "Job `sync` in labels.yml has no `timeout-minutes:` declaration. Default is 6 hours — a stuck codeload fetch or runner hang can burn budget. Add `timeout-minutes: 10` (or proportional).",
"type": "missing_timeout_minutes",
"file": ".github/workflows/labels.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium",
"recipe_id": "recipe-add-workflow-timeout-minutes",
"job": "sync"
},
{
"line": 38,
"reason": "job in .github/workflows/labels.yml references `secrets.*` but does not install `step-security/harden-runner` — review outbound-egress monitoring",
"type": "RE001",
"file": ".github/workflows/labels.yml",
"action": "report",
"rule_module": "research_extensions",
"severity": "medium"
},
{
"line": 44,
"reason": "job in .github/workflows/push-email-notify.yml references `secrets.*` but does not install `step-security/harden-runner` — review outbound-egress monitoring",
"type": "RE001",
"file": ".github/workflows/push-email-notify.yml",
"action": "report",
"rule_module": "research_extensions",
"severity": "medium"
},
{
"line": 82,
"reason": "job in .github/workflows/hypatia-scan.yml references `secrets.*` but does not install `step-security/harden-runner` — review outbound-egress monitoring",
"type": "RE001",
"file": ".github/workflows/hypatia-scan.yml",
"action": "report",
"rule_module": "research_extensions",
"severity": "medium"
},
{
"line": 52,
"reason": "job in .github/workflows/label-triage.yml references `secrets.*` but does not install `step-security/harden-runner` — review outbound-egress monitoring",
"type": "RE001",
"file": ".github/workflows/label-triage.yml",
"action": "report",
"rule_module": "research_extensions",
"severity": "medium"
},
{
"line": 33,
"reason": "workflow .github/workflows/labels.yml:33 job `sync` has no `timeout-minutes:` — defaults to 360 min on hang",
"type": "WH006",
"file": ".github/workflows/labels.yml",
"action": "report",
"rule_module": "workflow_hardening",
"severity": "medium"
},
{
"line": 47,
"reason": "workflow .github/workflows/label-triage.yml:47 job `triage` has no `timeout-minutes:` — defaults to 360 min on hang",
"type": "WH006",
"file": ".github/workflows/label-triage.yml",
"action": "report",
"rule_module": "workflow_hardening",
"severity": "medium"
},
{
"line": null,
"reason": "workflow .github/workflows/hypatia-scan.yml uploads SARIF to code scanning but masks the scanner's failure (`|| true` / `|| echo 0`) and never asserts the findings artefact is a non-empty array. When the scanner fails, this uploads a SARIF with zero results, and GitHub AUTO-CLOSES every previously-open alert for that category — silently, with the job green.",
"type": "WH014",
"file": ".github/workflows/hypatia-scan.yml",
"action": "report",
"rule_module": "workflow_hardening",
"severity": "high"
},
{
"reason": "Code scanning (Hypatia): hypatia/workflow_audit/missing_timeout_minutes -- Hypatia workflow_audit: missing_timeout_minutes -- 7 day(s) old",
"type": "CSA001",
"file": ".github/workflows/labels.yml",
"action": "review",
"rule_module": "code_scanning_alerts",
"severity": "medium"
}
]Powered by Hypatia Neurosymbolic CI/CD Intelligence |
…a hello` runs (#80) ## Summary This makes `just jaffa hello` run. On `main` (`16fb94a`) it fails with `Runtime error: Unhandled effect: println`, and so do `bin/jaffa eval examples/hello.affine` and the README's `eval` example. **The cause is in the example, not in affinescript.** `examples/hello.affine` declared its own effect: ``` effect IO { fn println(s: String) -> (); } ``` AffineScript already has a builtin `println`, typed `String -{IO}-> ()` (`affinescript` `lib/typecheck.ml:1824`). The declaration shadows that builtin with an effect operation. `eval` then performs the operation, finds no handler, and stops. The exit code 124 is affinescript's own error code. It is not a timeout: the run takes under a second, and a "Module not found" error returns 124 as well. I had earlier reported this as an affinescript 0.1.1 interpreter bug (in #79's Testing table and in my report to the owner). That was wrong. ## Changes - **`examples/hello.affine`:** the `effect IO { … }` block is removed. A short comment explains why it must not come back. `main` keeps its `-{IO}->` annotation, which now names the builtin's effect. - **`README.adoc` "Hello" section:** its copy of the example gets the same change, so the README shows the source that runs. ### Not changed - **The example's comment** says it exercises `let` and `===`, which it does not use. That was true before this PR too; making the example match the comment is a separate change. - **`docs/AFFIRMATION.adoc` and `docs/affirmations/AFFIRMATION-2026-10-07.adoc`.** The 10-07 affirmation (line 178) records that the README's `eval` example fails. Once this merges, that describes the repo as it was when signed. Agents do not edit signed affirmations; re-affirming is the owner's decision. - **The upstream affinescript examples** (`examples/hello.affine`, `examples/faces/hello-jaffa.affine`) fail the same way, and `hello-jaffa.affine` also fails with `Module 'io' not found`. affinescript is not changed here; the finding is logged for its owner. - `eval` prints the string with its quotes (`"Hello, JaffaScript!"`). That is how the interpreter displays the value, not something this repo controls. ## 📌 New pins - **Head SHA: `4d5c674e2d153fc54b8bd992c052da3f3e50a4d3`** - None. No action `uses:`, `actions.lock`, lockfile or container digest is added or changed. ## RSR Quality Checklist ### Required - [x] Tests pass: there is no test suite for examples. Each recipe was run on the new file (see Testing). - [ ] Code is formatted: no AffineScript formatter gate here. `affinescript lint --face jaffa` reports `No issues found`. - [x] Linter is clean: `affinescript lint` as above, and `asciidoctor --failure-level=WARN` passes on `README.adoc`. - [x] No banned language patterns: nothing added. - [ ] No `unsafe` blocks: n/a, no Rust changed. - [ ] No banned functions: n/a, no proofs changed. - [x] SPDX license headers present: `examples/hello.affine` keeps its `MPL-2.0` header; `README.adoc` keeps its header. - [x] No secrets, credentials, or `.env` files. ### As Applicable - [ ] `.machine_readable/*.a2ml`: no. A2ML is retired. - [x] Documentation updated: `README.adoc`'s copy of the example. - [ ] `TOPOLOGY.md`: n/a. - [ ] `CHANGELOG`: not updated; this is an example fix. - [ ] New dependencies: none. - [ ] ABI/FFI: n/a. ## Testing All runs used just 1.56.0 and affinescript 0.1.1, in this branch's worktree at `4d5c674`. | Command | `main` `16fb94a` | This head | |---|---|---| | `just jaffa hello` | **rc 124**, `Unhandled effect: println` | rc 0, prints `"Hello, JaffaScript!"` | | `just jaffa run examples/hello.affine` | rc 124, same error | rc 0 | | `just jaffa check examples/hello.affine` | rc 0 | rc 0, `Type checking passed` | | `just jaffa build examples/hello.affine <tmp>/hello.wasm` | not run | rc 0, a 315-byte WASM module | | `just jaffa preview examples/hello.affine` | not run | rc 0, prints the canonical lowering (`fn main`, `let greeting`) | | `just jaffa lint examples/hello.affine` | not run | rc 0, `No issues found` | | `./bin/jaffa eval` / `check` / `compile` on the example | `eval` rc 124 | all rc 0 | | The README's `[source,affine]` block, extracted and run with `eval` | rc 124 | rc 0 | - **Control:** the original file, kept as a copy outside the repo, still fails with `Unhandled effect: println` (rc 124) under the same binary. So the pass above comes from the change, not from the environment. - **Docstrings:** no functions are added or changed. ## Red checks on this head To be filled in once CI has run on this head. ## Screenshots n/a, no UI change. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01GpUzjdhWFi26k6s7AWxYcf Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>



Summary
This makes jaffascript's own task runner a
jaffajust module, the option the owner chose on 2026-10-09.The repo root held two justfiles:
Justfile(the RSR template, 1,545 lines) andjustfile(jaffascript's 29-line runner foraffinescript … --face jaffa). As a result:justin the root failed witherror: multiple candidate justfiles found … Justfile and justfile(rc 1).default,run,buildandlintexist in both files, so a plainimportwould collide.A module keeps the two sets of recipes apart. jaffa's recipes now run as
just jaffa <recipe>.Changes
justfile→jaffa.just(git sees a rename). Two lines change:defaultnow runs@just --list jaffa. It used to run@just --list, which inside a module lists the root Justfile's ~100 template recipes instead of jaffa's own.Justfileand.machine_readable/contractiles/Justfile(still byte-identical, checked withcmp):mod? jaffa "jaffa.just"plus a one-line comment, right after the existingimport? "contractile.just".mod?), for the same reason that import is optional. The contractiles copy sits in a directory withoutjaffa.justand must still parse.jaffa.justis ever deleted,just jaffa …reports an unknown recipe instead of a missing module file.README.adoc: the "via the justfile" example now readsjust jaffa run …/just jaffa preview ….EXPLAINME.adoc: the file-table row is nowjaffa.just, run asjust jaffa <task>, and addshello..github/CONTRIBUTING.md:18:just check→just jaffa check examples/hello.affine. The old line could not work: there is no rootcheckrecipe, and jaffa'schecktakes a file..editorconfig[justfile]→[*.just], and.gitattributesjustfile→*.just. Both now also covercontractile.just. Onmainthat file gottext=auto eol=lffrom the catch-all rule; it now getstext eol=lf. Its index and working-tree endings are LF either way (git ls-files --eol:i/lf w/lf).Not changed
docs/AFFIRMATION.adoc:202-204, 246anddocs/affirmations/AFFIRMATION-2026-10-07.adoc:182-184, 218. These signed AFFIRMATIONs say "justcannot run here" because of the two justfiles. Once this merges, that statement describes the repo as it was when it was signed. Re-affirming is the owner's decision, so agents do not edit them..machine_readable/STATE.a2mlmentions the justfile, but A2ML is retired, so it is untouched.just(justfile)" lines in.machine_readable/ai/.{cline,cursor,windsurf}rulesanddocs/practice/AI-CONVENTIONS.adoc, andROADMAP.adoc:14(a completed item). Each is still true.setup.sh:199accepts eitherJustfileorjustfile.Justfilestill exists.📌 New pins
3d02901c804ee4d53e488901d68e8c3c253a608c("Update branch" onto ci: pin the standards reusable workflows to #1209's merge (2e12b312) #78; the change itself is900179b45003b4f42179b1145c68c5fabe786189)uses:,actions.lock, lockfile or container digest is added or changed.RSR Quality Checklist
Required
just --summaryparses both Justfiles andjaffa.just. There is no separate just formatter gate here.asciidoctor --failure-level=WARNpasses on both edited.adocfiles.unsafeblocks: n/a, no Rust changed.jaffa.justkeepsMPL-2.0. Every other edited file keeps its existing header..envfiles.As Applicable
.machine_readable/*.a2ml: no. A2ML is retired.README.adoc,EXPLAINME.adoc,.github/CONTRIBUTING.md.TOPOLOGY.md: n/a.CHANGELOG: not updated, because it is a task-runner rename.Testing
All runs used just 1.56.0 and affinescript 0.1.1, in this worktree at
900179b. "Main" meansmainat809e521.just --list(bare, root)multiple candidate justfiles foundjaffa ...just jaffa(moduledefault)just jaffa check examples/hello.affineType checking passed(runsaffinescript check --face jaffa …)just jaffa hellojust --justfile justfile hello: rc 124,Runtime error: Unhandled effect: printlnjust --justfile .machine_readable/contractiles/Justfile --summarymod?is skipped there)just validate-rsrjust --justfile Justfile validate-rsr: rc 1,MISSING:the 3 retired.a2mlpathsjust jaffa hellofails onmaintoo. The failure is the affinescript 0.1.1 interpreter not handling theprintlneffect, not this change. It is reported separately.git merge-tree --write-treeof this head with ci: pin the standards reusable workflows to #1209's merge (2e12b312) #78's head (ac2edb2) exits 0. Positive control: a planted conflicting edit to.github/workflows/governance.ymlmakes it exit 1..githooks/docstring-scan.sh --range origin/main..HEAD --checkfinds 0 touched functions.Red checks on this head
Outcome
Merged 2026-10-09T00:47:24Z as
16fb94a, after "Update branch" moved the head to3d02901(#78 had merged at 00:46:37Z).main16fb94a,governance / Actions lockfile verifyis SUCCESS (job 113614527134). The failure on the earlier head900179b(job 113613430191,MISSING-LOCK DEBT, exit 3) came from the900c42c7pin it inherited, and ci: pin the standards reusable workflows to #1209's merge (2e12b312) #78 fixed that.squabble verify-satisfied hyperpolymath/jaffascript 79at 00:50:55Z: exit 0, DONE, no agent items.refs/pull/79/mergeare all already open onmain(61), so PR-minus-main is empty. Planted control: an alert number added only to the PR set is reported.As read before merge
Read 2026-10-09T00:5xZ via
gh pr checks(GraphQL): 27 pass, 1 fail.governance / Actions lockfile verifyfails, and the cause ismain, not this PR. This branch starts frommain809e521, whose governance pin is still900c42c7. The job (113613430191) runsgovernance-reusable.yml@900c42c7…and exits 3 withMISSING-LOCK DEBT, the same asmain(job 113610554625). ci: pin the standards reusable workflows to #1209's merge (2e12b312) #78 fixes it. After ci: pin the standards reusable workflows to #1209's merge (2e12b312) #78 merges, update this branch and the check re-runs against2e12b312. This PR touches no workflow.squabble verify-satisfied, for the same reason as on ci: pin the standards reusable workflows to #1209's merge (2e12b312) #78 (REST rate limit at 00:43Z).Screenshots
n/a, no UI change.
🤖 Generated with Claude Code
https://claude.ai/code/session_01GpUzjdhWFi26k6s7AWxYcf