Skip to content

build: make jaffascript's own justfile a jaffa just module - #79

Merged
hyperpolymath merged 2 commits into
mainfrom
claude/justfile-as-jaffa-module
Oct 9, 2026
Merged

hyperpolymath merged 2 commits into
mainfrom
claude/justfile-as-jaffa-module

Conversation

@hyperpolymath

@hyperpolymath hyperpolymath commented Oct 9, 2026 •

Copy link
Copy Markdown
Owner

Summary

This makes jaffascript's own task runner a jaffa just module, the option the owner chose on 2026-10-09.

The repo root held two justfiles: Justfile (the RSR template, 1,545 lines) and justfile (jaffascript's 29-line runner for affinescript … --face jaffa). As a result:

  • A bare just in the root failed with error: multiple candidate justfiles found … Justfile and justfile (rc 1).
  • A case-insensitive checkout (Windows, macOS) keeps only one of the two files.
  • The recipe names default, run, build and lint exist in both files, so a plain import would 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:
    • The header comment now names the file and how to run it.
    • default now 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.
  • Justfile and .machine_readable/contractiles/Justfile (still byte-identical, checked with cmp): mod? jaffa "jaffa.just" plus a one-line comment, right after the existing import? "contractile.just".
    • The module is optional (mod?), for the same reason that import is optional. The contractiles copy sits in a directory without jaffa.just and must still parse.
    • The cost: if jaffa.just is ever deleted, just jaffa … reports an unknown recipe instead of a missing module file.
  • README.adoc: the "via the justfile" example now reads just jaffa run … / just jaffa preview ….
  • EXPLAINME.adoc: the file-table row is now jaffa.just, run as just jaffa <task>, and adds hello.
  • .github/CONTRIBUTING.md:18: just check → just jaffa check examples/hello.affine. The old line could not work: there is no root check recipe, and jaffa's check takes a file.
  • .editorconfig [justfile] → [*.just], and .gitattributes justfile → *.just. Both now also cover contractile.just. On main that file got text=auto eol=lf from the catch-all rule; it now gets text 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, 246 and docs/affirmations/AFFIRMATION-2026-10-07.adoc:182-184, 218. These signed AFFIRMATIONs say "just cannot 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.a2ml mentions the justfile, but A2ML is retired, so it is untouched.
  • Generic "use just (justfile)" lines in .machine_readable/ai/.{cline,cursor,windsurf}rules and docs/practice/AI-CONVENTIONS.adoc, and ROADMAP.adoc:14 (a completed item). Each is still true.
  • setup.sh:199 accepts either Justfile or justfile. Justfile still exists.

📌 New pins

RSR Quality Checklist

Required

  • Tests pass: n/a, no source or test changed. Each recipe was run (see Testing).
  • Code is formatted: just --summary parses both Justfiles and jaffa.just. There is no separate just formatter gate here.
  • Linter is clean: asciidoctor --failure-level=WARN passes on both edited .adoc files.
  • No banned language patterns: nothing added.
  • No unsafe blocks: n/a, no Rust changed.
  • No banned functions: n/a, no source or proofs changed.
  • SPDX license headers present: jaffa.just keeps MPL-2.0. Every other edited file keeps its existing header.
  • No secrets, credentials, or .env files.

As Applicable

  • .machine_readable/*.a2ml: no. A2ML is retired.
  • Documentation updated: README.adoc, EXPLAINME.adoc, .github/CONTRIBUTING.md.
  • TOPOLOGY.md: n/a.
  • CHANGELOG: not updated, because it is a task-runner rename.
  • New dependencies: none.
  • ABI/FFI: n/a.

Testing

All runs used just 1.56.0 and affinescript 0.1.1, in this worktree at 900179b. "Main" means main at 809e521.

Command Main This head
just --list (bare, root) rc 1, multiple candidate justfiles found rc 0. The listing includes jaffa ...
just jaffa (module default) n/a rc 0. Lists only the 7 jaffa recipes
just jaffa check examples/hello.affine n/a rc 0, Type checking passed (runs affinescript check --face jaffa …)
just jaffa hello just --justfile justfile hello: rc 124, Runtime error: Unhandled effect: println rc 124, identical
just --justfile .machine_readable/contractiles/Justfile --summary n/a rc 0 (the mod? is skipped there)
just validate-rsr only as just --justfile Justfile validate-rsr: rc 1, MISSING: the 3 retired .a2ml paths runs bare: rc 1, the same 3 paths. Unchanged; the recipe predates the A2ML retirement

Red checks on this head

Outcome

Merged 2026-10-09T00:47:24Z as 16fb94a, after "Update branch" moved the head to 3d02901 (#78 had merged at 00:46:37Z).

  • On main 16fb94a, governance / Actions lockfile verify is SUCCESS (job 113614527134). The failure on the earlier head 900179b (job 113613430191, MISSING-LOCK DEBT, exit 3) came from the 900c42c7 pin it inherited, and ci: pin the standards reusable workflows to #1209's merge (2e12b312) #78 fixed that.
  • squabble verify-satisfied hyperpolymath/jaffascript 79 at 00:50:55Z: exit 0, DONE, no agent items.
  • Code scanning: the 52 open alerts on refs/pull/79/merge are all already open on main (61), so PR-minus-main is empty. Planted control: an alert number added only to the PR set is reported.
  • Not done: the full App census. REST was rate-limited again at 00:51:33Z.

As read before merge

Read 2026-10-09T00:5xZ via gh pr checks (GraphQL): 27 pass, 1 fail.

Screenshots

n/a, no UI change.

🤖 Generated with Claude Code

https://claude.ai/code/session_01GpUzjdhWFi26k6s7AWxYcf

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
@coderabbitai

coderabbitai Bot commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

You'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.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: f8c350fa-7a79-422f-b8c2-43bcdf1ea09b
📥 Commits

Reviewing files that changed from the base of the PR and between 4b6eecd and 3d02901.

📒 Files selected for processing (8)
  • .editorconfig
  • .gitattributes
  • .github/CONTRIBUTING.md
  • .machine_readable/contractiles/Justfile
  • EXPLAINME.adoc
  • Justfile
  • README.adoc
  • jaffa.just
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown

🔍 Hypatia Security Scan

Findings: 53 issues detected

Severity Count
🔴 Critical 6
🟠 High 20
🟡 Medium 27

⚠️ Action Required: Critical security issues found!

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

@hyperpolymath
hyperpolymath enabled auto-merge (squash) October 9, 2026 00:47
@sonarqubecloud

sonarqubecloud Bot commented Oct 9, 2026

Copy link
Copy Markdown

@hyperpolymath
hyperpolymath merged commit 16fb94a into main Oct 9, 2026
26 checks passed
@hyperpolymath
hyperpolymath deleted the claude/justfile-as-jaffa-module branch October 9, 2026 00:47
@github-actions

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown

🔍 Hypatia Security Scan

Findings: 53 issues detected

Severity Count
🔴 Critical 6
🟠 High 20
🟡 Medium 27

⚠️ Action Required: Critical security issues found!

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

hyperpolymath added a commit that referenced this pull request Oct 9, 2026
…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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant