feat(github,playwright): automated onboarding + pinned versions + CI smoke - #85
Closed
dylanneve1 wants to merge 2 commits into
Closed
feat(github,playwright): automated onboarding + pinned versions + CI smoke#85dylanneve1 wants to merge 2 commits into
dylanneve1 wants to merge 2 commits into
Conversation
β¦smoke Same treatment as mempalace (#84) for the other two internal Talon plugins. ## GitHub plugin (src/plugins/github/) - New install.ts with GITHUB_MCP_IMAGE pinned tag (previously: ':latest', which silently drifts on upstream releases). - ensureGithubMcpAvailable helper: verifies docker daemon, checks image presence, optionally docker pull when github.autoPull=true. - New config fields: github.autoPull (bool, default false) and github.image (string, advanced override). - init() runs the ensure flow, logs steps, surfaces errors. ## Playwright plugin (src/plugins/playwright/) - @playwright/mcp pinned to exact 0.0.70 in package.json (previously ^0.0.70 β caret allowed silent minor/patch drift). - New install.ts with PLAYWRIGHT_MCP_VERSION constant, SUPPORTED_BROWSERS source-of-truth, and ensurePlaywrightMcpAvailable helper. - ensurePlaywrightMcpAvailable: verifies the MCP CLI resolves, compares installed version to the pin, probes browser via 'playwright install --dry-run', optionally runs the real install when playwright.installBrowsers=true. - Browser check is skipped when using a remote endpoint (no local binary needed). ## Tests - New github-install.test.ts β 8 cases on ensureGithubMcpAvailable (happy path, docker unreachable, missing image with/without autoPull, pull failure, post-pull still missing, image override). - New playwright-install.test.ts β 10 cases covering the CLI presence check, unsupported browser rejection, installBrowsers=true install path, failure modes, and remote-endpoint mode. - All 1379 tests pass, typecheck clean, prettier clean, lint 0 errors. ## Functional CI - New .github/workflows/plugin-smoke.yml with two jobs: github-mcp β ubuntu-latest only (Docker). Pulls the pinned image, spawns via docker run -i, runs initialize + tools/list, asserts core tools present (get_me, search_repositories, list_issues). playwright-mcp β matrix ubuntu/macos/windows Γ chromium. Installs the browser, spawns @playwright/mcp via node, runs initialize + tools/list + browser_navigate about:blank + browser_close. Asserts expected tool names and valid response shapes. - Triggers on plugin path changes, main pushes, nightly cron (05:45 UTC to catch upstream breakage), and manual dispatch. ## Local verification - npx vitest run β 1379/1379 passing - node scripts/github-mcp-smoke.mjs smoke β 41 tools, core subset OK - node scripts/playwright-mcp-smoke.mjs install + smoke β 21 tools, navigate + close OK
β¦ion drift
## GitHub
- When autoPull=true, docker pull runs even if the image is already
present β refreshes the digest in case upstream force-pushed the tag.
'docker pull' is a cheap no-op when the digest hasn't changed, so the
cost is minimal.
- New test covering the 'present + autoPull β refresh' path.
## Playwright
- When the installed @playwright/mcp version drifts from
PLAYWRIGHT_MCP_VERSION, ensurePlaywrightMcpAvailable now returns
ok=false with an actionable error (was: just a step-note). Mutating
node_modules at runtime would desync with the lockfile, so fail
visibly instead and tell the user to run 'npm install'.
- New test exercising the version-mismatch failure path.
## Scope note
These two changes complete Dylan's 'auto-update installed versions'
request as far as is feasible per plugin:
- mempalace (pip) β realigns to exact target (previous commit).
- github (Docker) β re-pulls pinned tag to refresh digest.
- playwright (npm) β cannot safely auto-mutate node_modules; instead
fails fast with an actionable error.
Owner
Author
|
Superseded by #86 β unified plugin-lifecycle overhaul that removes opt-in flags, adds a shared self-heal layer, and consolidates the CI matrix. |
dylanneve1
pushed a commit
that referenced
this pull request
May 5, 2026
Overhaul of mempalace, github, and playwright to remove opt-in flags and introduce a shared, robust self-heal layer. Replaces #83, #84, #85. Enabling a built-in plugin now fully sets it up β no flags, no manual bootstrap: { "mempalace": { "enabled": true } } { "github": { "enabled": true, "token": "ghp_..." } } { "playwright":{ "enabled": true, "browser": "chromium" } } On every start Talon re-verifies the install and realigns to the pinned version if it drifted. Removed: autoInstall, autoPull, installBrowsers. Added: structured per-step progress logging with timings that pinpoint the slow/failing step. - semver.ts β tiny parse/compare for the floor + pin check - errors.ts β PluginError taxonomy (8 kinds) + subprocess stderr classifier with regression-tested patterns - progress.ts β numbered, timed step tracker with pluggable log sink - subprocess.ts β line-streaming spawn wrapper that normalises CR/LF/CR-only output (docker pull uses bare \r), captures stderr, and returns a classified PluginError on failure - lifecycle.ts β HealFn contract + runHeal() with hard timeout guard Each plugin keeps the upstream version pin as a source-of-truth constant and implements a dedicated heal() that uses the shared infra: - mempalace/heal.ts: MEMPALACE_TARGET="3.3.2", MEMPALACE_FLOOR="3.3.2". Managed mode owns ~/.talon/mempalace-venv (create β pip install β verify). User-supplied pythonPath switches to verify-only mode β we never mutate a user's Python environment without consent. - github/heal.ts: GITHUB_MCP_IMAGE="ghcr.io/github/github-mcp-server:v1.0.2". Always pulls on heal to refresh digest. Pull-fail with cached image β degraded (we run on stale); pull-fail without cache β failed. - playwright/heal.ts: PLAYWRIGHT_MCP_VERSION="0.0.70" (matches pin in package.json). Verify-only for the npm package (we do NOT mutate node_modules at runtime), auto-install for the chosen browser binary. Deliberately targeted, not volume. Shared infra: 39 cases. Per-plugin heal: 9 mempalace, 6 github, 11 playwright. Plugin factory: 5 mempalace. All test at decision boundaries (managed vs verify-only, present vs missing vs drift, happy vs classified-failure paths) β no mock-the-mock redundancy. 1421/1421 total passing Β· typecheck clean Β· prettier clean Β· 0 lint errors. Single workflow, three jobs: mempalace β matrix Ubuntu/macOS/Windows Γ Python 3.11/3.12 (6 runs) github β Ubuntu (Docker-only) (1 run) playwright β matrix Ubuntu/macOS/Windows Γ chromium (3 runs) Each job: pull/install the pinned version, spawn the real MCP server over stdio, handshake, tools/list, call a representative tool. No mocks, no network fakes. Triggers: PRs touching plugin paths, main pushes, nightly cron (05:30 UTC), manual dispatch. - npx vitest run β 1421/1421 passing - npm run typecheck β clean - npm run format:check β clean - npm run lint β 0 errors (9 pre-existing warnings) - node scripts/smoke-mempalace.mjs install + smoke β 29 tools, status ok - node scripts/smoke-github.mjs pull + smoke β 41 tools, list ok - node scripts/smoke-playwright.mjs install + smoke β 21 tools, navigate + close ok
dylanneve1
pushed a commit
that referenced
this pull request
May 8, 2026
Overhaul of mempalace, github, and playwright to remove opt-in flags and introduce a shared, robust self-heal layer. Replaces #83, #84, #85. Enabling a built-in plugin now fully sets it up β no flags, no manual bootstrap: { "mempalace": { "enabled": true } } { "github": { "enabled": true, "token": "ghp_..." } } { "playwright":{ "enabled": true, "browser": "chromium" } } On every start Talon re-verifies the install and realigns to the pinned version if it drifted. Removed: autoInstall, autoPull, installBrowsers. Added: structured per-step progress logging with timings that pinpoint the slow/failing step. - semver.ts β tiny parse/compare for the floor + pin check - errors.ts β PluginError taxonomy (8 kinds) + subprocess stderr classifier with regression-tested patterns - progress.ts β numbered, timed step tracker with pluggable log sink - subprocess.ts β line-streaming spawn wrapper that normalises CR/LF/CR-only output (docker pull uses bare \r), captures stderr, and returns a classified PluginError on failure - lifecycle.ts β HealFn contract + runHeal() with hard timeout guard Each plugin keeps the upstream version pin as a source-of-truth constant and implements a dedicated heal() that uses the shared infra: - mempalace/heal.ts: MEMPALACE_TARGET="3.3.2", MEMPALACE_FLOOR="3.3.2". Managed mode owns ~/.talon/mempalace-venv (create β pip install β verify). User-supplied pythonPath switches to verify-only mode β we never mutate a user's Python environment without consent. - github/heal.ts: GITHUB_MCP_IMAGE="ghcr.io/github/github-mcp-server:v1.0.2". Always pulls on heal to refresh digest. Pull-fail with cached image β degraded (we run on stale); pull-fail without cache β failed. - playwright/heal.ts: PLAYWRIGHT_MCP_VERSION="0.0.70" (matches pin in package.json). Verify-only for the npm package (we do NOT mutate node_modules at runtime), auto-install for the chosen browser binary. Deliberately targeted, not volume. Shared infra: 39 cases. Per-plugin heal: 9 mempalace, 6 github, 11 playwright. Plugin factory: 5 mempalace. All test at decision boundaries (managed vs verify-only, present vs missing vs drift, happy vs classified-failure paths) β no mock-the-mock redundancy. 1421/1421 total passing Β· typecheck clean Β· prettier clean Β· 0 lint errors. Single workflow, three jobs: mempalace β matrix Ubuntu/macOS/Windows Γ Python 3.11/3.12 (6 runs) github β Ubuntu (Docker-only) (1 run) playwright β matrix Ubuntu/macOS/Windows Γ chromium (3 runs) Each job: pull/install the pinned version, spawn the real MCP server over stdio, handshake, tools/list, call a representative tool. No mocks, no network fakes. Triggers: PRs touching plugin paths, main pushes, nightly cron (05:30 UTC), manual dispatch. - npx vitest run β 1421/1421 passing - npm run typecheck β clean - npm run format:check β clean - npm run lint β 0 errors (9 pre-existing warnings) - node scripts/smoke-mempalace.mjs install + smoke β 29 tools, status ok - node scripts/smoke-github.mjs pull + smoke β 41 tools, list ok - node scripts/smoke-playwright.mjs install + smoke β 21 tools, navigate + close ok
dylanneve1
pushed a commit
that referenced
this pull request
May 8, 2026
Overhaul of mempalace, github, and playwright to remove opt-in flags and introduce a shared, robust self-heal layer. Replaces #83, #84, #85. Enabling a built-in plugin now fully sets it up β no flags, no manual bootstrap: { "mempalace": { "enabled": true } } { "github": { "enabled": true, "token": "ghp_..." } } { "playwright":{ "enabled": true, "browser": "chromium" } } On every start Talon re-verifies the install and realigns to the pinned version if it drifted. Removed: autoInstall, autoPull, installBrowsers. Added: structured per-step progress logging with timings that pinpoint the slow/failing step. - semver.ts β tiny parse/compare for the floor + pin check - errors.ts β PluginError taxonomy (8 kinds) + subprocess stderr classifier with regression-tested patterns - progress.ts β numbered, timed step tracker with pluggable log sink - subprocess.ts β line-streaming spawn wrapper that normalises CR/LF/CR-only output (docker pull uses bare \r), captures stderr, and returns a classified PluginError on failure - lifecycle.ts β HealFn contract + runHeal() with hard timeout guard Each plugin keeps the upstream version pin as a source-of-truth constant and implements a dedicated heal() that uses the shared infra: - mempalace/heal.ts: MEMPALACE_TARGET="3.3.2", MEMPALACE_FLOOR="3.3.2". Managed mode owns ~/.talon/mempalace-venv (create β pip install β verify). User-supplied pythonPath switches to verify-only mode β we never mutate a user's Python environment without consent. - github/heal.ts: GITHUB_MCP_IMAGE="ghcr.io/github/github-mcp-server:v1.0.2". Always pulls on heal to refresh digest. Pull-fail with cached image β degraded (we run on stale); pull-fail without cache β failed. - playwright/heal.ts: PLAYWRIGHT_MCP_VERSION="0.0.70" (matches pin in package.json). Verify-only for the npm package (we do NOT mutate node_modules at runtime), auto-install for the chosen browser binary. Deliberately targeted, not volume. Shared infra: 39 cases. Per-plugin heal: 9 mempalace, 6 github, 11 playwright. Plugin factory: 5 mempalace. All test at decision boundaries (managed vs verify-only, present vs missing vs drift, happy vs classified-failure paths) β no mock-the-mock redundancy. 1421/1421 total passing Β· typecheck clean Β· prettier clean Β· 0 lint errors. Single workflow, three jobs: mempalace β matrix Ubuntu/macOS/Windows Γ Python 3.11/3.12 (6 runs) github β Ubuntu (Docker-only) (1 run) playwright β matrix Ubuntu/macOS/Windows Γ chromium (3 runs) Each job: pull/install the pinned version, spawn the real MCP server over stdio, handshake, tools/list, call a representative tool. No mocks, no network fakes. Triggers: PRs touching plugin paths, main pushes, nightly cron (05:30 UTC), manual dispatch. - npx vitest run β 1421/1421 passing - npm run typecheck β clean - npm run format:check β clean - npm run lint β 0 errors (9 pre-existing warnings) - node scripts/smoke-mempalace.mjs install + smoke β 29 tools, status ok - node scripts/smoke-github.mjs pull + smoke β 41 tools, list ok - node scripts/smoke-playwright.mjs install + smoke β 21 tools, navigate + close ok
dylanneve1
pushed a commit
that referenced
this pull request
May 9, 2026
Overhaul of mempalace, github, and playwright to remove opt-in flags and introduce a shared, robust self-heal layer. Replaces #83, #84, #85. Enabling a built-in plugin now fully sets it up β no flags, no manual bootstrap: { "mempalace": { "enabled": true } } { "github": { "enabled": true, "token": "ghp_..." } } { "playwright":{ "enabled": true, "browser": "chromium" } } On every start Talon re-verifies the install and realigns to the pinned version if it drifted. Removed: autoInstall, autoPull, installBrowsers. Added: structured per-step progress logging with timings that pinpoint the slow/failing step. - semver.ts β tiny parse/compare for the floor + pin check - errors.ts β PluginError taxonomy (8 kinds) + subprocess stderr classifier with regression-tested patterns - progress.ts β numbered, timed step tracker with pluggable log sink - subprocess.ts β line-streaming spawn wrapper that normalises CR/LF/CR-only output (docker pull uses bare \r), captures stderr, and returns a classified PluginError on failure - lifecycle.ts β HealFn contract + runHeal() with hard timeout guard Each plugin keeps the upstream version pin as a source-of-truth constant and implements a dedicated heal() that uses the shared infra: - mempalace/heal.ts: MEMPALACE_TARGET="3.3.2", MEMPALACE_FLOOR="3.3.2". Managed mode owns ~/.talon/mempalace-venv (create β pip install β verify). User-supplied pythonPath switches to verify-only mode β we never mutate a user's Python environment without consent. - github/heal.ts: GITHUB_MCP_IMAGE="ghcr.io/github/github-mcp-server:v1.0.2". Always pulls on heal to refresh digest. Pull-fail with cached image β degraded (we run on stale); pull-fail without cache β failed. - playwright/heal.ts: PLAYWRIGHT_MCP_VERSION="0.0.70" (matches pin in package.json). Verify-only for the npm package (we do NOT mutate node_modules at runtime), auto-install for the chosen browser binary. Deliberately targeted, not volume. Shared infra: 39 cases. Per-plugin heal: 9 mempalace, 6 github, 11 playwright. Plugin factory: 5 mempalace. All test at decision boundaries (managed vs verify-only, present vs missing vs drift, happy vs classified-failure paths) β no mock-the-mock redundancy. 1421/1421 total passing Β· typecheck clean Β· prettier clean Β· 0 lint errors. Single workflow, three jobs: mempalace β matrix Ubuntu/macOS/Windows Γ Python 3.11/3.12 (6 runs) github β Ubuntu (Docker-only) (1 run) playwright β matrix Ubuntu/macOS/Windows Γ chromium (3 runs) Each job: pull/install the pinned version, spawn the real MCP server over stdio, handshake, tools/list, call a representative tool. No mocks, no network fakes. Triggers: PRs touching plugin paths, main pushes, nightly cron (05:30 UTC), manual dispatch. - npx vitest run β 1421/1421 passing - npm run typecheck β clean - npm run format:check β clean - npm run lint β 0 errors (9 pre-existing warnings) - node scripts/smoke-mempalace.mjs install + smoke β 29 tools, status ok - node scripts/smoke-github.mjs pull + smoke β 41 tools, list ok - node scripts/smoke-playwright.mjs install + smoke β 21 tools, navigate + close ok
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Same treatment as #84 (mempalace) for the two remaining internal plugins. Three things for each:
Pinned version β GitHub MCP Docker image pinned via
GITHUB_MCP_IMAGE = "ghcr.io/github/github-mcp-server:v1.0.2"(was:latest).@playwright/mcppinned to exact0.0.70in package.json (was^0.0.70caret-drift). Both constants live in a dedicatedinstall.tsmodule next to the plugin.Automated onboarding β opt-in config flags. Both default
falseso we never touch the user's Docker cache or disk without consent.github.autoPullβdocker pullthe pinned image on init if missing.playwright.installBrowsersβnpx playwright install <browser>on init if the browser binary isn't there.Multi-OS functional CI β
.github/workflows/plugin-smoke.ymlwith two jobs:docker run -i, runs MCPinitializeβtools/list, asserts core tools are present (get_me,search_repositories,list_issues).ubuntu-latest / macos-latest / windows-latest Γ chromium. Installs the browser, spawns@playwright/mcpvia Node, runsinitializeβtools/listβtools/call browser_navigate about:blankβtools/call browser_close, asserts expected tool names and valid response shapes.Triggered by plugin path changes, main pushes, nightly cron (05:45 UTC), and manual dispatch.
Files
src/plugins/github/install.tsGITHUB_MCP_IMAGE+ensureGithubMcpAvailablesrc/plugins/github/index.tsautoPull/imageknobssrc/plugins/playwright/install.tsPLAYWRIGHT_MCP_VERSION,SUPPORTED_BROWSERS,ensurePlaywrightMcpAvailablesrc/plugins/playwright/index.tsinstallBrowsersknobsrc/util/config.tsgithub.autoPull,github.image,playwright.installBrowserssrc/core/plugin.tspackage.json@playwright/mcp:^0.0.70β0.0.70src/__tests__/github-install.test.tssrc/__tests__/playwright-install.test.ts.github/workflows/plugin-smoke.ymlscripts/github-mcp-smoke.mjsscripts/playwright-mcp-smoke.mjs.gitignore.playwright-mcp/artifact dirLocal verification
npx vitest runβ 1379/1379 passingnpm run typecheckβ cleannpm run format:checkβ cleannpm run lintβ 0 errorsnode scripts/github-mcp-smoke.mjs smokeβ pulled v1.0.2, spawned, 41 tools detected, core subset verifiednode scripts/playwright-mcp-smoke.mjs install + smokeβ 21 tools detected,browser_navigate+browser_closeboth returned valid responsesRelationship to other PRs
Independent of #83 and #84 β this one only touches github + playwright. Can merge in any order.