Skip to content

2.3.5–2.3.9: AI efficiency, diagnose_fault, target switch, documentation and build-artefact tools, workspace skills - #30

Merged
MatthiasHertelArm merged 39 commits into
Open-CMSIS-Pack:mainfrom
MatthiasHertelArm:pr/2.3.5-ai-efficiency
Sep 2, 2026
Merged

2.3.5–2.3.9: AI efficiency, diagnose_fault, target switch, documentation and build-artefact tools, workspace skills#30
MatthiasHertelArm merged 39 commits into
Open-CMSIS-Pack:mainfrom
MatthiasHertelArm:pr/2.3.5-ai-efficiency

Conversation

@MatthiasHertelArm

@MatthiasHertelArm MatthiasHertelArm commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

Fixes

Changes

Thirty-six commits on top of main (rebased onto the current mainaecf4dc, with the dependabot bumps to zod 4.5, semver 7.8 and typescript-eslint 8.68 — plus a commit regenerating TPIP and the bundle). Version 2.3.9 — please cut it as a pre-release from the merge (odd minor ⇒ scripts/package.ts packages with --pre-release). The same content is published as v2.3.9 on the fork with CI-built VSIX for the five platforms; the fork's v2.3.5–v2.3.8 pre-releases are the intermediate steps. Per-version detail in CHANGELOG.md.

AI efficiency (2.3.5–2.3.7) — the tools/list payload every agent turn carries −20 % (33.2 → 26.7 kB; a 30 kB budget and a 700-char description cap are asserted in the transport test), serial.enabled drops the ten serial_* tools entirely; get_debug_instructions serves the guide by topic instead of one 21 kB block; compact motion state (location, frame ids, top frames, breakpoints only when changed) and capped listings; diagnose_fault replaces the ~6-call HardFault loop with one call (fault registers, stacked frame, address resolution, ranked hypotheses); lookup_peripheral / lookup_register answer from the SVD without a session; cmsis_action names the target it ran on and target switches/verifies it; per-call telemetry (cmsis-developer-assistant://stats resource, get_session_status trailer, optional JSONL) and an eval-scenario runner that scores an agent's run against tool-call, turn and time budgets.

add-board-layer skill (2.3.8) — add a board layer to an existing csolution by interview: reads the csolution, the DFP/BSP pdsc and an existing layer first, asks only the open decisions, then reuses the BSP layer, integrates the DFP's configuration generator, or writes a minimal bare-metal layer; builds to green and hands over to csolution-retarget.

Documentation and build-artefact tools (2.3.9) — the experimental CMSIS Pack Docs extension moved in as-is: list_target_docs, search_target_docs, read_doc_pages, fetch_doc, get_peripheral_docs and list_build_artifacts, get_memory_usage, lookup_symbol, get_section_layout, get_build_diagnosticsoff by default behind packDocs.enabled / buildInfo.enabled, tagged experimental in the settings, routed like every other op across windows. PDFs are extracted with a bundled pdf.js so Windows hosts without poppler index too (#28); BM25 indexes the page heading as a weighted field and expands identifier-only queries from the SVD (#29; on RM0455 description-only queries R@1 49.5 % → 64.5 %, measured with the new npm run bench:search); the MCP instructions and skills tell agents to search the documentation instead of asking for it. Five palette commands and a Pack Docs panel; cmsis-pack-docs ships as a fourth bundled skill.

Skills into the workspace (2.3.9)Select Agent Skills first asks where the AI Skills Pack goes: This workspace only (the default — a skill in the personal directories is offered to the agent in every project and costs context there; a project skill is loaded only where it applies; <workspace>/.agents/skills, .claude/skills) or This user (as before). The choice is the target of the installedSkills setting, whose scope changes from application to resource; each workspace folder syncs from its own value, a project selection carries pack skills only, and a project without one never gains an empty .agents/skills.

Pack Docs panel: clear the store — two actions in the Store tab, each behind a modal confirmation that names the documents, files and MB involved: clear extracted text (pages, metadata and indexes of every document; downloads stay, re-extracted on next use) and delete downloaded PDFs (the arm/ and web/ trees fetch_doc filled; those documents show as "not fetched" again). PageStore.storeUsage() / clearExtracted() / clearDownloads(), tested.

Also — the Arm logo as the extension icon; VSIX 13.95 → 3.19 MB (unused media dropped, icon 256 px); the architecture diagram shows the documentation path and renders on dark themes; README Commands section.

Screenshots

n/a — the one new UI element is a two-item quick pick (This workspace only / This user) ahead of the existing skill picker.

Checklist

  • 🤖 Unit tests: 416 passing (npm test); both transport suites (npm run test:transport); npm run package + test/transport/packaged-vsix.js on the rebased head.
  • 🤹 Manual testing: 2.3.5–2.3.8 in daily use from the fork pre-releases. Not yet exercised live: the cmsis_action target switch on a two-target solution (verified against the CMSIS Solution 1.70.0 bundle and a stubbed transport test only).
  • 🛡️ Security: the server still binds to localhost only; fetch_doc downloads a PDF from a user- or agent-supplied URL into the extension's global storage (size-capped by packDocs.maxPdfMb), nothing leaves the machine; credential-shaped values stay redacted.
  • 📖 Documentation: README, CHANGELOG, docs/architecture/*, the generated cmsis-help skill.
  • 🧠 TPIP: pdfjs-dist 6.3.289 (Apache-2.0) added; TPIP.md regenerated for 2.3.9.

@MatthiasHertelArm
MatthiasHertelArm force-pushed the pr/2.3.5-ai-efficiency branch 3 times, most recently from 85ed021 to 1d0ef00 Compare August 31, 2026 15:02
@soumeh01
soumeh01 marked this pull request as ready for review September 1, 2026 07:08
soumeh01
soumeh01 previously approved these changes Sep 1, 2026
debugMCPServer.ts does not import vscode so it can run headless under the
transport harness; settings therefore have to arrive through the constructor.
Add a trailing DebugMCPServerOptions object (serialEnabled, telemetry.jsonlPath),
fixed for the lifetime of a server instance so the tool list a client sees
stays stable between turns, thread it through CoordinatorOptions.serverOptions,
expose getOptions(), cover it in the transport check and document the contract.
The settings themselves are declared by the packages that consume each field.
Each session's McpServer is now a MeasuredMcpServer whose registerTool wraps
the callback at the MCP boundary, so what is measured is what the client
experiences: argument and result bytes after parsing, redaction and routing,
wall time including a forward to another window, and the outcome (ok, timeout
read off the fence text, or error). A ToolMetrics ring per session feeds the
new cmsis-developer-assistant://stats resource (per-tool totals for the session
and the server instance plus the last 50 samples), a two-line trailer on
get_session_status, one INFO line per call, and the optional JSONL file
behind the new telemetry.jsonlPath setting (names and sizes only). The worker
logs a matching control-op timing line; the real-board driver stores the
statistics in its report. Covered by unit tests for the pure module and by the
transport harness. Groundwork for measuring the response-size trimming (Open-CMSIS-Pack#18)
and the agent evaluation runs (Open-CMSIS-Pack#27); closes Open-CMSIS-Pack#24.
Version 2.3.5 in package.json, SERVER_VERSION, TPIP and the provenance
notes; CHANGELOG section for 2.3.5 (per-tool call telemetry, the stats
resource, the get_session_status trailer and the telemetry.jsonlPath
setting); rebuilt dist/extension.js.
The guide for harnesses that do not load skills arrived as one 21 KB block
on every session. It is now sliced by marker comments a Markdown reader never
sees: without a topic the tool returns a ~2 KB overview (the critical steps,
the debugger-first rule) and the topic list; session, build, breakpoints,
inspection, faults and troubleshooting return one section each. The guide
gained a faults section (EXC_RETURN, the stacked frame, resolving BFAR, the
usual cause per flag) and a build section (cmsis_action result line, long
builds, flash, attach), and its inherited web-app root-cause examples were
replaced by Cortex-M ones. Shipped docs are read once per server instance and
also resolved from the repository root so the headless transport harness
exercises the real guide. Closes Open-CMSIS-Pack#25.
The serialized tools/list a client receives at initialize is re-sent to the
model on every turn, so its size is a per-turn cost. The per-call timeoutMs
note is now one short line per tool with the rationale once in the server
instructions; start_debugging, cmsis_action, reset, add_breakpoint,
add_logpoint, flash and get_debug_instructions keep the trigger and the one
caveat an agent needs at call time, with the reasoning moved to the
cmsis-debug-live skill and the get_debug_instructions topics. The ten serial
tools are registered only when the new serial.enabled setting is on, fixed per
server instance so the tool list never changes between turns. The transport
test asserts a byte budget for the list and a 700-character cap per
description. Single-window surface: 33.2 kB → 26.7 kB. Closes Open-CMSIS-Pack#23.
Step, continue, pause and wait_for_stop returned the full debug state on every
move — up to 50 frames and every breakpoint, pretty-printed — which is what
drove repeated context compactions in long hardware sessions. They now return
a compact state: location and frame ids, the top 5 frames with the rest
counted, and the breakpoint list only when it changed since the last snapshot;
the full snapshot still comes back when a session starts. read_memory defaults
to hex. get_call_stack prints workspace-relative paths and collapses frames
beyond 20 unless levels is given; get_threads lists up to 32. Variable
listings without variableNames are capped at 40 per scope and 200 characters
per value with a footer saying how to widen — with variableNames nothing is
capped, and a redaction placeholder is never clipped. The recovery section
after a motion timeout reads PC and LR instead of all 23 registers. Pure
helpers in core/textBudget.ts; DebugState.toCompactString and the caps are
unit-tested. Closes Open-CMSIS-Pack#18.
Agents asked "which bit in RCC.APB1ENR enables I2C1" or "what is at
0x40005400" and had to read the live register (needs a stopped session) or
open the SVD themselves. Two read-only tools now answer from the device
description without touching the target: the peripheral list, a peripheral's
register map with absolute addresses, which peripheral and register sit at an
address (turn a BFAR into I2C1.CR1, or name the SRAM/PPB region when the SVD
has nothing there), and one register's bit fields with their enumerated
values. The SVD is resolved from an explicit svdFile, the active session,
out/**/*.cbuild-run.yml (pname picks the core) or a single workspace .svd,
and the failure text lists every location tried. The parser reads
addressBlocks, enumeratedValues and dim register arrays, keeps derivedFrom,
no longer borrows a field's access for its register, and matches tag names
whole. Unknown names get suggestions instead of the full name list;
read_peripheral_register does the same and points at lookup_peripheral. Pure
lookup module and parser covered by a hand-written fixture SVD; the tool list
budget rises to 30 kB for the two tools. Closes Open-CMSIS-Pack#26.
Version 2.3.6 in package.json, SERVER_VERSION, TPIP and the provenance
notes; CHANGELOG section for 2.3.6 (get_debug_instructions topics, the
smaller tool list and serial.enabled, compact tool results, lookup_peripheral
and lookup_register); rebuilt dist/extension.js.
Investigating a HardFault took an agent six calls in a fixed order and it
often skipped the stacked frame or never resolved BFAR. diagnose_fault does
the first pass in one call on a stopped target: the fault registers (one
24-byte SCS block read, word-by-word fallback), the stacked exception frame
located through EXC_RETURN — PSP or MSP, basic or FP-extended — with the PC
of the faulting instruction and its caller, the top frames, the faulting
address resolved against the SVD or the Cortex-M system map, and up to three
ranked hypotheses each with the next tool call: unclocked peripheral, null
pointer, wild pointer, imprecise write, stack overflow with MSPLIM/PSPLIM,
corrupted function pointer, missing Thumb bit, unaligned access, divide by
zero, FPU off, bad VTOR. Sections after the fault registers degrade to a note
instead of failing the call; without fault flags it returns a short stop
context. The decoder is now structured (DecodedFault) with get_fault_info's
text unchanged apart from the new STKOF and DEBUGEVT lines. Four long tool
descriptions were shortened so the tool list stays within its budget. Pure
triage and decoder modules are unit-tested. Closes Open-CMSIS-Pack#22.
Skill and tool changes were judged by feel. scripts/eval-scenario.ts runs a
real Copilot CLI session against a planted bug in a small csolution with the
cmsis-debug-live skill and the MCP server, and reports what it cost: tool
calls by name with argument and result bytes, reasoning turns, wall time, the
server's per-tool byte totals diffed from the stats resource around the run,
and a verdict from the final answer against the expected root cause plus
tool-call, turn and time budgets — infrastructure failures are reported as
such. The fixture is the BSP Blinky example for the Corstone-300 FVP with the
Arm-FVP target-set and the model shim (Docker on macOS); five deterministic
overlays plant a divide by zero, an undefined instruction through a corrupted
function pointer, an MSPLIM stack overflow, an unaligned access and an LED
off-by-one with no fault. Opt-in only, never in npm test or CI; the pure
logic — scenario validation, event aggregation, verdict, mcp-config edit —
lives in src/core/evalScenario.ts and is unit-tested, and every shipped
scenario file is validated by the suite. The skill-trigger script shares the
Copilot CLI helpers. The fixture has not been built on the authoring machine
(no cbuild there); the first run on a machine with the toolbox and the FVP is
its validation. Closes Open-CMSIS-Pack#27.
cmsis_action only asked the CMSIS Solution extension whether a solution was
active, never which target-type / target-set, and its result did not say —
on a board + FVP or HE/HP solution a build or flash could go to the wrong
context unnoticed.

Every result now names the target it ran on and get_device_info reports the
panel's target. The new optional `target` input (type or type@set, the
csolution's names) selects one: a differing target is switched by writing
the selection to .vscode/cmsis.json and re-activating the solution — the
extension (1.70) re-reads the file on activation and exposes no command for
this — and verified through cmsis-csolution.getActiveTargetSet before
anything runs. Undeclared targets are refused with the declared list, an
unverifiable switch with what was written and what the extension still
reports, and a switch under a live session with a pointer to stop_debugging.

src/core/cmsisTarget.ts holds the pure parts (reference parsing and
matching, the target-types scan, the cmsis.json edit); the transport test
drives the echo, refusal, switch and no-op paths against a stubbed
extension. The build topic, the cmsis-debug-live skill, README and the
acceptance test describe the input.
Version 2.3.7 in package.json, SERVER_VERSION, TPIP and the provenance
notes; CHANGELOG section for 2.3.7 (cmsis_action target check and switch,
the agent evaluation scenarios, diagnose_fault); rebuilt dist/extension.js.
The ten token- and round-trip-saving changes of 2.3.5–2.3.7 as one list under the 2.3.7 section, matching the v2.3.7 release notes.
A third extension-authored skill next to cmsis-debug-live and cmsis-help,
always installed: add a board layer to an existing csolution by reading the
packs and the csolution first, asking only the open decisions (scope, layer
strategy, probe, STDIO transport, memory), then reusing the BSP layer,
integrating the DFP's configuration generator when startup exists only as
its output (the agent tells the user to run it — CubeMX, MCUXpresso Config
Tools, Device Configurator, MCC), or writing a minimal bare-metal layer, and
building to green. Hardware facts — register offsets, clock tree, VCP pins,
errata — come from the pack documentation through the CMSIS Pack Docs MCP
when it is installed, cited by document and page, cross-checked against the
SVD.

Registered as a bundled skill of the project category: the cmsis-project
router's workflow points at it, cmsis-help lists it, the catalog test pins
the three bundled entries, README and AGENTS name it.
Version 2.3.8 in package.json, SERVER_VERSION, TPIP and the provenance
notes; CHANGELOG section for 2.3.8 (the bundled add-board-layer skill);
rebuilt dist/extension.js.
…ets in

From the experimental cmsis-pack-docs extension (0.13.1), as-is: the
host-agnostic cores src/core/packDocs (target resolution from cbuild-run,
pdsc <book> walking, Arm document catalogue and download, user and
workspace document folders, pdftotext extraction, page store and BM25
index, peripheral dossiers over the SVD) and src/core/buildInfo (positioned
ELF32 reader, GNU ld / armlink map parser, build-log diagnostics), the two
handlers, the tool registrations, the panel (renamed PackDocsPanel), the 16
shipped Cortex-M core-peripheral SVDs with their generator, the
cmsis-pack-docs skill, and the 22 test suites with their fixtures.

Two adaptations so the move compiles here: the tool files call a
PackDocsDispatch instead of a handler (src/packDocsDispatch.ts — the
pack-docs counterpart of SerialDispatch, so the same registration serves
the single-window and the routed case), and the op table gains
PACKDOCS_DOC_OPS / PACKDOCS_BUILD_OPS with compile-time coverage of the
handlers' handle* methods; the five documentation ops carry the ten-minute
forward floor because indexing a manual takes minutes.
…outer

Ten tools, off by default behind cmsis-developer-assistant.packDocs.enabled
and buildInfo.enabled (fixed per window like serial.enabled): the server
registers the groups only when a gate is on and the session has a dispatch,
and its instructions gain one sentence per enabled group. Every window
builds the handler pair at activation and hands it to its control server,
whose dispatch is now three-way (serial, pack-docs docs/build, debug); the
routing handler forwards packDocsOp like serialOp, so a documentation
lookup runs in the window that owns the workspace. The enabled list is 55
tools / ~41 kB against its own 42 000-byte budget; the default list is
unchanged at 45 tools under 30 000.

Settings packDocs.* (extractor, pdftotextPath, maxPdfMb, includeUnlisted,
workspaceDocDirs, userDocsDir — default ~/.cmsis-pack-docs/user so imported
documents stay attributed) and buildInfo.* (maxSymbols, logGlobs) apply
live; the gates prompt for a reload. Commands: List / Index Target
Documentation, Import Document for Current Target, Open User Documents
Folder, Open Pack Docs Panel. Activation warns when the standalone
extension is still installed.

cmsis-pack-docs is the fourth bundled skill (bring-up); cmsis-debug-live
and add-board-layer point at the built-in tools instead of an external MCP,
cmsis-help lists the two groups, commands and settings. Tests: the op
table, a control-server round trip to the right handler and the refusal of
a window without handlers; the transport harness measures the all-on list
and the no-build answers; the packaged-VSIX check verifies the SVDs and the
skill ship. README, AGENTS, docs/architecture/packDocs.md, the server
architecture note, the provenance notes, the acceptance test and the
changelog describe it.
With the documentation tools on, the MCP instructions now say to use them
before asking the user for a datasheet or manual and instead of reading a
PDF into context: a document the user provides goes into the workspace
docs/ folder or through Import Document for Current Target and is searched.
With the tools off — the default — the instructions name the
packDocs.enabled setting, so an agent on a default install suggests it
rather than asking for documents or opening PDFs itself.

The same rule sits in the cmsis-pack-docs, cmsis-debug-live and
add-board-layer skills, and the build topic of get_debug_instructions
replaces its "check the documentation in the CMSIS Solution UI" advice
with the tools. The transport test asserts the default instructions carry
the pointer.
…lution

Field feedback: an agent with the documentation tools went to the web for an
ADC datasheet that was already indexed as a user document, because nothing
said the user and workspace folders are for third-party parts, a part
number reads like a web lookup, and the first correct call resolved a
fixture's cbuild-run in the same workspace.

Now the MCP instructions, the tool descriptions and the cmsis-pack-docs,
cmsis-debug-live and add-board-layer skills say that sensors, ADCs, codecs
and other third-party parts are documented the same way: any part number
starts at list_target_docs, an unlisted datasheet is fetched by URL with
fetch_doc (the web finds the URL, the tools read the document), and a PDF
the user provides goes into docs/ or through Import Document for Current
Target. The build topic and README say the same.

Target resolution asks the CMSIS Solution extension for the active
csolution and target-type (PackDocsHost / BuildInfoHost.activeContext) and
picks that context when the workspace holds several solutions, noting the
choice; `target` still wins, a hint that matches nothing keeps the
ambiguity error with the active context named, and a failing extension is
ignored. Covered by resolver tests for both cores. The e2e suite now uses a
private user documents folder instead of the developer's real one.
docs/improvement-notes.md records the field note as item 10.
search_target_docs ranked pages by BM25 over the body only; the heading was
a post-hoc boost on pages the body had already returned, so a register page
whose body speaks of bits and never repeats the description words was not a
candidate. The heading is now a second indexed field (DocIndex version 2,
headingPostings) scored at weight 5 on top of the body, the old ×3 post
boost becomes a 1.5 tie-breaker, and an older index is rebuilt from the
persisted pages on first load — no re-extraction.

scripts/search-benchmark.ts (npm run bench:search) makes ranking changes
measurable: gold pages are the manual headings that name a register, the
queries come from the SVD descriptions, and it reports R@1 / R@3 / MRR per
heading weight and post boost. RM0455 × STM32H7B3.svd: description-only
queries MRR 0.621 → 0.741 (R@1 49.5 % → 64.5 %), description plus register
name 0.873 → 0.994 (R@1 78.1 % → 98.8 %). Tables in
docs/improvement-notes.md §11. Issue Open-CMSIS-Pack#29 part 1.
packDocs.extractor gains pdfjs and auto now means pdf.js (legacy build, pure
JavaScript, loaded on first use), so a machine without pdftotext — most
Windows hosts — indexes documents too. Lines are rebuilt from pdf.js text
items by baseline, wide horizontal gaps become double spaces so register
table columns stay separable, and the tokenizer applies NFKC so ligatures
and full-width forms from either extractor meet on one term. A document
extracted by the other extractor is re-extracted on its next use.

VS Code's extension host is Electron and pdf.js does not take it for Node,
so GlobalWorkerOptions.workerSrc points at the shipped worker module
(re-included in the VSIX by .vscodeignore) and pdf.js runs it as a fake
worker on the same thread; the packaged-VSIX check asserts the file ships.

Gated by the search benchmark on RM0455 with the heading field on: pdf.js
MRR 0.739 / 0.995 against pdftotext 0.740 / 0.994, 2 965 pages in 3.9 s.
bench:search can extract a PDF with either extractor (--pdf, --extractor,
--save). +0.8 MB in dist/extension.js; TPIP entry added. Issue Open-CMSIS-Pack#28.
An identifier-only query gains the words of its SVD description at half
weight: a peripheral instance (USART1) brings its type synonyms and
description, a bare field name (GPIOAEN) brings the register it lives in
and the field's description, so the manual is found even when it never
spells the identifier. Expansions never gate the all-terms boost and the
result says what was expanded.

Register names, prose and quoted phrases are left alone. The benchmark
(now with a third set, the bare register name) showed expanding register
names or the acronyms inside a sentence only dilutes the ranking — two
points on description queries, 0.3 on bare register names — while the
heading field already puts register pages first (R@1 98.2 % for the bare
name). With the restriction all three sets are unchanged; the tables are in
docs/improvement-notes.md §11. Issue Open-CMSIS-Pack#29 part 2.
assets/DebugMCP.webp (9.7 MB) was referenced by nothing and shipped in
every package since the fork — 70 % of the VSIX; assets/DebugMCP.mp4
(15 MB) was excluded from the package but kept in the repository;
assets/architecture.svg was an unused rendering of the diagram the README
shows as PNG. All three are removed. The extension icon is 256 px instead
of 1024 (1.4 MB → 52 KB). The design notes under docs/ no longer ship —
only docs/agent-resources, which the MCP resources read, does.

Packaged VSIX: 13.95 MB → 3.19 MB; the packaged-VSIX check still finds
everything the runtime needs.
Every packDocs.* and buildInfo.* setting carries VS Code's experimental
tag, so the Settings UI shows the badge and the Experimental filter finds
them; the two .enabled descriptions say so first. README and the generated
cmsis-help label the documentation and build-artefact tool groups the same
way.
A Commands section between Getting Started and Agent Tools describes the seven palette commands — agent/skills setup and the five documentation commands — and the overview bullets point at it.
The same media/arm.png the other Arm extensions ship (CMSIS Solution, CMSIS Debugger, Keil Studio Pack, Device Manager) replaces the icon inherited from DebugMCP.
…egible on dark themes

The How It Works picture gains the documentation retrieval box — pack
PDFs, user and workspace documents and fetch_doc downloads through pdf.js
into the page store, the search tools answering from it with the SVD
joined in — and is rendered on an opaque background: the previous PNG was
transparent with black labels, which vanish on the dark extension page.
npm run diagram regenerates it from the Mermaid source with a local Chrome
(scripts/puppeteer.json). The README explains the window routing and the
documentation path in two paragraphs.
…efault

Select Agent Skills (and step 2 of the setup) first asks where the AI
Skills Pack goes. This workspace only — the default — copies the selected
pack skills into the project's .agents/skills (and .claude/skills when
Claude Code is installed or the project has a .claude directory), next to
the sources, to commit or ignore; a skill in the personal directories is
offered to the agent in every project and its description costs context
there whether the project is CMSIS or not, a project skill is loaded only
where it applies. This user keeps the previous behaviour.

The choice is the target of the installedSkills setting, whose scope
changes from application to resource: the User value drives the personal
directories, a Workspace or Folder value the project's, each folder of a
multi-root workspace from its own, so a selection checked out in
.vscode/settings.json is applied on activation like one from Settings
Sync and removing it sweeps the project copies. A project selection
carries the pack skills and their hidden dependencies only — the
extension's own skills stay personal — and a project without a selection
never gains an empty .agents/skills. The installer takes its roots per
sync, adding a folder to the workspace syncs it, and the install prompt
counts a pack skill picked in either scope.
…erns hid

src/core/buildInfo/buildLog.ts matched the Visual Studio pattern
[Bb]uild[Ll]og.* in .gitignore, the build-log test fixtures matched *.log
and the Arm document-catalogue fixtures under src/test/fixtures/packdocs/arm
matched [Aa][Rr][Mm]/ — all inherited from DebugMCP and meant for build
output. The files existed in the working copy, so every local build and
test run passed while the pushed tree did not compile (CI for v2.3.9:
"Cannot find module './buildLog'"). Negations keep the original patterns
and track the four paths.
…n isolation

The first CI run of the documentation and build-artefact code (it came in
after v2.3.8 and was only ever run on macOS) failed on the Windows runners
and, in one test, everywhere.

Workspace-relative paths in the list_build_artifacts, get_memory_usage,
get_build_diagnostics and list_target_docs results now use forward slashes
on every platform — the agent copies them into commands, and the tests
assert them that way. The tests themselves stop assuming POSIX: absolute
expectations go through path.resolve (drive letter on Windows), the temp
directory is escaped properly before it is put into a RegExp (the old
character class was mis-parsed and escaped nothing, so C:\Users became
C:Users), and the user-document folders named with glob characters are
skipped on win32, where * and ? are not legal in file names. The
end-to-end suites build their fixture workspace in suiteSetup, which takes
longer than mocha's 2 s default on the Windows runners: the test config
sets 20 s.

The fetch_doc test asserted that the fetched document ranks Open-CMSIS-Pack#1 for
VECTRESET when searched without a doc filter. VECTRESET is identifier-
shaped, so the SVD expansion adds its description words and the "1 Debug"
heading page can outrank p.2 depending on what else the store has indexed
— the test passed only after the earlier tests of the suite had filled the
store. It now asserts presence; the ranking is covered by the search tests.
The installer stages a skill as .<name>.tmp-<pid> next to its destination
and renames it into place. A process that dies between the two — an
extension host killed during a sync, which every interrupted test run is —
leaves the staging directory behind, and Claude Code and VS Code list it
as a skill named ".cmsis-pack-docs.tmp-25348". Five of them had
accumulated here. installOne now removes every .<name>.tmp-* directory of
the skill it is about to stage; other dot-directories are still left
alone.
readdir order is a property of the file system: NTFS lists boards/ and
cores/ before Keil/ (case-insensitive), APFS and ext4 the other way round.
The order of the matched list is informational; the test compares the
sorted lists.
Dependabot's bump of typescript to 7.0.2 (Open-CMSIS-Pack#35) cannot install:
@typescript-eslint/eslint-plugin declares typescript ">=4.8.4 <6.1.0", and
TypeScript 7.0 — the native compiler — ships no programmatic API for it
to load anyway. The TypeScript 7.0 announcement's side-by-side setup
resolves both: @typescript/native (an alias of typescript@7) provides tsc
for compile, check-types and the test build, and the typescript package
resolves to @typescript/typescript6, the TypeScript 6 API, which
typescript-eslint 8.69 supports. The lint plugin and parser move from
8.56 to 8.69.

TypeScript 6.0 stopped including every @types package it finds; the
sources rely on the node, mocha and vscode globals, so tsconfig.json names
them — the only change either compiler asked for: with it, 7.0.2
type-checks the tree with no errors.

Verified with the new lockfile from a clean npm ci: check-types, lint,
build, 415 unit tests, both transport suites, package and the
packaged-VSIX check. The shipped bundle is unchanged — esbuild does not
use tsc.
Two housekeeping actions in the Store tab, kept apart because they answer
different needs: "clear extracted text…" removes every document's pages,
metadata and search index across the store and prunes the emptied
directories — downloads and fetch records stay, so a fetched document is
still fetched and everything is extracted and indexed again on its next
use (after an extractor switch, a suspect index, or to reclaim space);
"delete downloaded PDFs…" removes the arm/ and web/ trees fetch_doc filled
— PDFs, fetch records and their extraction — so those documents are
offered as "not fetched" again.

Each asks first: a modal confirmation names the documents, files and
megabytes it is about to remove, computed by the new
PageStore.storeUsage(). clearExtracted() and clearDownloads() drop the
store's in-memory page and index caches, and the handler forgets its
chapter cache. The panel shows the outcome in its status line and
refreshes the Store and Target tabs. Covered by a pageStore test that
sets up a pack document and a fetched Arm document and checks what each
clear removes and keeps.
main brought zod 4.5.2, semver 7.8.5 and @types/express 5.0.6 (dependabot); the tree runs on them unchanged — 416 tests, both transport harnesses, the packaged VSIX. TPIP.md regenerated; dist rebuilt with zod 4.
pdf.js refuses to start when Array.prototype or Object.prototype carries
an enumerable property, and the extension host is one process shared by
every extension — the CMSIS csolution extension assigns
Array.prototype.groupedBy, so every extraction died with "The
`Array.prototype` contains unexpected enumerable property" and nothing
could be indexed or searched.

PdfjsExtractor now drives a worker_threads worker (pdfWorker.ts, bundled
as dist/pdfWorker.js by a second esbuild entry point): a fresh realm no
other extension can patch. The thread starts on the first document, is
kept for the next, retired after a minute idle, and terminated when an
extraction times out — which now stops pdf.js mid-document instead of
waiting for the next page boundary.

Where pdf.js detects Node it presets workerSrc to "./pdf.worker.mjs"
beside pdf.mjs — which exists in node_modules, where the tests run, but
not beside the bundle once esbuild has inlined the library. The worker
therefore sets the shipped pdf.worker.min.mjs unconditionally, and the
packaged-VSIX check now runs an extraction through the packaged
dist/pdfWorker.js, the only place that class of bug is visible.

itemsToPageText moves to pdfText.ts, shared by the worker and the tests.
New tests cover extraction under a patched Array.prototype, a timeout
followed by a fresh extraction, and a missing file.
The target picker — a cbuild-run context or pack + device — moves into a
header shared by every tab, with the resolution and core under it, since
it drives them all. The former Target tab, which stacked the SVD browser
above the document list, splits into Documents (every document the tools
see for the target, its state, and the fetch / index / browse / search
actions) and Peripherals (the device SVD, the Arm core peripherals and
the NPU as groups, instances and bit views); Store becomes Page store —
what is extracted and indexed on disk across all targets, its header
now on three short lines instead of a wrapping path — and Tools stays.

Each tab carries a count and a tooltip and opens with a one-line
description of what it shows; the header stays put while the active view
scrolls, and nothing refers to "the Target tab" from other tabs any
more. A tab saved by the old three-tab layout opens as Documents.

Regenerates the bundle: dist/extension.js with both this and the worker
thread, plus its new sibling dist/pdfWorker.js.
@MatthiasHertelArm
MatthiasHertelArm merged commit eb427a1 into Open-CMSIS-Pack:main Sep 2, 2026
17 checks passed
This was referenced Sep 7, 2026
@MatthiasHertelArm
MatthiasHertelArm deleted the pr/2.3.5-ai-efficiency branch September 7, 2026 17:12
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.

3 participants