Repository navigation
Arkitect 2.4.0
Added
-
arkitect report --draft <diagram> [--spec <spec>]prints the seven report headings with File, Icons and Validation filled: the file's pages and counts, each icon's id and pack (or ref and library) and every placeholder, missing, ambiguous or on-demand mark resolved from the spec without writing, and everyvalidateerror, warning and note word for word, with the build report's unknown kinds, unknown fields and notes. Engine, Assumptions, Render and Deviations each hold a<!-- fill in -->line, andarkitect reportand the Stop hook fail a report while one is left (#387). -
Every Draw.io build carries its spec, as an
arkitect-specattribute on<mxfile>, which Draw.io Desktop keeps on save, andarkitect drawio spec <file>prints it: an edit to a diagram Arkitect built changes the spec and rebuilds instead of hand-writing XML. Rebuilding the printed spec reproduces the file byte for byte. A file saved by an editor since still counts as Arkitect's while it carries the spec, so a rebuild names the cells added there and keeps their backup (#376), andspecwarns that changes made there are not in it.references/editing.mdgains that branch. Every built file is larger by its spec, about 3 KB for the starter; the two committed examples are rebuilt, and nothing they draw moved (#388). -
arkitect report --draftwithout--speclists the icons from the spec the diagram carries, so a Draw.io file, whose cells do not record their icon, needs no spec file beside it (#388). -
Every Excalidraw build carries its spec under
customData.arkitectSpecof the first element its first node drew, andarkitect excalidraw spec <file>prints it. The issue proposed the top of the scene orappState; the app drops both on save and keeps an element'scustomData. Rebuilding the printed spec with the same seed reproduces the scene byte for byte. A rebuild over a scene the app changed names the elements added there and keeps their backup (#376), andspecwarns when the scene no longer matches what the build wrote.references/editing.mdgains that branch. The two committed examples are rebuilt and re-rendered; nothing they draw moved (#388). -
Every eval case carries one tier tag.
tier-1is the floor and must stay at 1.00;tier-2andtier-3hold the cases that measure progress, where a score below 1.00 is expected. Every other tag is a documented competency,weight: 3marks the grader a tier-2 or tier-3 case exists for, and a test holds all three. The 18 existing cases are tier 1, andexcalidraw-learning-skill-stays-manualis taggedinvocation, like its Draw.io twin, in place ofskills.docs/testing.mdsaid 17 cases, nine for Draw.io, and is checked now (#415). -
The eval summary prints a scorecard by tier and by competency, each with its cases, mean score and the cases where every run was perfect. An efficiency line reads each run's trace: median turns, tool calls, failed or refused calls, permission denials and the bytes of tool output taken into context. A failed
weight: 3grader is listed asCRIT, and a run that used every turn asTURNS. The gate fails on a tier-1 case below 1.00, an errored run, or a case further than--tolerance(default 0.2) below its--baseline, which is a scoreboard or aresult.json. A tier-2 or tier-3 case below 1.00 no longer fails it.--scoreboard FILEwrites the run's scores and counts with no path, prompt or reply in it.scripts/eval.shwrites one beside every result and takes--baseline,--toleranceand--tier N(#415). -
Four tier-2 and tier-3 eval cases measure editing, one competency four ways.
drawio-edit-built-diagramandexcalidraw-edit-built-scenegive the agent a file Arkitect built and nobody has touched since, and expect the spec route of #388: print the spec, change it, rebuild over the file.drawio-edit-saved-by-desktopgives it the same build after a Draw.io Desktop save that filled a box orange and added a text cell by hand, and expects both to survive.excalidraw-edit-follows-the-scenegives it a scene drawn in the app, with its own colours and no roughness, and expects an in-place edit in that look with every arrow bound. Each scaffold builds its fixture with the real CLI throughevals/fixtures.mjs. A test makes each fixture, acts out the right outcome and the traps, and holds every file grader to its verdict on each (#405, #415). -
Eight more tier-2 and tier-3 eval cases, for what the contract promises and no case measured:
drawio-refused-spec-is-repaired: a refused spec fixed rather than its edge dropped;drawio-instructions-in-a-spec: a note planted in a spec, asking for an upload, a POST and a deletion, treated as data;drawio-lifecycle-target-state: lifecycle caveats repeated for a target state, and a customer name and codename kept out of every search, fetch and download;drawio-whole-file-never-read: a 400 KB diagram answered without its payload entering the trace;drawio-interview-when-vague: one question with a recommended answer, and nothing drawn yet;drawio-scale-multi-region: twenty-odd components in nine nested boundaries;excalidraw-legend-for-two-kinds: flows told apart by kind, and the legend that follows;excalidraw-portable-report-check:report --draft, filled in, then checked, on an AGENTS.md host.
The suite has 30 cases. Five tags are new:
robustness,privacy,context,interviewandscale(#415). -
evals/scoreboard.jsonholds the first full run of the 30 cases: Haiku under test, Sonnet judging, 88 runs for $1.64. Tier 1 scored 1.00, tier 2 0.89 and tier 3 0.96.evals/README.mdsays what the headroom showed and when to replace the board, and a test keeps the board naming exactly the cases that exist, each with its tier and no path (#415). -
arkitect drawio pattern Nandarkitect excalidraw pattern Nprint one section of the pattern catalog, read-only, and with no N list the sections. BothSKILL.mdstep 2 namenode scripts/pattern.mjs Nin place of reading the section by hand:sed -non a plugin file is refused in a sandboxed run, and two eval runs read that refusal as a dead shell and stopped without the edit. AGENTS.md step 2 names the command too, and each reading path is 13 bytes shorter (#417). -
Two eval cases continue a conversation through
context.history_file, which the runner resumes withclaude --resume:drawio-interview-continues(tier 3) takes the user's answer to the first interview question and expects the next one, never one already answered, andexcalidraw-edit-next-turn(tier 2) asks for one change to a scene built a turn earlier and expects it rebuilt by its spec, with a backup, the other nodes kept and the assumption it made untrue gone. Each history is written by itshistory.mjsthroughtranscript()inevals/fixtures.mjs, in the shape Claude Code writes a session, and a test rebuilds it, checks the chain and the tool calls, and refuses a path or a$CLAUDE_PLUGIN_ROOTcommand, which the agent's shell leaves empty. Resuming writes the continued session into the case folder:.gitignorekeeps it out andscripts/eval.shdeletes it. A new tag,conversation.evals/scoreboard.jsonis replaced by a run of the 32 cases on Haiku, 94 runs for $1.56: tier 1 1.00, tier 2 0.93, tier 3 0.89 (#418). -
evals/scoreboard.sonnet.jsonandevals/scoreboard.opus.jsonhold tiers 2 and 3 on Sonnet and Opus, beside the Haiku board, so a case every model fails can be told from one only a small model fails. Tier 2 scored 0.93, 0.99 and 0.97 on Haiku, Sonnet and Opus; tier 3 0.89, 0.99 and 0.98. Only the two interview cases fall below 1.00 on every model (#422, #423).evals/README.mdgains a table of each model's tier means, perfect cases and cost, linked to its board, and a test keeps each board naming exactly the tier-2 and tier-3 cases, its model and no path (#419).
Changed
- AGENTS.md step 8 and both
SKILL.mdstep 9 namearkitect report --draftin place of the sentence asking for eachvalidatewarning by hand, with every id; the drafted Validation section carries them. Each reading path is a few bytes shorter (#387). - The Cursor and OpenCode slash command is
/arkitect, not/diagram:arkitect install cursor-commandwrites.cursor/commands/arkitect.mdandarkitect install opencodewrites.opencode/command/arkitect.md.diagramis a generic name a host, an extension or the project itself can hold, and a project's owndiagram.mdkept Arkitect's from installing. Adapter names are unchanged. An install removes thediagram.mdan earlier Arkitect wrote, under any install path, and says so; any otherdiagram.mdis the project's own, kept byte for byte and named. Cursor and OpenCode users type/arkitectfrom now on (#401).
Fixed
analyze --outandbuild --outrefuse a hard link or symlink to the file they read, as they already refused the same path.analyze a.drawio --out summary.json, through a hard link, replaced the diagram with its summary, exit 0 and no backup (#391).- Both builders refuse, exit 2 and nothing written, an
--outinside the Arkitect install, which the next plugin or npm update replaces;--defaults, which every template rebuild passes, still writes there. The Codex skill said to run a guide's commands from the skill folder, where a relative--outlanded inside the install; it now says to run them from the project folder. A build that wrote into the install now exits 2 (#377). - Draw.io
validatefails an image linked by URL (http:,https:,//,file:) instead of warning, asreferences/editing.mdalready said and Excalidraw's validator already did; Draw.io's ownimg/…artwork passes. Excalidraw's validator names a remote image file once, not also as unreadable. A file that passed with that warning now fails (#379). - Draw.io
validatewarns when a wrapped label holds a word wider than its box. Wrapping breaks at spaces and hyphens, so a CamelCase or snake_case name ran out of both sides of the box and passed (#381). - Both build reports list an unknown key inside
layoutunderunknownFields, and Draw.io's insidecontextand Excalidraw's insidestyletoo.layout.colPichchanged no spacing and was named nowhere (#393). - The Excalidraw build report lists an unknown
accent, boundarycolor,strokeStyle,fillStyle,route,layout.routeorroutingunderunknownKinds, with what it was drawn as. An unknownstrokeStyleorfillStyleused to be written into the scene as it was; the default is written now.validatewarns on an element whosestrokeStyleorfillStyleExcalidraw does not know. A spec whoseroutewas unknown now draws theautoroute in place of an elbow (#380). - The
build-routehook routes a diagram request that names Draw.io or Excalidraw and also a PNG, an SVG or a canvas to that engine's skill. "Draw our AWS architecture in Draw.io and give me a PNG for the slides" got no line, because the format filter ran before the engine was read (#383). - The report check counts a build whose quoted script path holds a space, as an install under
/Users/Jane Doedoes. Since #373 such a build was not counted, and its report went unchecked (#382). - The report check keeps the folder of an
--outwhose name it cannot resolve:--out out/$n.drawio, withn=$(basename …), now stands for a diagram inout/, not for any file. A later review that quoteddocs/arch.drawiowas sent back for the seven headings (#395). - The report check reads a folder held in a variable set in the same command:
S=scratch/tpl; … --out "$S/$n.drawio"now stands for a diagram intpl/, not for any file. Every later reply naming any diagram path was sent back for the seven headings (#397). - The report check counts a build only from what the shell runs. A build command quoted in a heredoc's body, a
node -estring, a commit message or any other quoted string of more than one word counted, its--outbecame a built file or any file, and every later reply naming a diagram path was sent back for the seven headings. The body ofbash -c,pwsh -Command,cmd /cor a heredoc fed to a shell still counts, and so does a quoted path to the builder. A script a heredoc writes and a later line runs is no longer counted (#400). arkitect install --forcecopies a Cursor rule, a Cursor or OpenCode command or the Codex skill it replaces to<file>.backup-<stamp>first, when it holds anything but the block being written.install --all --force, the documented update, replaced a project's own command with no copy left. The name ends past the extension, so Cursor and OpenCode do not load the copy as a second command (#401).- Both build reports leave the edge-kind table to
--print-styleunless an override drew the build: the house style's meanings repeated in every report of a rebuild loop (#386). - The Excalidraw build report names each shared mark by
refandpack. Its source, licence and sha256 moved behind--verbose, once per ref undericons.sources: printed for every node, they made the gallery's report 10 KB (#386). - Draw.io
analyze --cellsprints one compact JSON row per cell, without its empty keys;--cells --allkeeps every key. Fifteen pretty-printed keys per cell made the starter's table 11 KB, on the route the read hook names in place of reading the file (#385). - Excalidraw
analyze --cellsprints one line per spec node, boundary and edge: its main shape's type and short id, the box around it and its element count. A scene no spec drew gets a line per outermost group, else per element;--cells --allkeeps the element table. One object per element, every stroke of an icon included, made the 48-node template's table 140 KB; it is now 5 KB (#385). - The Draw.io build report notes a diagram of more than three nodes, with edges, and no
noteto hold the assumptions, and a page whoselegend: falsedrew no legend for two or more connector kinds. Both non-negotiables went unchecked on every host. The generate-architecture eval case reads the file for the note (#384). - The Excalidraw build report notes the same two: a scene of more than three nodes, with edges, and no
note, andlegend: falseover two or more connector kinds. Its generate-architecture eval case reads the scene for a note rectangle (#384). docs/status.mdno longer carries a release snapshot. Its 2.3.0 "Where it stands" named seven open issues, all closed, and a Node 20 floor since raised to 22; the audit prompt reads that page first. It keeps how work gets done and the decisions that can look unfinished.evals/README.mdcounted the portable report check as a nineteenth case; it is one of the ten Draw.io cases (#389).- An Excalidraw boundary is sized to hold a child scope's
outsidelabel. The label belonged to the parent frame but crossed its top border, andvalidatepassed. This changes what a spec draws: a parent of an outside-labelled scope is now taller, and wider where the label is. A top-level outside label is unchanged (#392). - The Draw.io build notes a node or boundary drawn inside or across a boundary it is not a member of, and
validatewarns on a cell drawn inside or across a container that is not its parent, naming both. A boundary covers every cell between its members, so a node set between two of them was drawn inside the VPC the spec put it outside, and both passed. A file with that defect, a hand-drawn icon laid over a group shape included, now has a warning (#378). - The Excalidraw build notes the same, and stamps each member's boundary into
customData.arkitectasparent, sovalidatewarns on a node drawn inside or across a boundary it is not a member of. A scene built before carries noparentand is not checked. The two committed examples are rebuilt for the stamp; nothing they draw moved (#378). - A Draw.io build that replaces a diagram someone added to since it was built names, in
notes, each cell the build does not draw, with the backup path, and writes that backup as<name>.backup-<stamp>-kept.<ext>, which retention never deletes. It compares cell ids, leaving out the ids the builder makes up, so a node dropped from the spec is named too. The rebuild dropped an added "Audit log" with nothing said, and seven more rebuilds deleted the only backup holding it (#376). - The Excalidraw build does the same for elements without Arkitect's stamp, and now stamps its title and legend as
{"chrome": true}; a title or legend from before sits where the build draws one, and is not counted. The two committed examples are rebuilt for the stamp (#376). - The four stays-manual eval cases check the fixture itself: its content, its cell or element count, and that no
EditorWritetouched it. Theirinput-unchangedgraders looked for the fixture intarget: files, which lists only the files a run created; the scaffold wrote it before the run, so they passed whatever happened to it. A test refuses afilesgrader that names a file its case's scaffold writes (#414). - The
build-routehook routes a diagram asked for politely: "I'd like", "would like", "could you do", "put together" or "show me", then a diagram or a flowchart. "I'd like an architecture diagram of our platform for the client's architecture review board" loaded no skill, and every run ofdrawio-interview-when-vagueasked five or six questions at once where the skill asks one. "A fix for the diagram", or a diagram noun naming code ("the diagram renderer", "a diagram view"), still gets nothing (#416). - A fifth hook,
hooks/install-write.mjs, refuses a shell command,WriteorEditthat would write inside the plugin, which the next update replaces: above all amkdir, a redirect, ateeor an--outafter acdinto a skill folder. 11 eval runs of 15 rancd <plugin>/skills/arkitect-drawio && …, and one lost its deliverable to amkdir -p ./eval-outputfrom there. The refusal names the path, says the shell still works, and says to run the command from the project with the script's full path. Running or reading a script from the skill folder passes, and everything does when the project is the plugin itself. BothSKILL.mdsayscripts/and every path are in the skill folder, to be run from the project, never by acdthere, and AGENTS.md says the same; the Excalidraw reading path stays 8 bytes under its 12,000 (#404).