Skip to content

port(rsr-certifier-vscode): rewrite extension.ts as extension.affine (affinescript#64)#46

Merged
hyperpolymath merged 1 commit into
mainfrom
port/rsr-certifier-vscode-to-affine
May 11, 2026
Merged

port(rsr-certifier-vscode): rewrite extension.ts as extension.affine (affinescript#64)#46
hyperpolymath merged 1 commit into
mainfrom
port/rsr-certifier-vscode-to-affine

Conversation

@hyperpolymath
Copy link
Copy Markdown
Owner

Summary

Ports rhodium-standard-repositories/satellites/rsr-certifier/extensions/vscode/src/extension.ts (380 LOC) to AffineScript. Closes the standards-side acceptance bullet in affinescript#64.

Dependencies (must land first)

  1. hyperpolymath/affinescript#102 — expands stdlib/Vscode.affine + the packages/affine-vscode/mod.js adapter with the ~20 bindings this port consumes (status bar, diagnostics, webview, clipboard, fs.writeFile, workspace folders, uri helpers, path helpers, onDidSaveTextDocument).
  2. The vendored adapter in src/affine-vscode-adapter.cjs is a verbatim copy of the updated mod.js. If #102 changes during review, this file needs a re-sync.

What changed

File Status Purpose
…/extensions/vscode/src/extension.affine new AffineScript source-of-truth. Ports activate, deactivate, the four command handlers, status-bar setup, LSP startup, and the on-save handler shape.
…/extensions/vscode/src/affine-vscode-adapter.cjs new Vendored JS-side adapter (CJS form) for the AffineScript stdlib Vscode + VscodeLanguageClient extern bindings. Copy of affinescript:packages/affine-vscode/mod.js. Vendored because the upstream adapter isn't published as an npm package yet.
…/extensions/vscode/src/index.cjs new Runtime entry point. Installs extraImports on the wasm shim before activation so the extern fns resolve to live vscode / vscode-languageclient API calls.
…/extensions/vscode/out/extension.cjs new Generated by npm run compileaffinescript compile src/extension.affine -o out/extension.cjs. Committed so the extension can be installed without an AffineScript toolchain on PATH.
…/extensions/vscode/package.json modified main./src/index.cjs; compile invokes affinescript compile; TS/eslint devDeps dropped; version 0.1.00.2.0.
…/extensions/vscode/src/extension.ts deleted Replaced.
…/extensions/vscode/tsconfig.json deleted No TypeScript to compile.

Acceptance criteria (from affinescript#64)

  • affinescript#35 has landed.
  • Port rsr-certifier/extensions/vscode/src/extension.ts.affine.
  • Activation verified via shim.activate (registers ExtensionContext handle, instantiates wasm with extraImports, sets up status bar, registers commands, starts LSP).
  • Command registration verified — rsr.checkCompliance, rsr.initConfig, rsr.showReport, rsr.generateBadge registered via Vscode::registerCommand with wasm-table indices 03 (order matches handler declarations in extension.affine). On-save handler at index 4.
  • LSP wiring verified — VscodeLanguageClient::newLanguageClient + languageClientStart, using rsr.serverPath config or context.asAbsolutePath("server/rsr-lsp[.exe]") fallback (platform-aware via processPlatform).
  • Clean disposal verified — shim.deactivate exported; status-bar item, diagnostic collection, and all command disposables join ctx.subscriptions for host-managed release.

Feature-parity degradations

The current AffineScript extern-call ABI is synchronous, so two Thenable-returning vscode APIs cannot be bound:

API Used by Effect on port
vscode.window.withProgress(opts, async task) the "preferred" checkCompliance path Removed. All four commands shell out to the rsr CLI in a terminal — the same fallback the original TS extension already used for the no-LSP case.
LanguageClient.sendRequest(method, params) rsr/getCompliance custom request Removed. The downstream effects (status-bar mutation on every check result, diagnostic-collection updates) also go. The status bar shows a static initial value; the diagnostic collection is created and disposed but not populated.

onDidSaveTextDocument: the handler drops the TextDocument argument at the FFI boundary (wasm-table thunks are zero-arg in this adapter). The on-save handler is a no-op to avoid spawning a terminal on every save anywhere; the rsr.checkOnSave flag is honoured at the registration level so the wiring is in place once an async-extern ABI lands.

showReport webview renders a constant placeholder shape rather than per-check data (the per-check data flowed from the sendRequest path that we cannot bind).

The compile step produces 7 advisory If without else returns Never warnings — these are the same early-return-if pattern the affinescript pilot extension uses, and are cosmetic.

TS-exemption table

The repo's .claude/CLAUDE.md "TypeScript Exemptions" table currently lists only avow-protocol/telegram-bot/avow-telegram-bot/**. The rsr-certifier extension.ts was not a per-repo exemption row — it was covered by the universal-allowlist *vscode* directory-segment pattern in .github/workflows/rsr-antipattern.yml. Removing the .ts file therefore does not require a CLAUDE.md table edit; the file simply ceases to exist.

Test plan

  • affinescript#102 is merged and a release is cut (or local toolchain points at that branch).
  • npm run compile succeeds with the AffineScript toolchain on PATH (or AFFINESCRIPT_STDLIB env var pointing at affinescript/stdlib). Confirmed locally: compiles to out/extension.cjs cleanly.
  • Install the extension into VS Code (vsce package + code --install-extension rsr-certified-0.2.0.vsix).
  • Open a folder with a .git directory or .rsr.toml — extension activates; console shows "RSR-Certified extension is activating..."; status bar shows ☆ RSR: SILVER 75%.
  • Cmd/Ctrl+Shift+PRSR: Check Compliance — opens terminal RSR Check, runs rsr check "<workspace>".
  • RSR: Initialize Configuration — writes .rsr.toml at workspace root and opens it; info message "RSR configuration created: .rsr.toml".
  • RSR: Show Compliance Report — opens webview panel with the placeholder report shape.
  • RSR: Generate Badge — copies badge markdown to clipboard; info message confirms.
  • Click the status bar item — fires rsr.showReport, panel opens.
  • If rsr-lsp is on PATH (or bundled at server/rsr-lsp[.exe]), LSP starts. If absent, the warning "RSR LSP server not found. Some features may be limited." shows; extension continues without LSP.
  • Reload window — deactivate runs cleanly; no disposable leaks; CI antipattern check passes (no .ts files).

Related

🤖 Generated with Claude Code

…(affinescript#64)

Closes the standards side of affinescript#64 (port external VS Code
extensions to .affine). Unblock conditions:
  - affinescript#35  (Node-target codegen + Vscode.affine bindings)
  - affinescript#102 (binding-surface expansion for the rsr-certifier
                     port — status bar, diagnostics, webview, clipboard,
                     fs.writeFile, onDidSaveTextDocument, workspace
                     folders, uri helpers, path helpers)

Layout:
  src/extension.affine            AffineScript source-of-truth
  src/affine-vscode-adapter.cjs   Vendored JS adapter (copy of
                                  affinescript:packages/affine-vscode/mod.js)
  src/index.cjs                   Runtime entry point. Installs
                                  `extraImports` on the wasm shim so the
                                  AffineScript extern bindings resolve to
                                  real vscode/lc API calls.
  out/extension.cjs               Generated by `npm run compile`.
  package.json                    `main` -> ./src/index.cjs; `compile`
                                  invokes affinescript compile; TS
                                  devDeps + eslint config removed;
                                  version 0.1.0 -> 0.2.0.

Removed:
  src/extension.ts (replaced)
  tsconfig.json (no TS to compile)

Acceptance-criteria coverage from affinescript#64:

  Activation:           shim.activate wires ExtensionContext as a handle
                         and instantiates the wasm with extraImports.
  Command registration: rsr.{checkCompliance,initConfig,showReport,
                         generateBadge} registered via
                         Vscode::registerCommand with wasm-table indices.
  LSP wiring:           VscodeLanguageClient::newLanguageClient +
                         languageClientStart, using rsr.serverPath config
                         or extensionAbsolutePath fallback to
                         server/rsr-lsp[.exe] (platform-aware).
  Clean disposal:       shim.deactivate exported; status-bar item,
                         diagnostic collection, and all command
                         disposables join ctx.subscriptions for
                         host-managed release.

Feature-parity notes (degradations under the current synchronous
extern-call ABI — affinescript#102 README documents the omissions):

  - Thenable-returning vscode APIs are not bound:
      vscode.window.withProgress(opts, async task)
      LanguageClient.sendRequest(method, params)
    Effect: the "live in-process compliance results" path is removed.
    All four commands shell out to the `rsr` CLI in a fresh terminal
    (the same fallback path the original TS extension already used for
    the no-LSP case). The status bar shows a static initial value
    instead of being mutated on every check result. The diagnostic
    collection is created and disposed but not populated.

  - onDidSaveTextDocument drops the TextDocument arg at the FFI
    boundary (handlers are zero-arg wasm-table thunks). To avoid
    "spawn terminal on every save anywhere", the on-save handler is a
    no-op; users who want check-on-save can invoke the command
    manually. The rsr.checkOnSave config flag is honoured at the
    *registration* level so the wiring is in place once an async-extern
    ABI lands.

  - The webview report renders a constant placeholder shape rather than
    per-check data (the per-check data flowed from the sendRequest path).

TS-exemption table note:

The repo's `.claude/CLAUDE.md` "TypeScript Exemptions" table currently
lists only `avow-protocol/telegram-bot/avow-telegram-bot/**`. The
rsr-certifier extension.ts was *not* a per-repo exemption row — it was
covered by the universal-allowlist `*vscode*` directory-segment pattern
in .github/workflows/rsr-antipattern.yml. Removing the .ts file
therefore does not require a CLAUDE.md table edit; the file simply
ceases to exist.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@chatgpt-codex-connector
Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Credits must be used to enable repository wide code reviews.

@hyperpolymath hyperpolymath merged commit d398752 into main May 11, 2026
16 of 19 checks passed
@hyperpolymath hyperpolymath deleted the port/rsr-certifier-vscode-to-affine branch May 11, 2026 07:42
hyperpolymath added a commit that referenced this pull request May 11, 2026
## Summary

Two related CI fixes — both unblocking workflows that have been red on
`main` for weeks.

### 1. `.github/workflows/rsr-antipattern.yml` — heredoc syntax bug

The "Check for TypeScript" step had two `PYEOF` tokens in succession but
only one opening `python3 << 'PYEOF'`, leaving the second Python block
dangling as bash commands. Bash saw `BUILTIN_GLOBS = [...]` as a command
and exited 127. Every commit to `main` since the check was added has hit
this. Same bug was in `hyperpolymath/my-lang` (see
[hyperpolymath/my-lang#13](hyperpolymath/my-lang#13)).

The first Python block already does the full TypeScript exemption check
honouring the universal allowlist and the parsed `.claude/CLAUDE.md`
table. The duplicated second block is removed.

### 2. `.github/workflows/language-policy.yml` — duplicate TS check with
no allowlist

The "Check for TypeScript files" step did a blunt `find . -name "*.ts"`
filter with no allowlist beyond `node_modules` and `*.d.ts`.
False-positived on legitimate bridge files like
`lol/test/vitest.config.ts`, which lives under the `**/test/**`
universal-allowlist pattern that `rsr-antipattern.yml` honours.

Two checks for the same banned-language family is also a
single-source-of-truth violation. This PR removes the duplicate from
`language-policy.yml`; `rsr-antipattern.yml` remains the canonical
TypeScript-detection check. All other `language-policy.yml` steps
(ReScript, Go, Python, V-lang, ATS2, Java/Kotlin, Swift, Flutter/Dart,
Makefiles, package.json runtime deps) stay — they remain the single
source of truth for those languages.

## What this PR fixes vs. what stays red

**Fixed by this PR:**

- `antipattern-check` no longer exits 127 on the heredoc syntax bug. It
now runs to completion.
- `Check for Banned Languages / Check for TypeScript files` no longer
false-positives on `lol/test/vitest.config.ts`.

**Surfaces real pre-existing migration debt (out of scope for this
PR):**

- `antipattern-check / Check for ReScript` flags ~30 real `.res` files
under
`rhodium-standard-repositories/satellites/{consent-aware-http,cccp/.../7-tentacles}/`.
These were previously hidden behind the heredoc crash — the check never
reached this step before. The fix here unblocks the workflow's ability
to surface them; the actual migration is its own multi-PR effort.
- `Check for Banned Languages / Check for ReScript files` (in
`language-policy.yml`) also flags the same `.res` files. Same
observation.
- `Hypatia Neurosymbolic Analysis (Dogfooding)` — `hypatia-cli.sh scan
.` exits 1 with no diagnostic across multiple repos. Filed at
[hyperpolymath/hypatia#213](hyperpolymath/hypatia#213).

So this PR doesn't turn the standards CI fully green — that would need
the ReScript migration and the Hypatia scanner fix. But it does:

1. Unblock the antipattern check's *ability to run*.
2. Eliminate a false-positive that was masking real signal.
3. Halve the spurious red-X load on every PR.

## Why now

Both bugs surfaced while merging the affinescript#64 port work in #46.
Pre-existing — unrelated to that port — but kept its merge state at
`BLOCKED` until force-merged with `--admin`. Fixing now so future port
PRs have less friction.

## Test plan

- [x] CI on this PR shows `antipattern-check` running to completion (not
exit 127).
- [x] `Check for Banned Languages / Check for TypeScript files` step
passes (no spurious vitest.config.ts hit).
- [ ] Verified by sight: the only remaining failures on this PR are
pre-existing — ReScript migration debt and the Hypatia scanner bug — not
introduced or worsened here.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 <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