fix: close the gaps the final 1.0 review found where the fixes meet · pangular-inspector/devtools@9f28be1 · GitHub
Skip to content

Commit 9f28be1

Browse files
erkamyamanclaude
authored andcommitted
fix: close the gaps the final 1.0 review found where the fixes meet
Hub messages for agent writes showed only the new page line and posted no-op writes, an ambiguous form id refused a write without isError, arguments that moved to another tool were silently ignored, an Analog navigation timer still ran in the Angular zone, the e2e jobs skipped changes to the demo and the tools docs, and a release could publish a commit whose main CI failed or a tag other than the one it ran from. The feed now reads the answer behind the page line, those refusals carry isError, moved arguments name the tool to use, the timers run outside the zone, CI covers those paths, and a release needs a tag ref and green CI on main. The docs and changelog match.
1 parent 20880b9 commit 9f28be1

21 files changed

Lines changed: 276 additions & 56 deletions

‎.github/workflows/ci.yml‎

Lines changed: 5 additions & 3 deletions

‎.github/workflows/release.yml‎

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,14 @@
11
name: Release
22

33
# Publishes @pangular-inspector/devtools to npm from a version tag, with provenance, after checking
4-
# the exact tarball it publishes. Push a tag such as v1.0.0 on a commit of main, or run it from the
5-
# Actions tab with that tag. See apps/docs/src/content/contributing/publishing.md#releasing.
4+
# the exact tarball it publishes. Push a tag such as v1.0.0 on a commit of main whose CI passed, or
5+
# run it from the Actions tab with that tag picked as the ref. See
6+
# apps/docs/src/content/contributing/publishing.md#releasing.
67
on:
78
push:
89
tags: ['v*']
10+
# Run with "Use workflow from" set to the tag; a branch is refused.
911
workflow_dispatch:
10-
inputs:
11-
tag:
12-
description: The version tag to release, such as v1.0.0. It must already be pushed.
13-
required: true
14-
type: string
1512

1613
permissions:
1714
contents: read
@@ -23,7 +20,7 @@ concurrency:
2320

2421
jobs:
2522
release:
26-
name: Publish ${{ inputs.tag || github.ref_name }}
23+
name: Publish ${{ github.ref_name }}
2724
runs-on: ubuntu-latest
2825
timeout-minutes: 120
2926
# Protect this environment (required reviewers, tags only) in the repository settings. It holds
@@ -34,12 +31,21 @@ jobs:
3431
contents: write
3532
# npm publish --provenance signs the attestation with the workflow's OIDC token.
3633
id-token: write
34+
# gh run list reads the CI runs of the tagged commit.
35+
actions: read
3736
env:
38-
TAG: ${{ inputs.tag || github.ref_name }}
37+
# Both triggers run on the tag itself: a tag push, or a manual run with the tag as the ref.
38+
TAG: ${{ github.ref_name }}
3939
steps:
40+
- name: Check the run is for a tag
41+
if: github.ref_type != 'tag'
42+
run: |
43+
echo "::error::Release runs only on a version tag, not on ${GITHUB_REF}. Pick the tag in \"Use workflow from\"."
44+
exit 1
45+
4046
- uses: actions/checkout@v7
4147
with:
42-
ref: refs/tags/${{ inputs.tag || github.ref_name }}
48+
ref: ${{ github.ref }}
4349
# The whole history, so the tagged commit can be checked against main.
4450
fetch-depth: 0
4551
persist-credentials: false
@@ -51,6 +57,21 @@ jobs:
5157
exit 1
5258
fi
5359
60+
# The full CI (ci.yml) must have passed on main for this exact commit, so a commit whose CI
61+
# failed, or is still running, is never published.
62+
- name: Check CI passed on the tagged commit
63+
env:
64+
GH_TOKEN: ${{ github.token }}
65+
GH_REPO: ${{ github.repository }}
66+
run: |
67+
sha=$(git rev-parse HEAD)
68+
passed=$(gh run list --workflow ci.yml --commit "$sha" --branch main --event push \
69+
--status success --json databaseId -q 'length > 0')
70+
if [ "$passed" != "true" ]; then
71+
echo "::error::CI has no successful run on main for $sha. Wait for it to pass, or fix main and tag again."
72+
exit 1
73+
fi
74+
5475
# The tag, the package version and the changelog section must agree. The section becomes the
5576
# GitHub release notes.
5677
- name: Check the version and the changelog

‎apps/docs/src/content/agents/mcp-server.md‎

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,19 +37,19 @@ Run `pangular mcp --print-config` in your project folder. It prints the config f
3737
npx @pangular-inspector/devtools mcp --print-config --port 4000 --base /__devframes/
3838
```
3939

40-
| Flag | Effect on the output |
41-
| --------------- | ----------------------------------------------------------------------------------------------------------- |
42-
| `--root <dir>` | The project folder in the stdio config, as an absolute path. The default is the working directory. |
43-
| `--host <host>` | Host in the HTTP URL and the `Origin` header. The default is `localhost`. |
44-
| `--port <port>` | Port in the HTTP URL. The default is 9999, the [standalone CLI](../getting-started/cli.md). |
45-
| `--base <path>` | The hub base, such as `/__devframes/`. The URL becomes `<base>__mcp` and the config sends the bearer token. |
46-
| `--https` | The server is behind TLS. The URL and the `Origin` header use `https://`. |
40+
| Flag | Effect on the output |
41+
| --------------- | -------------------------------------------------------------------------------------------------- |
42+
| `--root <dir>` | The project folder in the stdio config, as an absolute path. The default is the working directory. |
43+
| `--host <host>` | Host in the HTTP URL and the `Origin` header. The default is `localhost`. |
44+
| `--port <port>` | Port in the HTTP URL. The default is 9999, the [standalone CLI](../getting-started/cli.md). |
45+
| `--base <path>` | The hub base, such as `/__devframes/`. The URL becomes `<base>__mcp`. |
46+
| `--https` | The server is behind TLS. The URL and the `Origin` header use `https://`. |
4747

48-
`--config` and `--read-only` are added to the stdio command. The output never holds the token. It reads the token from `PANGULAR_MCP_TOKEN` (VS Code asks for it) and prints the `export` line that sets it from the [token file](#send-a-token). Without `--base`, the HTTP config targets the standalone CLI, which asks for the same token.
48+
`--config` and `--read-only` are added to the stdio command. The output never holds the token. It reads the token from `PANGULAR_MCP_TOKEN` (VS Code asks for it) and prints the `export` line that sets it from the [token file](#send-a-token). The HTTP config always sends the bearer token. Without `--base`, it targets the standalone CLI, which asks for the same token.
4949

5050
The stdio server is named `pangular` and the HTTP one `pangular-live`, so you can add both. Claude Code prefers a local server over a project server of the same name, so with one name the HTTP server would never load.
5151

52-
With `--base` and a `--host` that is not a loopback address, such as `192.168.1.20`, the output starts the HTTP part with a warning: the URL is `http`, so the token travels in clear text on your network. Serve the hub over TLS and pass `--https`, or keep it to a network you trust. `localhost`, `127.0.0.1` and `::1` get no warning.
52+
With a `--host` that is not a loopback address, such as `192.168.1.20`, and no `--https`, the output starts the HTTP part with a warning: the URL is `http`, so the token travels in clear text on your network. Serve the hub over TLS and pass `--https`, or keep it to a network you trust. `localhost`, `127.0.0.1` and `::1` get no warning.
5353

5454
## Connect over stdio
5555

‎apps/docs/src/content/agents/tools.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ The argument names are the same in every tool:
8383

8484
A call that sends an argument name a tool no longer takes, such as `selector` for `inspect-component` or `storeId` for `ngrx-history`, is refused with the name to use instead.
8585

86+
An argument that moved to another tool is refused with the tool to use: `record`, `flash`, `track` and `angularProfiling` on `change-detection` (use `record-change-detection`), `overlay` on `hydration` (use `highlight` with `hydration`), and `routeId` and `on` on `navigate` (use `list-routes` with `resolveLazy`, and `record-guards` with `on`).
87+
8688
A tool that refuses a call answers with `isError: true`. That covers a wrong or missing argument, a `page` that reports no such data, an action turned off in the config or under `agent.readOnly`, a form or action the page refuses, and a write that would have to guess the tab. The text starts with `Refused:` or `Invalid arguments:` and says what to change.
8789

8890
An action or destructive tool that does nothing also answers `isError: true`: no page to send it to, a target that matches nothing, a navigation the app cancelled or that failed, or a recording no page confirmed. An empty result of a read, such as no HTTP calls yet, is an ordinary answer.

‎apps/docs/src/content/contributing/publishing.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ Releases publish from CI, not from a laptop. `.github/workflows/release.yml` pub
9999
In one pull request, set <code>version</code> in <code>packages/devtools/package.json</code> and add a <code>## 1.2.3</code> section to <code>packages/devtools/CHANGELOG.md</code>. List every removed or renamed export, option and tool under Upgrade notes. Merge it to <code>main</code>.
100100
</ngmd-step>
101101
<ngmd-step title="Tag the merged commit">
102-
Run <code>git tag v1.2.3</code> on that commit of <code>main</code> and <code>git push origin v1.2.3</code>. The tag starts the workflow. To rerun a release, start <strong>Release</strong> from the <strong>Actions</strong> tab with the same tag.
102+
Wait for CI to pass on that commit of <code>main</code>. Then run <code>git tag v1.2.3</code> on it and <code>git push origin v1.2.3</code>. The tag starts the workflow. To rerun a release, start <strong>Release</strong> from the <strong>Actions</strong> tab and pick the tag, not a branch, under <strong>Use workflow from</strong>.
103103
</ngmd-step>
104104
<ngmd-step title="Approve the npm environment">
105105
The job runs in the <code>npm</code> environment, which holds the <code>NPM_TOKEN</code> secret. Approve it when the run asks.
@@ -108,7 +108,7 @@ Releases publish from CI, not from a laptop. `.github/workflows/release.yml` pub
108108

109109
The workflow stops at the first check that fails, before anything reaches npm:
110110

111-
1. The tag is on `main`, and it equals `v` plus the package version. The changelog has a non-empty section for that version (`scripts/release-notes.mjs`).
111+
1. The run is for a tag, and the tag is on `main`. The CI workflow (`ci.yml`) has a successful run on `main` for the tagged commit. The tag equals `v` plus the package version. The changelog has a non-empty section for that version (`scripts/release-notes.mjs`).
112112
2. `pnpm typecheck`, `pnpm test:devtools` and `pnpm test:panel` pass.
113113
3. `pnpm --filter @pangular-inspector/devtools pack` builds one tarball. The root `.pnpmfile.cjs` drops `devDependencies`, `scripts` and the `nx` block from the packed `package.json`.
114114
4. `pnpm verify:publish` (Angular CLI and Analog) and a few cells of `pnpm e2e:install` install that exact tarball from a local registry into fresh apps, open them in Chromium and run the package audit.

‎apps/docs/src/content/getting-started/cli.md‎

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -194,15 +194,15 @@ Your agent client runs this command for you. [MCP server](../agents/mcp-server.m
194194
npx @pangular-inspector/devtools mcp --print-config --port 4000 --base /__devframes/
195195
```
196196

197-
| Flag | What it does |
198-
| ---------------- | ---------------------------------------------------------------------------------------------------------------------------- |
199-
| `--print-config` | Print the client config and exit. |
200-
| `--host <host>` | Host of the server that runs your app, for the HTTP config. The default is `localhost`. |
201-
| `--port <port>` | Port of that server, from 1 to 65535. The default is 9999, the standalone CLI. |
202-
| `--base <path>` | The hub base, such as `/__devframes/` for the Express hub and the Vite plugin. With it, the HTTP config sends the MCP token. |
203-
| `--https` | The server is behind TLS, so the HTTP config uses `https://`. |
204-
205-
`--root`, `--config` and `--read-only` go into the printed stdio command, with absolute paths. The stdio server is named `pangular` and the HTTP server `pangular-live`, so a client can hold both. With `--base` and a `--host` that is not a loopback address, the output warns that the token travels in clear text over `http`; pass `--https` when the server is behind TLS.
197+
| Flag | What it does |
198+
| ---------------- | ------------------------------------------------------------------------------------------------------------------ |
199+
| `--print-config` | Print the client config and exit. |
200+
| `--host <host>` | Host of the server that runs your app, for the HTTP config. The default is `localhost`. |
201+
| `--port <port>` | Port of that server, from 1 to 65535. The default is 9999, the standalone CLI. |
202+
| `--base <path>` | The hub base, such as `/__devframes/` for the Express hub and the Vite plugin. The HTTP URL becomes `<base>__mcp`. |
203+
| `--https` | The server is behind TLS, so the HTTP config uses `https://`. |
204+
205+
`--root`, `--config` and `--read-only` go into the printed stdio command, with absolute paths. The stdio server is named `pangular` and the HTTP server `pangular-live`, so a client can hold both. The HTTP config always sends the MCP token, for the hub and for the standalone CLI. With a `--host` that is not a loopback address and no `--https`, the output warns that the token travels in clear text over `http`; pass `--https` when the server is behind TLS.
206206

207207
### Source scan only
208208

‎packages/devtools/CHANGELOG.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ These changes can break a 0.0.7 setup without an error.
3535

3636
### Agent tools renamed
3737

38-
1.0 renames tools and arguments so that each name follows one pattern: an optional library prefix (`ngrx-`, `redux-`, `tanstack-`, `capacitor-`, `analog-`), then a verb that says whether the tool reads source (`scan`), reads the page (`list`, `inspect`, `explain`, `lint`) or writes (`run`, `set`, `record`). There are no aliases. A call to an old tool name is an unknown tool. An old argument is refused with `isError` and the name to use instead, such as ``There is no `selector` argument; pass `component`.`` Tool ids are `pangular:<name>` on the server and `pangular_<name>` for MCP clients; the tables leave the prefix out.
38+
1.0 renames tools and arguments so that each name follows one pattern: an optional library prefix (`ngrx-`, `redux-`, `tanstack-`, `capacitor-`, `analog-`), then a verb that says whether the tool reads source (`scan`), reads the page (`list`, `inspect`, `explain`, `lint`) or writes (`run`, `set`, `record`). There are no aliases. A call to an old tool name is an unknown tool. An old argument is refused with `isError` and the name to use instead, such as ``There is no `selector` argument; pass `component`.`` An argument that moved to another tool (`record` on `change-detection`, `overlay` on `hydration`, `routeId` and `on` on `navigate`) is refused with `isError` and the tool to use. Tool ids are `pangular:<name>` on the server and `pangular_<name>` for MCP clients; the tables leave the prefix out.
3939

4040
| 0.0.7 | 1.0.0 |
4141
| ---------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
@@ -153,7 +153,7 @@ What remains: `/config` exports `DEFAULT_POPUP_HOTKEY`, `PANGULAR_ACTIONS`, `PAN
153153

154154
#### Agents and MCP
155155

156-
- 97 agent tools. New tools include `audit`, `snapshot`, `wait-for`, `scan-templates` (#415), `list-errors`, `explain-error`, `list-console`, `find-leaks`, `diagnose-change-detection` (#395), `set-component-property`, `set-signal`, `track-subscriptions`, `watch-signal`, `hydration`, `screenshot-component`, `open-in-panel`, `startup-timing`, `read-provider-value`, `record-change-detection`, `probe-route`, `record-guards`, the TanStack Query, Capacitor, plugin and NgRx session tools, and tools for HTTP fault rules and SSR overrides.
156+
- 98 agent tools. New tools include `audit`, `snapshot`, `wait-for`, `scan-templates` (#415), `list-errors`, `explain-error`, `list-console`, `find-leaks`, `diagnose-change-detection` (#395), `set-component-property`, `set-signal`, `track-subscriptions`, `watch-signal`, `hydration`, `screenshot-component`, `open-in-panel`, `startup-timing`, `read-provider-value`, `record-change-detection`, `probe-route`, `record-guards`, the TanStack Query, Capacitor, plugin and NgRx session tools, and tools for HTTP fault rules and SSR overrides.
157157
- One naming scheme for tools and arguments, and plain markdown answers. See **Agent tools renamed**.
158158
- Tool titles, inspector tags and safety tiers (`action` and `destructive`).
159159
- Every answer names the page it read, and one rule picks the default page for every tool.

‎packages/devtools/src/__tests__/agent-tools.test.ts‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1058,3 +1058,30 @@ describe('agent tools', () => {
10581058
expect(await call('inspect-providers', '')).toMatch(/no injector data/i);
10591059
});
10601060
});
1061+
1062+
describe('arguments moved to another tool', () => {
1063+
it('refuses them with isError and the tool to use', async () => {
1064+
const { ctx } = await boot();
1065+
const refused = async (tool: string, args: Record<string, unknown>) => {
1066+
try {
1067+
await ctx.agent.invoke(`pangular:${tool}`, args);
1068+
} catch (error) {
1069+
if (error instanceof ToolRefusal) return error.message;
1070+
throw error;
1071+
}
1072+
return undefined;
1073+
};
1074+
expect(await refused('change-detection', { record: 'start' })).toContain(
1075+
'`pangular:record-change-detection`',
1076+
);
1077+
expect(await refused('change-detection', { angularProfiling: true })).toContain(
1078+
'`pangular:record-change-detection`',
1079+
);
1080+
expect(await refused('hydration', { overlay: true })).toContain(
1081+
'`pangular:highlight` with `hydration`',
1082+
);
1083+
expect(await refused('navigate', { action: 'go', url: '/', routeId: 'r1' })).toContain(
1084+
'`pangular:list-routes` with `resolveLazy`',
1085+
);
1086+
});
1087+
});

‎packages/devtools/src/__tests__/cd-export-tool.test.ts‎

Lines changed: 4 additions & 2 deletions

0 commit comments

Comments
 (0)