feat: AppleScript dictionary — scripted read/write of notes - #208
Conversation
BANAL.app now ships an sdef (Resources/BANAL.sdef) with six verbs: list notes, read note, create note, update note, set published, publish site. Handlers live in a new BANALScripting library target; every verb goes through the same NoteStore route the App Intents use (fresh store per call, flush on settle), so scripted writes land as plain files on disk and the running app observes them like Finder edits. Disk stays the only truth. Record answers return as JSON text; publish site returns the status sentence. The app target links BANALScripting via a keep-alive bootstrap so release dead-stripping preserves the ObjC command classes, and Supporting/Info.plist enables NSAppleScriptEnabled + OSAScriptingDefinition (Makefile copies the sdef into Resources). Verified against the live signed .app: create/read/update/ set-published/publish all round-trip to disk (.cook with >> metadata in Recipes/, frontmatter flags, sanitized .publish artifacts). sdef gotchas baked into the final shape: 8-char event codes, cocoa class element first inside command, concrete result types — the app-side parser rejects anything else silently (-1708).
|
SummaryCoverage spans note creation, reading, updating, publishing, vault persistence, and command integration, along with safety checks for invalid vaults, unsafe paths, hostile names, and concurrent edits. It also examines publishing error handling and site output integrity, with the tested application behavior broadly healthy aside from a separate partial-publication risk. Safe to merge — the only identified issue is a medium-severity publishing integrity bug that is explicitly unrelated to this PR and is not a regression or newly introduced failure. It is a flag for later rather than a merge blocker. Tests run by ItoAdditional Findings DetailsThese findings are unrelated to the current changes but were observed during testing. 🟡 Publishing can leave an incomplete site
Evidence PackageTip Reply with @itoqa to send us feedback on this test run. |
main picked up the agent CLI (#207) and the identity-contract fix (#206) while this branch carried the AppleScript dictionary. Both sides appended a section after Publish — Command line and Scripting now coexist — and the STATUS verification-tooling exception appears once, with both surfaces listed.
|
Diff SummaryThe run covered normal vault and publishing behavior, stable external identities, diagnostics, empty and failed operations, and boundary cases involving unsafe paths and file access. It also exercised adversarial security and overlapping-publish scenarios, with the broader expected behavior generally holding aside from a serious path-isolation issue. Not safe to merge yet — this PR introduces a high-severity security failure in vault path enforcement that can expose files outside the selected vault. The publish concurrency findings are unrelated to this PR and are caveats rather than merge drivers. Tests run by ItoTests that are no longer relevantBelow are tests that previously ran and are no longer relevant:
Additional Findings DetailsThese findings are unrelated to the current changes but were observed during testing. 🟡 Concurrent publishes can corrupt results
Evidence Package🟡 Repeated publishes can overwrite each other
Evidence PackageTip Reply with @itoqa to send us feedback on this test run. |


Third item from the issue pile: an AppleScript dictionary with read + write, per the maintainer's scope call.
Surface
Resources/BANAL.sdefdefines six verbs on the app:How it works
BANALScriptinglibrary target:NoteScripting(the verbs) +NSScriptCommandsubclasses (dispatch, mapped via sdef<cocoa class>).BANALApplinks it through a keep-alive bootstrap so release dead-stripping preserves the ObjC classes.IntentVaultResolver— the same route the App Intents take — and flushes on settle. Scripted writes land as plain files (Recipes/Tom Yum.cookkeeps>>metadata; titles become plain names) and a running app observes them like Finder edits. No second database.make appcopies the sdef into Resources; Info.plist gainsNSAppleScriptEnabled+OSAScriptingDefinition; XcodeGen spec mirrors both.Verified against the live signed .app
Booted
dist/BANAL.appagainst a scratch vault and drove every verb from osascript: create → read → update → set published → publish site, then asserted disk state (edited body on disk,published: truefrontmatter, Cooklang>>metadata, sanitized.publish/Scripted Note.html, feed + index).Three sdef landmines cost most of the debugging, now documented in the commit: event codes must be 8 chars;
<cocoa>must be the first child of<command>; result types must be concrete — the app-side parser rejects violations silently with -1708, while reply conversion of native dictionaries throws inside\_populateReplyAppleEventWithResult(hence JSON-text results).Tests
5 unit tests on the scripting layer (temp vaults): list/read shapes, create writes plain-named files with frontmatter, unknown language rejected, body+published round-trip to disk, publish returns status copy and artifacts. Full suite green. README gains a Scripting section; CHANGELOG updated.