Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: CI

on:
push:
branches: [main]
pull_request:

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Phase-0 manifest contract gate
# Asserts dist/repo.meta.json parses, carries all required fields,
# and every exposes.* path resolves on disk. Cross-repo tier-2
# contract per .github/docs/AI-discoverability-plan.md §3.4.
# Runs before npm install so a broken manifest fails fast.
run: make check-manifest

- name: docs/ prose-only gate
# Cross-repo guardrail: docs/ holds only human-readable prose.
run: make check-docs-prose

- uses: actions/setup-node@v4
with:
# Node 22 — required for `node --test --experimental-strip-types`
# which is the test runner npm test invokes against tests/*.test.ts.
node-version: '22'

- name: Install dependencies
run: npm ci

- name: Build + test
# `npm test` is `tsc -p ./ --noEmit && node --test tests/*.test.ts`
# — it type-checks src/ + tests/ and runs the unit suite.
run: npm test

- name: Compile extension
# Produces out/extension.js — the marketplace entry point.
run: npm run compile
166 changes: 166 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
---
# Machine-readable project descriptor — schema v1 (2026-05-05).
name: m-stdlib-vscode
kind: [editor-extension, language-tooling]
status: active
languages: [typescript]

distribution:
github: m-dev-tools/m-stdlib-vscode
marketplace_id: rafael5.m-stdlib-vscode

location: ~/m-dev-tools/m-stdlib-vscode

exposes:
extension_info: "dist/extension-info.json"
package_json: "package.json"
snippets: "snippets/m.json"
bundled_manifest: "assets/stdlib-manifest.json (snapshot of m-stdlib/dist/stdlib-manifest.json, refreshed at release time)"

consumes:
formats:
- "m-stdlib/dist/stdlib-manifest.json (schema v1)"
services: []
upstream_data:
- "m-stdlib — runtime input: hover docs, goto-def line numbers, completion lists all come from the resolved stdlib-manifest.json"

companions:
- project: m-stdlib
relation: "primary input — the manifest this extension reads is m-stdlib's `make manifest` output; m-stdlib has architectural priority"
- project: m-cli
relation: "shares the `$M_CLI_MANIFEST` env var as a discovery hint; if a user has m-cli set up, the extension picks up the same manifest without per-workspace config"
- project: tree-sitter-m-vscode
relation: "sibling editor extension — different concern (syntax highlighting via tree-sitter); both extensions co-exist in a `.m` buffer without conflict"

incompatibilities:
- "Not a full M language server. Scope is exactly the m-stdlib public surface (`STD*` modules + their public labels); non-stdlib symbols are deliberately left alone."
- "Not a syntax highlighter. That's tree-sitter-m-vscode."
- "ObjectScript out of scope — M only."

docs:
primary: README.md
---

# m-stdlib-vscode — Claude project context

VS Code extension that surfaces m-stdlib's `dist/stdlib-manifest.json`
as hover docs, goto-definition, and completion inside any open `.m`
file. The manifest is the single source of truth; this extension is a
thin presentation layer over it.

The full design rationale, manifest-discovery order, and per-feature
behaviour is in `README.md`.

## What this is

- A VS Code extension (`rafael5.m-stdlib-vscode`) that registers
hover, definition, and completion providers for the `m` language.
- A manifest reader: at activation it walks a documented discovery
order to resolve `dist/stdlib-manifest.json`, then watches the
resolved file for changes and rebuilds its in-memory index on save.
- A snippet pack (`snippets/m.json`) for the canonical m-stdlib
idioms (the same set documented in m-stdlib's how-to guides).
- A bundled manifest snapshot (`assets/stdlib-manifest.json`) so the
extension works on a stock install with no other repo on disk;
refreshed at release time by copying m-stdlib's `dist/stdlib-manifest.json`.

## What this is NOT

- A full M (MUMPS) language server. Non-`STD*` symbols are out of scope.
- A syntax highlighter. The TextMate / tree-sitter grammar that
tokenises `.m` files lives in **tree-sitter-m-vscode**; the two
extensions are deliberately independent so a user can install either
one without the other.
- A linter. M linting belongs to `m-cli`.
- A test runner. M testing belongs to `m-cli` + `m-test-engine`.
- A regenerator of m-stdlib's manifest. The manifest is produced by
`make manifest` in `m-stdlib`; this extension only reads it.

## Setup

```bash
npm ci # install vscode + tsc + @types/node
```

Node ≥ 18 is required for the TypeScript build. No M toolchain
required — the manifest is read as JSON and the extension never
shells out to YottaDB / IRIS.

## Test

```bash
npm test # tsc --noEmit + node --test on tests/*.test.ts
```

The `npm test` script runs `tsc -p ./ --noEmit` (full type-check of
`src/` and `tests/`) followed by `node --test --experimental-strip-types tests/*.test.ts`
(unit tests for the manifest resolver, token recogniser, and snippet
schema). No VS Code instance is launched; the tests exercise the pure
TypeScript modules in isolation.

## Build / generate

```bash
npm run compile # tsc -p ./ → out/extension.js
npm run watch # tsc -watch (development host loop)
```

The `out/` directory is the VS Code runtime entry point (`main` in
`package.json`). It is gitignored — published `.vsix` packages
include it via `npm run vscode:prepublish`.

The `dist/` directory in this repo is separate from `out/` and is
**not** a TypeScript build output. `dist/extension-info.json` and
`dist/repo.meta.json` are hand-authored Phase-0 contract payloads
that describe the extension to the org-level AI-discoverability
catalog. When `package.json` changes a value referenced by
`dist/extension-info.json` (version, publisher, engine pin, settings
schema), update the dist file in the same commit — the
`check-manifest` gate only verifies the dist file exists, not that it
agrees with `package.json`, so drift is on the author.

## Verify

The `verification_commands` declared in `dist/repo.meta.json`:

```bash
make check-manifest # dist/repo.meta.json valid + exposes.* paths exist
```

Cross-repo guardrail:

```bash
make check-docs-prose # docs/ holds only prose (this repo has no docs/ at all)
```

## Guardrails

- **Do not hand-edit `dist/extension-info.json` to disagree with
`package.json`.** The dist file is hand-authored, but it's a mirror
of `package.json` (version, publisher, engine pin, settings keys,
marketplace id). When `package.json` changes a mirrored value,
update the dist file in the same commit.
- **The manifest-discovery order is contract.** Consumers
(m-stdlib's docs, m-cli's `--manifest` flag, the bundled-manifest
fallback story) reference the four-step order: setting →
`$M_CLI_MANIFEST` → workspace walk-up → bundled assets. Reordering
or removing a step is a breaking change requiring coordinated docs
updates in m-stdlib.
- **`m-stdlib` has architectural priority over `m-stdlib-vscode`.**
This extension is a downstream consumer of m-stdlib's manifest
schema. If a needed manifest field is missing, propose adding it
to m-stdlib first; do not synthesise it client-side.
- **Do not expand scope beyond `STD*`.** A "full M language server"
is out of scope and would conflict with tree-sitter-m-vscode and
any future m-cli LSP work. Hover / goto-def / completion stay
scoped to symbols the manifest knows about; everything else is
passed through to other providers.
- **Do not hand-edit `dist/repo.meta.json` `verified_on` to a future
date.** The org smoke test rejects manifests older than 90 days;
bump the date only when the manifest changes materially (new
exposes payload, version bump, publisher change).
- **Bundled `assets/stdlib-manifest.json` is a release-time snapshot,
not a live artefact.** Do not regenerate it from a local m-stdlib
checkout outside a release flow — that would silently desync
installed users from what their `m-stdlib.manifestPath` setting
resolves to. Refresh it only when bumping the extension version.
1 change: 1 addition & 0 deletions CLAUDE.md
51 changes: 51 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# m-stdlib-vscode — Phase-0 AI-discoverability contract gates.
#
# The VS Code extension build itself runs through npm scripts:
#
# npm ci # install vscode + tsc + @types/node
# npm test # tsc --noEmit + node --test on tests/*.test.ts
# npm run compile # tsc -p ./ → out/extension.js
#
# This Makefile only carries the cross-repo gates so verification_commands
# in dist/repo.meta.json line up with the other org repos.

.PHONY: manifest check-manifest check-docs-prose

# ── Phase-0 AI-discoverability contract ───────────────────────────────
#
# Tier-2 entry to the org catalog. See
# https://github.com/m-dev-tools/.github/blob/main/docs/AI-discoverability-plan.md
#
# `dist/extension-info.json` and `dist/repo.meta.json` are hand-authored,
# not regenerated. The source of truth for what they mirror lives in
# `package.json` (version, publisher, engine pin, settings schema,
# marketplace id). When `package.json` changes a mirrored value, update
# the dist file in the same commit (this is captured in AGENTS.md
# § Guardrails).
#
# `make manifest` is therefore a pointer no-op — it exists so
# verification_commands in dist/repo.meta.json line up with other org
# repos that DO have a generator.

manifest:
@echo "m-stdlib-vscode: dist/extension-info.json is hand-authored alongside package.json."
@echo " see AGENTS.md § Build / generate for the rebuild-when-it-changes guardrail."

check-manifest:
python3 tools/check-manifest.py

# Guardrail: docs/ holds only human-readable prose. Same target name
# as the tier-1 repos so cross-repo muscle memory works.
check-docs-prose:
@if [ ! -d docs ]; then echo "check-docs-prose: no docs/ directory ✓"; exit 0; fi; \
violations=$$(find docs -type f \
! -name '*.md' ! -name '*.markdown' \
! -name '*.png' ! -name '*.jpg' ! -name '*.jpeg' \
! -name '*.gif' ! -name '*.svg' ! -name '*.webp' \
! -name '.gitkeep'); \
if [ -n "$$violations" ]; then \
echo "ERROR: non-prose files under docs/ — move to a top-level domain dir:" >&2; \
echo "$$violations" >&2; \
exit 1; \
fi; \
echo "check-docs-prose: docs/ is prose-only ✓"
44 changes: 44 additions & 0 deletions dist/extension-info.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"engines": {
"vscode": "^1.85.0"
},
"license": "MIT",
"manifest_discovery_order": [
"m-stdlib.manifestPath setting",
"$M_CLI_MANIFEST env var",
"workspace folder walk-up",
"bundled assets/stdlib-manifest.json"
],
"marketplace_id": "rafael5.m-stdlib-vscode",
"name": "m-stdlib-vscode",
"publisher": "rafael5",
"schema_version": "1",
"settings": [
{
"default": "",
"description": "Path to dist/stdlib-manifest.json. Empty = auto-discover: workspace folder walk-up, then $M_CLI_MANIFEST, then the manifest bundled with the extension. Set this to your m-stdlib checkout's dist/stdlib-manifest.json for live tracking.",
"key": "m-stdlib.manifestPath",
"type": "string"
},
{
"default": true,
"description": "Show hover docs on `^STD*` and `label^STDxxx` symbols.",
"key": "m-stdlib.enableHover",
"type": "boolean"
},
{
"default": true,
"description": "Enable Cmd/Ctrl-click goto-definition for `^STD*` symbols.",
"key": "m-stdlib.enableDefinition",
"type": "boolean"
},
{
"default": true,
"description": "Suggest module + label names as completions in `.m` files.",
"key": "m-stdlib.enableCompletion",
"type": "boolean"
}
],
"snippets_path": "snippets/",
"version": "0.2.0"
}
17 changes: 17 additions & 0 deletions dist/repo.meta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"$schema": "https://raw.githubusercontent.com/m-dev-tools/.github/main/profile/repo.meta.schema.json",
"id": "tool:m-stdlib-vscode",
"repo": "https://github.com/m-dev-tools/m-stdlib-vscode",
"role": "VS Code extension — manifest-driven hover / goto-def / completion for STD* symbols in .m files",
"language": ["typescript"],
"license": "MIT",
"agent_instructions": "AGENTS.md",
"verified_on": "2026-05-10",
"exposes": {
"extension_info": "dist/extension-info.json",
"package_json": "package.json"
},
"consumes": ["tool:m-stdlib"],
"verification_commands": ["make check-manifest"],
"status": "active"
}
Loading
Loading