| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
0.70.0: the first release under the new name, and the deletion declared (#1390) Both old names were deleted from the index on 2026-09-23 to free the new one: aihawk and the shim that held invisible-playwright-mcp. Four endpoints answer 404 for both (JSON, simple, RSS, the file host) while invisible-playwright answers 200 at the same moment, and PyPI accepted a pending publisher for the new name, which it does only for a name that does not exist. So today `uvx invisible-playwright-mcp` resolves to nothing, and this version is what the README's instructions need to reach. It also takes back a correction that was itself wrong. #1389 called the 404 a transient, on the premise that PyPI does not let a deleted name be registered again. It does, which is what made the rename possible; the deletion was real and propagated unevenly. Three docstrings now say so. The releases check learns the case it was missing. A deleted project answers 404 and so does an index having a bad minute, and nothing the index says can tell them apart, so each distribution carries the day it was deleted, declared like the boundary. Deleted ranges are not asked, and their tags are not evidence that something should be served. The declaration is checked in the one direction the index can answer: a project declared deleted that serves versions fails. The single-version guard is now a skip: the first release under the new name is the only version on the index, and failing on that would be red on every pull request until a second release, for nothing wrong. Proven by three mutations, each red and naming its cause: aihawk declared live, the boundary moved to 0.68.0, and a served project declared deleted. | 2 天前 | |
The package, the command and the module are invisible-playwright-mcp (#1385) PyPI has no rename, so the old name was deleted from the index and this takes the name the shim used to hold. The distribution and the command are invisible-playwright-mcp, the module is invisible_playwright_mcp: one is typed at a shell, the other is imported, and pyproject.toml is the name one house. Kept because they name state that already exists, where a rename is not a move but a silent loss: the session directory under %APPDATA%, Application Support and XDG_DATA_HOME, the three localStorage keys, the AIHAWK_ variables and the registry name. Four gates were reporting on a copy of the name rather than on the name, and the worst of them went green: the content gate could no longer find the command in the README fences, so four of its checks were skipped while it printed clean. Merged with all 14 checks green, the releases check among them: it had been red on main since the previous rename, and the fix for a project the index has never heard of closes it for the right reason. | 3 天前 | |
The package, the command and the module are invisible-playwright-mcp (#1385) PyPI has no rename, so the old name was deleted from the index and this takes the name the shim used to hold. The distribution and the command are invisible-playwright-mcp, the module is invisible_playwright_mcp: one is typed at a shell, the other is imported, and pyproject.toml is the name one house. Kept because they name state that already exists, where a rename is not a move but a silent loss: the session directory under %APPDATA%, Application Support and XDG_DATA_HOME, the three localStorage keys, the AIHAWK_ variables and the registry name. Four gates were reporting on a copy of the name rather than on the name, and the worst of them went green: the content gate could no longer find the command in the README fences, so four of its checks were skipped while it printed clean. Merged with all 14 checks green, the releases check among them: it had been red on main since the previous rename, and the fix for a project the index has never heard of closes it for the right reason. | 3 天前 | |
The old name is abandoned, and it hands over its data on the way out (#1386) The package rename kept six things, each for a measured reason, and every one of those reasons was about somebody data or somebody position. The answer is not choosing between the name and the data: it is carrying the data along. The variables are INVISIBLE_MCP_HOME, INVISIBLE_MCP_MODEL and INVISIBLE_MCP_SESSION_ID, with env.py the one place that knows them, because each is now two strings. The retired name still answers and says so once, through the logger, since stdout is the protocol channel. The session directory is invisible-playwright-mcp, and the old one is moved onto it at startup, once, printing where to. storage.home() stays a pure answer to where is the directory. The browser three keys are built from one prefix and carried across on the first read; one of them holds an unsent draft. The registry name and the eight wiki slugs were chosen by the owner after reading the cost: the registry gets a second entry with no redirect from the first, and six pages that held the first result for their query lose those positions with no 301. Left on purpose: the LICENSE copyright line, the Telegram community URL, and the retired names themselves, which are what the hand-over reads. Merged with all 14 checks green. | 3 天前 | |
The package, the command and the module are invisible-playwright-mcp (#1385) PyPI has no rename, so the old name was deleted from the index and this takes the name the shim used to hold. The distribution and the command are invisible-playwright-mcp, the module is invisible_playwright_mcp: one is typed at a shell, the other is imported, and pyproject.toml is the name one house. Kept because they name state that already exists, where a rename is not a move but a silent loss: the session directory under %APPDATA%, Application Support and XDG_DATA_HOME, the three localStorage keys, the AIHAWK_ variables and the registry name. Four gates were reporting on a copy of the name rather than on the name, and the worst of them went green: the content gate could no longer find the command in the README fences, so four of its checks were skipped while it printed clean. Merged with all 14 checks green, the releases check among them: it had been red on main since the previous rename, and the fix for a project the index has never heard of closes it for the right reason. | 3 天前 | |
The old name is abandoned, and it hands over its data on the way out (#1386) The package rename kept six things, each for a measured reason, and every one of those reasons was about somebody data or somebody position. The answer is not choosing between the name and the data: it is carrying the data along. The variables are INVISIBLE_MCP_HOME, INVISIBLE_MCP_MODEL and INVISIBLE_MCP_SESSION_ID, with env.py the one place that knows them, because each is now two strings. The retired name still answers and says so once, through the logger, since stdout is the protocol channel. The session directory is invisible-playwright-mcp, and the old one is moved onto it at startup, once, printing where to. storage.home() stays a pure answer to where is the directory. The browser three keys are built from one prefix and carried across on the first read; one of them holds an unsent draft. The registry name and the eight wiki slugs were chosen by the owner after reading the cost: the registry gets a second entry with no redirect from the first, and six pages that held the first result for their query lose those positions with no 301. Left on purpose: the LICENSE copyright line, the Telegram community URL, and the retired names themselves, which are what the hand-over reads. Merged with all 14 checks green. | 3 天前 | |
The package, the command and the module are invisible-playwright-mcp (#1385) PyPI has no rename, so the old name was deleted from the index and this takes the name the shim used to hold. The distribution and the command are invisible-playwright-mcp, the module is invisible_playwright_mcp: one is typed at a shell, the other is imported, and pyproject.toml is the name one house. Kept because they name state that already exists, where a rename is not a move but a silent loss: the session directory under %APPDATA%, Application Support and XDG_DATA_HOME, the three localStorage keys, the AIHAWK_ variables and the registry name. Four gates were reporting on a copy of the name rather than on the name, and the worst of them went green: the content gate could no longer find the command in the README fences, so four of its checks were skipped while it printed clean. Merged with all 14 checks green, the releases check among them: it had been red on main since the previous rename, and the fix for a project the index has never heard of closes it for the right reason. | 3 天前 | |
The old name is abandoned, and it hands over its data on the way out (#1386) The package rename kept six things, each for a measured reason, and every one of those reasons was about somebody data or somebody position. The answer is not choosing between the name and the data: it is carrying the data along. The variables are INVISIBLE_MCP_HOME, INVISIBLE_MCP_MODEL and INVISIBLE_MCP_SESSION_ID, with env.py the one place that knows them, because each is now two strings. The retired name still answers and says so once, through the logger, since stdout is the protocol channel. The session directory is invisible-playwright-mcp, and the old one is moved onto it at startup, once, printing where to. storage.home() stays a pure answer to where is the directory. The browser three keys are built from one prefix and carried across on the first read; one of them holds an unsent draft. The registry name and the eight wiki slugs were chosen by the owner after reading the cost: the registry gets a second entry with no redirect from the first, and six pages that held the first result for their query lose those positions with no 301. Left on purpose: the LICENSE copyright line, the Telegram community URL, and the retired names themselves, which are what the hand-over reads. Merged with all 14 checks green. | 3 天前 | |
The package, the command and the module are invisible-playwright-mcp (#1385) PyPI has no rename, so the old name was deleted from the index and this takes the name the shim used to hold. The distribution and the command are invisible-playwright-mcp, the module is invisible_playwright_mcp: one is typed at a shell, the other is imported, and pyproject.toml is the name one house. Kept because they name state that already exists, where a rename is not a move but a silent loss: the session directory under %APPDATA%, Application Support and XDG_DATA_HOME, the three localStorage keys, the AIHAWK_ variables and the registry name. Four gates were reporting on a copy of the name rather than on the name, and the worst of them went green: the content gate could no longer find the command in the README fences, so four of its checks were skipped while it printed clean. Merged with all 14 checks green, the releases check among them: it had been red on main since the previous rename, and the fix for a project the index has never heard of closes it for the right reason. | 3 天前 | |
The package, the command and the module are invisible-playwright-mcp (#1385) PyPI has no rename, so the old name was deleted from the index and this takes the name the shim used to hold. The distribution and the command are invisible-playwright-mcp, the module is invisible_playwright_mcp: one is typed at a shell, the other is imported, and pyproject.toml is the name one house. Kept because they name state that already exists, where a rename is not a move but a silent loss: the session directory under %APPDATA%, Application Support and XDG_DATA_HOME, the three localStorage keys, the AIHAWK_ variables and the registry name. Four gates were reporting on a copy of the name rather than on the name, and the worst of them went green: the content gate could no longer find the command in the README fences, so four of its checks were skipped while it printed clean. Merged with all 14 checks green, the releases check among them: it had been red on main since the previous rename, and the fix for a project the index has never heard of closes it for the right reason. | 3 天前 | |
The package, the command and the module are invisible-playwright-mcp (#1385) PyPI has no rename, so the old name was deleted from the index and this takes the name the shim used to hold. The distribution and the command are invisible-playwright-mcp, the module is invisible_playwright_mcp: one is typed at a shell, the other is imported, and pyproject.toml is the name one house. Kept because they name state that already exists, where a rename is not a move but a silent loss: the session directory under %APPDATA%, Application Support and XDG_DATA_HOME, the three localStorage keys, the AIHAWK_ variables and the registry name. Four gates were reporting on a copy of the name rather than on the name, and the worst of them went green: the content gate could no longer find the command in the README fences, so four of its checks were skipped while it printed clean. Merged with all 14 checks green, the releases check among them: it had been red on main since the previous rename, and the fix for a project the index has never heard of closes it for the right reason. | 3 天前 | |
Sixteen tests nobody was running, and they had rotted (#1356) Sixteen tests nobody was running, and they had rotted `addopts` is `-m 'not ui and not e2e'`, and the only job that asked for anything asked for `-m e2e tests/mcp_server`. So the sixteen tests in tests/test_ui_drive.py - which drive a real browser through a real MCP server, the sharpest thing this suite can do - were selected by no run anywhere. ALL SIXTEEN ERRORED AT FIXTURE SETUP, and had for some time. The fixture navigated into a browser it had never opened; the product stopped allowing that when browser_open became the only tool that opens one, and the comment beside the call still described the older world in so many words: "browser_navigate opens the first page itself, which is the only way a page is opened at all". True when written. NOTHING COULD GO RED. A deselected test does not fail. It is absent, and a summary calls that "deselected", which reads like a decision rather than a gap. Same shape as the workflow trigger that never fires, one file over: something is declared and nothing executes it. With browser_open added to the fixture, all sixteen pass in 27 seconds. THE FIX IS THE CAUSE. The e2e job already fetches an engine and already drives it, so it now runs the ui selection too, after the e2e one because both drive real browsers and must run serially. About half a minute, no extra download. AND A GATE ON THE CLASS: every marker `addopts` deselects must be named by some workflow. A marker nobody asks for is a set of tests nobody runs, and they rot without a red. ⛔ THAT GATE FAILED ITS OWN FIRST KNOWN-BAD, and the way it failed is worth the line it cost. Removing `-m ui` from the job left it green - because the comment I had just written beside the job, the one explaining that it now runs `-m ui`, satisfied the search. The check was answered by the prose next to the code, which is the most repeated defect in this repository, met inside the gate written to find things that never run. It strips comments now, and the known-bad kills it. The second known-bad is the one that proves the defect was real rather than imagined: put the fixture back as it was and the sixteen error again. AND THE ENGLISH GATE CAUGHT ME while this was being written - an Italian sentence in a comment, in a public English-only repository. It works. Also measured while the machine was idle, because a suite this expensive is worth knowing the shape of: with STEALTHFOX_BINARY pointed at the pinned engine, the e2e selection is 34 passed and 0 skipped in six minutes. Without it, twelve of those skip for want of a real binary - which is what the runner does, and is worth knowing rather than reading 22 passed as full coverage. Suite 681 green by default, 16 green on -m ui, 34 green on -m e2e. Tests and a workflow, nothing that goes into the wheel, so no version. | 10 天前 | |
The package, the command and the module are invisible-playwright-mcp (#1385) PyPI has no rename, so the old name was deleted from the index and this takes the name the shim used to hold. The distribution and the command are invisible-playwright-mcp, the module is invisible_playwright_mcp: one is typed at a shell, the other is imported, and pyproject.toml is the name one house. Kept because they name state that already exists, where a rename is not a move but a silent loss: the session directory under %APPDATA%, Application Support and XDG_DATA_HOME, the three localStorage keys, the AIHAWK_ variables and the registry name. Four gates were reporting on a copy of the name rather than on the name, and the worst of them went green: the content gate could no longer find the command in the README fences, so four of its checks were skipped while it printed clean. Merged with all 14 checks green, the releases check among them: it had been red on main since the previous rename, and the fix for a project the index has never heard of closes it for the right reason. | 3 天前 | |
The package, the command and the module are invisible-playwright-mcp (#1385) PyPI has no rename, so the old name was deleted from the index and this takes the name the shim used to hold. The distribution and the command are invisible-playwright-mcp, the module is invisible_playwright_mcp: one is typed at a shell, the other is imported, and pyproject.toml is the name one house. Kept because they name state that already exists, where a rename is not a move but a silent loss: the session directory under %APPDATA%, Application Support and XDG_DATA_HOME, the three localStorage keys, the AIHAWK_ variables and the registry name. Four gates were reporting on a copy of the name rather than on the name, and the worst of them went green: the content gate could no longer find the command in the README fences, so four of its checks were skipped while it printed clean. Merged with all 14 checks green, the releases check among them: it had been red on main since the previous rename, and the fix for a project the index has never heard of closes it for the right reason. | 3 天前 | |
The old name is abandoned, and it hands over its data on the way out (#1386) The package rename kept six things, each for a measured reason, and every one of those reasons was about somebody data or somebody position. The answer is not choosing between the name and the data: it is carrying the data along. The variables are INVISIBLE_MCP_HOME, INVISIBLE_MCP_MODEL and INVISIBLE_MCP_SESSION_ID, with env.py the one place that knows them, because each is now two strings. The retired name still answers and says so once, through the logger, since stdout is the protocol channel. The session directory is invisible-playwright-mcp, and the old one is moved onto it at startup, once, printing where to. storage.home() stays a pure answer to where is the directory. The browser three keys are built from one prefix and carried across on the first read; one of them holds an unsent draft. The registry name and the eight wiki slugs were chosen by the owner after reading the cost: the registry gets a second entry with no redirect from the first, and six pages that held the first result for their query lose those positions with no 301. Left on purpose: the LICENSE copyright line, the Telegram community URL, and the retired names themselves, which are what the hand-over reads. Merged with all 14 checks green. | 3 天前 | |
The package, the command and the module are invisible-playwright-mcp (#1385) PyPI has no rename, so the old name was deleted from the index and this takes the name the shim used to hold. The distribution and the command are invisible-playwright-mcp, the module is invisible_playwright_mcp: one is typed at a shell, the other is imported, and pyproject.toml is the name one house. Kept because they name state that already exists, where a rename is not a move but a silent loss: the session directory under %APPDATA%, Application Support and XDG_DATA_HOME, the three localStorage keys, the AIHAWK_ variables and the registry name. Four gates were reporting on a copy of the name rather than on the name, and the worst of them went green: the content gate could no longer find the command in the README fences, so four of its checks were skipped while it printed clean. Merged with all 14 checks green, the releases check among them: it had been red on main since the previous rename, and the fix for a project the index has never heard of closes it for the right reason. | 3 天前 | |
The old name is abandoned, and it hands over its data on the way out (#1386) The package rename kept six things, each for a measured reason, and every one of those reasons was about somebody data or somebody position. The answer is not choosing between the name and the data: it is carrying the data along. The variables are INVISIBLE_MCP_HOME, INVISIBLE_MCP_MODEL and INVISIBLE_MCP_SESSION_ID, with env.py the one place that knows them, because each is now two strings. The retired name still answers and says so once, through the logger, since stdout is the protocol channel. The session directory is invisible-playwright-mcp, and the old one is moved onto it at startup, once, printing where to. storage.home() stays a pure answer to where is the directory. The browser three keys are built from one prefix and carried across on the first read; one of them holds an unsent draft. The registry name and the eight wiki slugs were chosen by the owner after reading the cost: the registry gets a second entry with no redirect from the first, and six pages that held the first result for their query lose those positions with no 301. Left on purpose: the LICENSE copyright line, the Telegram community URL, and the retired names themselves, which are what the hand-over reads. Merged with all 14 checks green. | 3 天前 | |
The old name is abandoned, and it hands over its data on the way out (#1386) The package rename kept six things, each for a measured reason, and every one of those reasons was about somebody data or somebody position. The answer is not choosing between the name and the data: it is carrying the data along. The variables are INVISIBLE_MCP_HOME, INVISIBLE_MCP_MODEL and INVISIBLE_MCP_SESSION_ID, with env.py the one place that knows them, because each is now two strings. The retired name still answers and says so once, through the logger, since stdout is the protocol channel. The session directory is invisible-playwright-mcp, and the old one is moved onto it at startup, once, printing where to. storage.home() stays a pure answer to where is the directory. The browser three keys are built from one prefix and carried across on the first read; one of them holds an unsent draft. The registry name and the eight wiki slugs were chosen by the owner after reading the cost: the registry gets a second entry with no redirect from the first, and six pages that held the first result for their query lose those positions with no 301. Left on purpose: the LICENSE copyright line, the Telegram community URL, and the retired names themselves, which are what the hand-over reads. Merged with all 14 checks green. | 3 天前 | |
The package, the command and the module are invisible-playwright-mcp (#1385) PyPI has no rename, so the old name was deleted from the index and this takes the name the shim used to hold. The distribution and the command are invisible-playwright-mcp, the module is invisible_playwright_mcp: one is typed at a shell, the other is imported, and pyproject.toml is the name one house. Kept because they name state that already exists, where a rename is not a move but a silent loss: the session directory under %APPDATA%, Application Support and XDG_DATA_HOME, the three localStorage keys, the AIHAWK_ variables and the registry name. Four gates were reporting on a copy of the name rather than on the name, and the worst of them went green: the content gate could no longer find the command in the README fences, so four of its checks were skipped while it printed clean. Merged with all 14 checks green, the releases check among them: it had been red on main since the previous rename, and the fix for a project the index has never heard of closes it for the right reason. | 3 天前 | |
The package, the command and the module are invisible-playwright-mcp (#1385) PyPI has no rename, so the old name was deleted from the index and this takes the name the shim used to hold. The distribution and the command are invisible-playwright-mcp, the module is invisible_playwright_mcp: one is typed at a shell, the other is imported, and pyproject.toml is the name one house. Kept because they name state that already exists, where a rename is not a move but a silent loss: the session directory under %APPDATA%, Application Support and XDG_DATA_HOME, the three localStorage keys, the AIHAWK_ variables and the registry name. Four gates were reporting on a copy of the name rather than on the name, and the worst of them went green: the content gate could no longer find the command in the README fences, so four of its checks were skipped while it printed clean. Merged with all 14 checks green, the releases check among them: it had been red on main since the previous rename, and the fix for a project the index has never heard of closes it for the right reason. | 3 天前 | |
The package, the command and the module are invisible-playwright-mcp (#1385) PyPI has no rename, so the old name was deleted from the index and this takes the name the shim used to hold. The distribution and the command are invisible-playwright-mcp, the module is invisible_playwright_mcp: one is typed at a shell, the other is imported, and pyproject.toml is the name one house. Kept because they name state that already exists, where a rename is not a move but a silent loss: the session directory under %APPDATA%, Application Support and XDG_DATA_HOME, the three localStorage keys, the AIHAWK_ variables and the registry name. Four gates were reporting on a copy of the name rather than on the name, and the worst of them went green: the content gate could no longer find the command in the README fences, so four of its checks were skipped while it printed clean. Merged with all 14 checks green, the releases check among them: it had been red on main since the previous rename, and the fix for a project the index has never heard of closes it for the right reason. | 3 天前 | |
The old name is abandoned, and it hands over its data on the way out (#1386) The package rename kept six things, each for a measured reason, and every one of those reasons was about somebody data or somebody position. The answer is not choosing between the name and the data: it is carrying the data along. The variables are INVISIBLE_MCP_HOME, INVISIBLE_MCP_MODEL and INVISIBLE_MCP_SESSION_ID, with env.py the one place that knows them, because each is now two strings. The retired name still answers and says so once, through the logger, since stdout is the protocol channel. The session directory is invisible-playwright-mcp, and the old one is moved onto it at startup, once, printing where to. storage.home() stays a pure answer to where is the directory. The browser three keys are built from one prefix and carried across on the first read; one of them holds an unsent draft. The registry name and the eight wiki slugs were chosen by the owner after reading the cost: the registry gets a second entry with no redirect from the first, and six pages that held the first result for their query lose those positions with no 301. Left on purpose: the LICENSE copyright line, the Telegram community URL, and the retired names themselves, which are what the hand-over reads. Merged with all 14 checks green. | 3 天前 | |
The old name is abandoned, and it hands over its data on the way out (#1386) The package rename kept six things, each for a measured reason, and every one of those reasons was about somebody data or somebody position. The answer is not choosing between the name and the data: it is carrying the data along. The variables are INVISIBLE_MCP_HOME, INVISIBLE_MCP_MODEL and INVISIBLE_MCP_SESSION_ID, with env.py the one place that knows them, because each is now two strings. The retired name still answers and says so once, through the logger, since stdout is the protocol channel. The session directory is invisible-playwright-mcp, and the old one is moved onto it at startup, once, printing where to. storage.home() stays a pure answer to where is the directory. The browser three keys are built from one prefix and carried across on the first read; one of them holds an unsent draft. The registry name and the eight wiki slugs were chosen by the owner after reading the cost: the registry gets a second entry with no redirect from the first, and six pages that held the first result for their query lose those positions with no 301. Left on purpose: the LICENSE copyright line, the Telegram community URL, and the retired names themselves, which are what the hand-over reads. Merged with all 14 checks green. | 3 天前 | |
The interface after a UX pass: a modal panel, a truthful transcript, controls that say what they do (#1302) A UX pass over the interface, driven by an audit of six dimensions - spatial model, typography, interaction, accessibility, visual hierarchy, first run and failure states - with every finding verified against the code before it was acted on, and every change checked in a real browser afterwards. The owner's complaint first. The sessions panel covered half the conversation and left it looking readable: measured 240px off the front of every line at every desktop width, 48% of the measure at 1440px, 61% at 960. It is a modal now - the page behind it goes inert and dims, Escape closes it, a click outside closes it, choosing a conversation closes it - and `inert` has one owner because two reasons can hold the same pane. The transcript stops saying things that are not true. A step nobody landed breathed for ever; Stop was reported as an error; a failed step was marked by colour alone with the same verb as one still running; tool output was cut in silence for the watcher and the model; a dead stream left the clock counting; the queued sentence was never on screen and a second Enter destroyed it; the most frequent row said the same four words twice. Nobody is locked out by how they use it. The live region was rewritten 25 times a second; a reconnect read the whole conversation aloud; the one input had no focus ring, then two; every finished step was a tab stop that opened nothing; screens and chips were named by their contents. Every control says what it does. Enter looks different when it will queue; Clear explains itself instead of going dead; the first-run example fills the box; a failed load of the session list is told from an empty one; one rule says "cannot be used"; pressed is one rung above hovered; the panel's icon sits on the line everything else shares. Found only by screenshots, and recorded as such: a comment inside a start tag that printed attributes down the seam between the panes; two backspace bytes that had blinded two gates; two nested focus rectangles on the composer. Each has a gate now, including one that reads the bytes of every tracked file and one that reads the served page with an HTML parser. Measured and rejected, so nobody re-derives it: widening the conversation when the browser pane is empty (it already opens at 70 characters a line), and centring the two panes (ragged bands at both edges). 579 passed. Fifty-one known-bad mutations run against the new and rewritten gates, fifty-one killed. One commit landed with a red test because the suite's verdict was read through a word filter; the next commit says so and fixes it. | 13 天前 | |
The package, the command and the module are invisible-playwright-mcp (#1385) PyPI has no rename, so the old name was deleted from the index and this takes the name the shim used to hold. The distribution and the command are invisible-playwright-mcp, the module is invisible_playwright_mcp: one is typed at a shell, the other is imported, and pyproject.toml is the name one house. Kept because they name state that already exists, where a rename is not a move but a silent loss: the session directory under %APPDATA%, Application Support and XDG_DATA_HOME, the three localStorage keys, the AIHAWK_ variables and the registry name. Four gates were reporting on a copy of the name rather than on the name, and the worst of them went green: the content gate could no longer find the command in the README fences, so four of its checks were skipped while it printed clean. Merged with all 14 checks green, the releases check among them: it had been red on main since the previous rename, and the fix for a project the index has never heard of closes it for the right reason. | 3 天前 | |
The old name is abandoned, and it hands over its data on the way out (#1386) The package rename kept six things, each for a measured reason, and every one of those reasons was about somebody data or somebody position. The answer is not choosing between the name and the data: it is carrying the data along. The variables are INVISIBLE_MCP_HOME, INVISIBLE_MCP_MODEL and INVISIBLE_MCP_SESSION_ID, with env.py the one place that knows them, because each is now two strings. The retired name still answers and says so once, through the logger, since stdout is the protocol channel. The session directory is invisible-playwright-mcp, and the old one is moved onto it at startup, once, printing where to. storage.home() stays a pure answer to where is the directory. The browser three keys are built from one prefix and carried across on the first read; one of them holds an unsent draft. The registry name and the eight wiki slugs were chosen by the owner after reading the cost: the registry gets a second entry with no redirect from the first, and six pages that held the first result for their query lose those positions with no 301. Left on purpose: the LICENSE copyright line, the Telegram community URL, and the retired names themselves, which are what the hand-over reads. Merged with all 14 checks green. | 3 天前 | |
The package, the command and the module are invisible-playwright-mcp (#1385) PyPI has no rename, so the old name was deleted from the index and this takes the name the shim used to hold. The distribution and the command are invisible-playwright-mcp, the module is invisible_playwright_mcp: one is typed at a shell, the other is imported, and pyproject.toml is the name one house. Kept because they name state that already exists, where a rename is not a move but a silent loss: the session directory under %APPDATA%, Application Support and XDG_DATA_HOME, the three localStorage keys, the AIHAWK_ variables and the registry name. Four gates were reporting on a copy of the name rather than on the name, and the worst of them went green: the content gate could no longer find the command in the README fences, so four of its checks were skipped while it printed clean. Merged with all 14 checks green, the releases check among them: it had been red on main since the previous rename, and the fix for a project the index has never heard of closes it for the right reason. | 3 天前 | |
The old name is abandoned, and it hands over its data on the way out (#1386) The package rename kept six things, each for a measured reason, and every one of those reasons was about somebody data or somebody position. The answer is not choosing between the name and the data: it is carrying the data along. The variables are INVISIBLE_MCP_HOME, INVISIBLE_MCP_MODEL and INVISIBLE_MCP_SESSION_ID, with env.py the one place that knows them, because each is now two strings. The retired name still answers and says so once, through the logger, since stdout is the protocol channel. The session directory is invisible-playwright-mcp, and the old one is moved onto it at startup, once, printing where to. storage.home() stays a pure answer to where is the directory. The browser three keys are built from one prefix and carried across on the first read; one of them holds an unsent draft. The registry name and the eight wiki slugs were chosen by the owner after reading the cost: the registry gets a second entry with no redirect from the first, and six pages that held the first result for their query lose those positions with no 301. Left on purpose: the LICENSE copyright line, the Telegram community URL, and the retired names themselves, which are what the hand-over reads. Merged with all 14 checks green. | 3 天前 | |
The old name is abandoned, and it hands over its data on the way out (#1386) The package rename kept six things, each for a measured reason, and every one of those reasons was about somebody data or somebody position. The answer is not choosing between the name and the data: it is carrying the data along. The variables are INVISIBLE_MCP_HOME, INVISIBLE_MCP_MODEL and INVISIBLE_MCP_SESSION_ID, with env.py the one place that knows them, because each is now two strings. The retired name still answers and says so once, through the logger, since stdout is the protocol channel. The session directory is invisible-playwright-mcp, and the old one is moved onto it at startup, once, printing where to. storage.home() stays a pure answer to where is the directory. The browser three keys are built from one prefix and carried across on the first read; one of them holds an unsent draft. The registry name and the eight wiki slugs were chosen by the owner after reading the cost: the registry gets a second entry with no redirect from the first, and six pages that held the first result for their query lose those positions with no 301. Left on purpose: the LICENSE copyright line, the Telegram community URL, and the retired names themselves, which are what the hand-over reads. Merged with all 14 checks green. | 3 天前 | |
The package, the command and the module are invisible-playwright-mcp (#1385) PyPI has no rename, so the old name was deleted from the index and this takes the name the shim used to hold. The distribution and the command are invisible-playwright-mcp, the module is invisible_playwright_mcp: one is typed at a shell, the other is imported, and pyproject.toml is the name one house. Kept because they name state that already exists, where a rename is not a move but a silent loss: the session directory under %APPDATA%, Application Support and XDG_DATA_HOME, the three localStorage keys, the AIHAWK_ variables and the registry name. Four gates were reporting on a copy of the name rather than on the name, and the worst of them went green: the content gate could no longer find the command in the README fences, so four of its checks were skipped while it printed clean. Merged with all 14 checks green, the releases check among them: it had been red on main since the previous rename, and the fix for a project the index has never heard of closes it for the right reason. | 3 天前 | |
The package, the command and the module are invisible-playwright-mcp (#1385) PyPI has no rename, so the old name was deleted from the index and this takes the name the shim used to hold. The distribution and the command are invisible-playwright-mcp, the module is invisible_playwright_mcp: one is typed at a shell, the other is imported, and pyproject.toml is the name one house. Kept because they name state that already exists, where a rename is not a move but a silent loss: the session directory under %APPDATA%, Application Support and XDG_DATA_HOME, the three localStorage keys, the AIHAWK_ variables and the registry name. Four gates were reporting on a copy of the name rather than on the name, and the worst of them went green: the content gate could no longer find the command in the README fences, so four of its checks were skipped while it printed clean. Merged with all 14 checks green, the releases check among them: it had been red on main since the previous rename, and the fix for a project the index has never heard of closes it for the right reason. | 3 天前 | |
0.70.0: the first release under the new name, and the deletion declared (#1390) Both old names were deleted from the index on 2026-09-23 to free the new one: aihawk and the shim that held invisible-playwright-mcp. Four endpoints answer 404 for both (JSON, simple, RSS, the file host) while invisible-playwright answers 200 at the same moment, and PyPI accepted a pending publisher for the new name, which it does only for a name that does not exist. So today `uvx invisible-playwright-mcp` resolves to nothing, and this version is what the README's instructions need to reach. It also takes back a correction that was itself wrong. #1389 called the 404 a transient, on the premise that PyPI does not let a deleted name be registered again. It does, which is what made the rename possible; the deletion was real and propagated unevenly. Three docstrings now say so. The releases check learns the case it was missing. A deleted project answers 404 and so does an index having a bad minute, and nothing the index says can tell them apart, so each distribution carries the day it was deleted, declared like the boundary. Deleted ranges are not asked, and their tags are not evidence that something should be served. The declaration is checked in the one direction the index can answer: a project declared deleted that serves versions fails. The single-version guard is now a skip: the first release under the new name is the only version on the index, and failing on that would be red on every pull request until a second release, for nothing wrong. Proven by three mutations, each red and naming its cause: aihawk declared live, the boundary moved to 0.68.0, and a served project declared deleted. | 2 天前 | |
The old name is abandoned, and it hands over its data on the way out (#1386) The package rename kept six things, each for a measured reason, and every one of those reasons was about somebody data or somebody position. The answer is not choosing between the name and the data: it is carrying the data along. The variables are INVISIBLE_MCP_HOME, INVISIBLE_MCP_MODEL and INVISIBLE_MCP_SESSION_ID, with env.py the one place that knows them, because each is now two strings. The retired name still answers and says so once, through the logger, since stdout is the protocol channel. The session directory is invisible-playwright-mcp, and the old one is moved onto it at startup, once, printing where to. storage.home() stays a pure answer to where is the directory. The browser three keys are built from one prefix and carried across on the first read; one of them holds an unsent draft. The registry name and the eight wiki slugs were chosen by the owner after reading the cost: the registry gets a second entry with no redirect from the first, and six pages that held the first result for their query lose those positions with no 301. Left on purpose: the LICENSE copyright line, the Telegram community URL, and the retired names themselves, which are what the hand-over reads. Merged with all 14 checks green. | 3 天前 | |
The package, the command and the module are invisible-playwright-mcp (#1385) PyPI has no rename, so the old name was deleted from the index and this takes the name the shim used to hold. The distribution and the command are invisible-playwright-mcp, the module is invisible_playwright_mcp: one is typed at a shell, the other is imported, and pyproject.toml is the name one house. Kept because they name state that already exists, where a rename is not a move but a silent loss: the session directory under %APPDATA%, Application Support and XDG_DATA_HOME, the three localStorage keys, the AIHAWK_ variables and the registry name. Four gates were reporting on a copy of the name rather than on the name, and the worst of them went green: the content gate could no longer find the command in the README fences, so four of its checks were skipped while it printed clean. Merged with all 14 checks green, the releases check among them: it had been red on main since the previous rename, and the fix for a project the index has never heard of closes it for the right reason. | 3 天前 | |
The package, the command and the module are invisible-playwright-mcp (#1385) PyPI has no rename, so the old name was deleted from the index and this takes the name the shim used to hold. The distribution and the command are invisible-playwright-mcp, the module is invisible_playwright_mcp: one is typed at a shell, the other is imported, and pyproject.toml is the name one house. Kept because they name state that already exists, where a rename is not a move but a silent loss: the session directory under %APPDATA%, Application Support and XDG_DATA_HOME, the three localStorage keys, the AIHAWK_ variables and the registry name. Four gates were reporting on a copy of the name rather than on the name, and the worst of them went green: the content gate could no longer find the command in the README fences, so four of its checks were skipped while it printed clean. Merged with all 14 checks green, the releases check among them: it had been red on main since the previous rename, and the fix for a project the index has never heard of closes it for the right reason. | 3 天前 | |
The package, the command and the module are invisible-playwright-mcp (#1385) PyPI has no rename, so the old name was deleted from the index and this takes the name the shim used to hold. The distribution and the command are invisible-playwright-mcp, the module is invisible_playwright_mcp: one is typed at a shell, the other is imported, and pyproject.toml is the name one house. Kept because they name state that already exists, where a rename is not a move but a silent loss: the session directory under %APPDATA%, Application Support and XDG_DATA_HOME, the three localStorage keys, the AIHAWK_ variables and the registry name. Four gates were reporting on a copy of the name rather than on the name, and the worst of them went green: the content gate could no longer find the command in the README fences, so four of its checks were skipped while it printed clean. Merged with all 14 checks green, the releases check among them: it had been red on main since the previous rename, and the fix for a project the index has never heard of closes it for the right reason. | 3 天前 | |
The package, the command and the module are invisible-playwright-mcp (#1385) PyPI has no rename, so the old name was deleted from the index and this takes the name the shim used to hold. The distribution and the command are invisible-playwright-mcp, the module is invisible_playwright_mcp: one is typed at a shell, the other is imported, and pyproject.toml is the name one house. Kept because they name state that already exists, where a rename is not a move but a silent loss: the session directory under %APPDATA%, Application Support and XDG_DATA_HOME, the three localStorage keys, the AIHAWK_ variables and the registry name. Four gates were reporting on a copy of the name rather than on the name, and the worst of them went green: the content gate could no longer find the command in the README fences, so four of its checks were skipped while it printed clean. Merged with all 14 checks green, the releases check among them: it had been red on main since the previous rename, and the fix for a project the index has never heard of closes it for the right reason. | 3 天前 | |
The package, the command and the module are invisible-playwright-mcp (#1385) PyPI has no rename, so the old name was deleted from the index and this takes the name the shim used to hold. The distribution and the command are invisible-playwright-mcp, the module is invisible_playwright_mcp: one is typed at a shell, the other is imported, and pyproject.toml is the name one house. Kept because they name state that already exists, where a rename is not a move but a silent loss: the session directory under %APPDATA%, Application Support and XDG_DATA_HOME, the three localStorage keys, the AIHAWK_ variables and the registry name. Four gates were reporting on a copy of the name rather than on the name, and the worst of them went green: the content gate could no longer find the command in the README fences, so four of its checks were skipped while it printed clean. Merged with all 14 checks green, the releases check among them: it had been red on main since the previous rename, and the fix for a project the index has never heard of closes it for the right reason. | 3 天前 | |
The package, the command and the module are invisible-playwright-mcp (#1385) PyPI has no rename, so the old name was deleted from the index and this takes the name the shim used to hold. The distribution and the command are invisible-playwright-mcp, the module is invisible_playwright_mcp: one is typed at a shell, the other is imported, and pyproject.toml is the name one house. Kept because they name state that already exists, where a rename is not a move but a silent loss: the session directory under %APPDATA%, Application Support and XDG_DATA_HOME, the three localStorage keys, the AIHAWK_ variables and the registry name. Four gates were reporting on a copy of the name rather than on the name, and the worst of them went green: the content gate could no longer find the command in the README fences, so four of its checks were skipped while it printed clean. Merged with all 14 checks green, the releases check among them: it had been red on main since the previous rename, and the fix for a project the index has never heard of closes it for the right reason. | 3 天前 | |
The package, the command and the module are invisible-playwright-mcp (#1385) PyPI has no rename, so the old name was deleted from the index and this takes the name the shim used to hold. The distribution and the command are invisible-playwright-mcp, the module is invisible_playwright_mcp: one is typed at a shell, the other is imported, and pyproject.toml is the name one house. Kept because they name state that already exists, where a rename is not a move but a silent loss: the session directory under %APPDATA%, Application Support and XDG_DATA_HOME, the three localStorage keys, the AIHAWK_ variables and the registry name. Four gates were reporting on a copy of the name rather than on the name, and the worst of them went green: the content gate could no longer find the command in the README fences, so four of its checks were skipped while it printed clean. Merged with all 14 checks green, the releases check among them: it had been red on main since the previous rename, and the fix for a project the index has never heard of closes it for the right reason. | 3 天前 | |
The package, the command and the module are invisible-playwright-mcp (#1385) PyPI has no rename, so the old name was deleted from the index and this takes the name the shim used to hold. The distribution and the command are invisible-playwright-mcp, the module is invisible_playwright_mcp: one is typed at a shell, the other is imported, and pyproject.toml is the name one house. Kept because they name state that already exists, where a rename is not a move but a silent loss: the session directory under %APPDATA%, Application Support and XDG_DATA_HOME, the three localStorage keys, the AIHAWK_ variables and the registry name. Four gates were reporting on a copy of the name rather than on the name, and the worst of them went green: the content gate could no longer find the command in the README fences, so four of its checks were skipped while it printed clean. Merged with all 14 checks green, the releases check among them: it had been red on main since the previous rename, and the fix for a project the index has never heard of closes it for the right reason. | 3 天前 | |
The language gate comes from the core, and this repository exempts nothing * The language gate comes from the core, and this repository exempts nothing invisible-core 30.23.0 carries the check that a public repository is English, as `invisible_core.english`. Until now it was a script copied here from the wrapper, and the copy carried the wrapper's data with it: four of the five paths in its exclusion list - `src/invisible_playwright/_pw/`, `_driver/`, `_juggler/injected.js`, `tests/test_fork.py` - do not exist in this repository and never did. A dead exclusion never makes anything red, which is exactly why nobody found it; the shared gate refuses one. So `scripts/check_english_only.py` is deleted, the `english` CI job installs the core and runs the module, and the tool-description test imports the word list from `invisible_core.english` instead of loading the script by path. This repository declares no `[tool.invisible.english]` at all: measured, the shared gate reads 245 tracked files here and is silent with nothing exempt. The dependency floor moves to `invisible-playwright>=0.16.2`, which is the first wrapper pinning a core that has the module the test imports. * The version is declared in three files, and the suite declares what it imports Three things the CI found on the first run, all of them mine and all of them real. The version lives in `pyproject.toml`, `manifest.json` and `server.json`, and bumping one left two behind: the gate compares them and said so. Bumped. `invisible-core` is now a DECLARED test dependency. It was already arriving through `invisible-playwright`, so nothing was missing at runtime - but since 30.23.0 the language gate is `invisible_core.english` and two test files import it directly, and an import that leans on a transitive dependency works until the day the wrapper stops needing the core. `test_the_suite_declares_everything_it _imports` caught it against the published stack, which is what it is for. And `test_the_gate_says_which_tree_it_judged.py` is rewritten against the module instead of the deleted script. Its own docstring had named this consolidation and said it was not done yet - "the single home for a rule that all three must obey is invisible_core ... that consolidation is a core release and is not done here". It is done, so the test that asserted the REFUSAL is gone: the script could only judge where it lived, so pointing it elsewhere was a mistake to catch; the module takes the tree as an argument, so pointing it elsewhere is an ordinary request. What replaces it is the property the refusal was protecting - a cross-repo run answers about the tree it was given and names it, and pointed at a guilty tree it accuses THAT one rather than reporting its own clean state. The file also pins what the copy cost: four of the five exclusions it carried named paths that only ever existed in the wrapper, and this repository now declares none. Suite 693 passed against the published stack - invisible-core 30.23.0 and invisible-playwright 0.16.2 resolved from the index, in a clean venv. ruff clean, language gate clean on 245 files with nothing exempt. | 10 天前 | |
The old name is abandoned, and it hands over its data on the way out (#1386) The package rename kept six things, each for a measured reason, and every one of those reasons was about somebody data or somebody position. The answer is not choosing between the name and the data: it is carrying the data along. The variables are INVISIBLE_MCP_HOME, INVISIBLE_MCP_MODEL and INVISIBLE_MCP_SESSION_ID, with env.py the one place that knows them, because each is now two strings. The retired name still answers and says so once, through the logger, since stdout is the protocol channel. The session directory is invisible-playwright-mcp, and the old one is moved onto it at startup, once, printing where to. storage.home() stays a pure answer to where is the directory. The browser three keys are built from one prefix and carried across on the first read; one of them holds an unsent draft. The registry name and the eight wiki slugs were chosen by the owner after reading the cost: the registry gets a second entry with no redirect from the first, and six pages that held the first result for their query lose those positions with no 301. Left on purpose: the LICENSE copyright line, the Telegram community URL, and the retired names themselves, which are what the hand-over reads. Merged with all 14 checks green. | 3 天前 | |
The old name is abandoned, and it hands over its data on the way out (#1386) The package rename kept six things, each for a measured reason, and every one of those reasons was about somebody data or somebody position. The answer is not choosing between the name and the data: it is carrying the data along. The variables are INVISIBLE_MCP_HOME, INVISIBLE_MCP_MODEL and INVISIBLE_MCP_SESSION_ID, with env.py the one place that knows them, because each is now two strings. The retired name still answers and says so once, through the logger, since stdout is the protocol channel. The session directory is invisible-playwright-mcp, and the old one is moved onto it at startup, once, printing where to. storage.home() stays a pure answer to where is the directory. The browser three keys are built from one prefix and carried across on the first read; one of them holds an unsent draft. The registry name and the eight wiki slugs were chosen by the owner after reading the cost: the registry gets a second entry with no redirect from the first, and six pages that held the first result for their query lose those positions with no 301. Left on purpose: the LICENSE copyright line, the Telegram community URL, and the retired names themselves, which are what the hand-over reads. Merged with all 14 checks green. | 3 天前 | |
The package, the command and the module are invisible-playwright-mcp (#1385) PyPI has no rename, so the old name was deleted from the index and this takes the name the shim used to hold. The distribution and the command are invisible-playwright-mcp, the module is invisible_playwright_mcp: one is typed at a shell, the other is imported, and pyproject.toml is the name one house. Kept because they name state that already exists, where a rename is not a move but a silent loss: the session directory under %APPDATA%, Application Support and XDG_DATA_HOME, the three localStorage keys, the AIHAWK_ variables and the registry name. Four gates were reporting on a copy of the name rather than on the name, and the worst of them went green: the content gate could no longer find the command in the README fences, so four of its checks were skipped while it printed clean. Merged with all 14 checks green, the releases check among them: it had been red on main since the previous rename, and the fix for a project the index has never heard of closes it for the right reason. | 3 天前 | |
The package, the command and the module are invisible-playwright-mcp (#1385) PyPI has no rename, so the old name was deleted from the index and this takes the name the shim used to hold. The distribution and the command are invisible-playwright-mcp, the module is invisible_playwright_mcp: one is typed at a shell, the other is imported, and pyproject.toml is the name one house. Kept because they name state that already exists, where a rename is not a move but a silent loss: the session directory under %APPDATA%, Application Support and XDG_DATA_HOME, the three localStorage keys, the AIHAWK_ variables and the registry name. Four gates were reporting on a copy of the name rather than on the name, and the worst of them went green: the content gate could no longer find the command in the README fences, so four of its checks were skipped while it printed clean. Merged with all 14 checks green, the releases check among them: it had been red on main since the previous rename, and the fix for a project the index has never heard of closes it for the right reason. | 3 天前 | |
The package, the command and the module are invisible-playwright-mcp (#1385) PyPI has no rename, so the old name was deleted from the index and this takes the name the shim used to hold. The distribution and the command are invisible-playwright-mcp, the module is invisible_playwright_mcp: one is typed at a shell, the other is imported, and pyproject.toml is the name one house. Kept because they name state that already exists, where a rename is not a move but a silent loss: the session directory under %APPDATA%, Application Support and XDG_DATA_HOME, the three localStorage keys, the AIHAWK_ variables and the registry name. Four gates were reporting on a copy of the name rather than on the name, and the worst of them went green: the content gate could no longer find the command in the README fences, so four of its checks were skipped while it printed clean. Merged with all 14 checks green, the releases check among them: it had been red on main since the previous rename, and the fix for a project the index has never heard of closes it for the right reason. | 3 天前 | |
The old name is abandoned, and it hands over its data on the way out (#1386) The package rename kept six things, each for a measured reason, and every one of those reasons was about somebody data or somebody position. The answer is not choosing between the name and the data: it is carrying the data along. The variables are INVISIBLE_MCP_HOME, INVISIBLE_MCP_MODEL and INVISIBLE_MCP_SESSION_ID, with env.py the one place that knows them, because each is now two strings. The retired name still answers and says so once, through the logger, since stdout is the protocol channel. The session directory is invisible-playwright-mcp, and the old one is moved onto it at startup, once, printing where to. storage.home() stays a pure answer to where is the directory. The browser three keys are built from one prefix and carried across on the first read; one of them holds an unsent draft. The registry name and the eight wiki slugs were chosen by the owner after reading the cost: the registry gets a second entry with no redirect from the first, and six pages that held the first result for their query lose those positions with no 301. Left on purpose: the LICENSE copyright line, the Telegram community URL, and the retired names themselves, which are what the hand-over reads. Merged with all 14 checks green. | 3 天前 | |
The package, the command and the module are invisible-playwright-mcp (#1385) PyPI has no rename, so the old name was deleted from the index and this takes the name the shim used to hold. The distribution and the command are invisible-playwright-mcp, the module is invisible_playwright_mcp: one is typed at a shell, the other is imported, and pyproject.toml is the name one house. Kept because they name state that already exists, where a rename is not a move but a silent loss: the session directory under %APPDATA%, Application Support and XDG_DATA_HOME, the three localStorage keys, the AIHAWK_ variables and the registry name. Four gates were reporting on a copy of the name rather than on the name, and the worst of them went green: the content gate could no longer find the command in the README fences, so four of its checks were skipped while it printed clean. Merged with all 14 checks green, the releases check among them: it had been red on main since the previous rename, and the fix for a project the index has never heard of closes it for the right reason. | 3 天前 | |
The package, the command and the module are invisible-playwright-mcp (#1385) PyPI has no rename, so the old name was deleted from the index and this takes the name the shim used to hold. The distribution and the command are invisible-playwright-mcp, the module is invisible_playwright_mcp: one is typed at a shell, the other is imported, and pyproject.toml is the name one house. Kept because they name state that already exists, where a rename is not a move but a silent loss: the session directory under %APPDATA%, Application Support and XDG_DATA_HOME, the three localStorage keys, the AIHAWK_ variables and the registry name. Four gates were reporting on a copy of the name rather than on the name, and the worst of them went green: the content gate could no longer find the command in the README fences, so four of its checks were skipped while it printed clean. Merged with all 14 checks green, the releases check among them: it had been red on main since the previous rename, and the fix for a project the index has never heard of closes it for the right reason. | 3 天前 | |
The package, the command and the module are invisible-playwright-mcp (#1385) PyPI has no rename, so the old name was deleted from the index and this takes the name the shim used to hold. The distribution and the command are invisible-playwright-mcp, the module is invisible_playwright_mcp: one is typed at a shell, the other is imported, and pyproject.toml is the name one house. Kept because they name state that already exists, where a rename is not a move but a silent loss: the session directory under %APPDATA%, Application Support and XDG_DATA_HOME, the three localStorage keys, the AIHAWK_ variables and the registry name. Four gates were reporting on a copy of the name rather than on the name, and the worst of them went green: the content gate could no longer find the command in the README fences, so four of its checks were skipped while it printed clean. Merged with all 14 checks green, the releases check among them: it had been red on main since the previous rename, and the fix for a project the index has never heard of closes it for the right reason. | 3 天前 | |
The old name is abandoned, and it hands over its data on the way out (#1386) The package rename kept six things, each for a measured reason, and every one of those reasons was about somebody data or somebody position. The answer is not choosing between the name and the data: it is carrying the data along. The variables are INVISIBLE_MCP_HOME, INVISIBLE_MCP_MODEL and INVISIBLE_MCP_SESSION_ID, with env.py the one place that knows them, because each is now two strings. The retired name still answers and says so once, through the logger, since stdout is the protocol channel. The session directory is invisible-playwright-mcp, and the old one is moved onto it at startup, once, printing where to. storage.home() stays a pure answer to where is the directory. The browser three keys are built from one prefix and carried across on the first read; one of them holds an unsent draft. The registry name and the eight wiki slugs were chosen by the owner after reading the cost: the registry gets a second entry with no redirect from the first, and six pages that held the first result for their query lose those positions with no 301. Left on purpose: the LICENSE copyright line, the Telegram community URL, and the retired names themselves, which are what the hand-over reads. Merged with all 14 checks green. | 3 天前 | |
The old name is abandoned, and it hands over its data on the way out (#1386) The package rename kept six things, each for a measured reason, and every one of those reasons was about somebody data or somebody position. The answer is not choosing between the name and the data: it is carrying the data along. The variables are INVISIBLE_MCP_HOME, INVISIBLE_MCP_MODEL and INVISIBLE_MCP_SESSION_ID, with env.py the one place that knows them, because each is now two strings. The retired name still answers and says so once, through the logger, since stdout is the protocol channel. The session directory is invisible-playwright-mcp, and the old one is moved onto it at startup, once, printing where to. storage.home() stays a pure answer to where is the directory. The browser three keys are built from one prefix and carried across on the first read; one of them holds an unsent draft. The registry name and the eight wiki slugs were chosen by the owner after reading the cost: the registry gets a second entry with no redirect from the first, and six pages that held the first result for their query lose those positions with no 301. Left on purpose: the LICENSE copyright line, the Telegram community URL, and the retired names themselves, which are what the hand-over reads. Merged with all 14 checks green. | 3 天前 | |
The package, the command and the module are invisible-playwright-mcp (#1385) PyPI has no rename, so the old name was deleted from the index and this takes the name the shim used to hold. The distribution and the command are invisible-playwright-mcp, the module is invisible_playwright_mcp: one is typed at a shell, the other is imported, and pyproject.toml is the name one house. Kept because they name state that already exists, where a rename is not a move but a silent loss: the session directory under %APPDATA%, Application Support and XDG_DATA_HOME, the three localStorage keys, the AIHAWK_ variables and the registry name. Four gates were reporting on a copy of the name rather than on the name, and the worst of them went green: the content gate could no longer find the command in the README fences, so four of its checks were skipped while it printed clean. Merged with all 14 checks green, the releases check among them: it had been red on main since the previous rename, and the fix for a project the index has never heard of closes it for the right reason. | 3 天前 | |
The half the gate said it could not do, and one declaration of asyncio (#1352) 0.67.0 shipped a gate on dead product surface and declared methods out of scope, with a reason: a method reaches the code as an attribute, and plan.describe and SessionPlan.describe are the same attribute name, so counting names cannot tell the dead one from the live one beside it. That reason was true and it was not a limit, it was a missing step. It is done now. RESOLVE THE OWNER, AND THE AMBIGUITY GOES AWAY. An attribute on a name that the file imported as a MODULE is the module's function and never the method; self.X, Class.X and anything.X could all be the method and count. The second half is deliberately generous - an arbitrary expression counts as a reference to every method of that name - so it errs by letting something live, never by accusing it. 47 methods judged out of the 59 defined: the twelve left out are methods of a class WITH A BASE, which may be satisfying somebody else's contract, and decorated ones, which can be handed somewhere this cannot follow. The real-tree mutation it exists for - SessionPlan.describe put back - is named by file and line. AND THE FIRST VERSION OF IT LET THAT MUTATION SURVIVE. Strings were split into words, so the docstrings in plan.py - which say "describe() reads the KWARGS" - counted as reaching the method. The check was satisfied by the prose beside the code, which is the most repeated defect in this project, met inside the tool built to find it. Whole-string identifiers only now, which keeps the genuine getattr case and drops the sentences: the universe of attribute names went from 4,798 to 500, so nine tenths of what was keeping methods alive was prose. Floors AND a ceiling are asserted, because a collapse makes every method look dead, an explosion makes every one look alive, and a hand-written perimeter goes stale the day somebody changes what is excluded - which it already had, at 59. THE PAGE WAS SCANNED THE SAME WAY AND IS CLEAN, which is worth writing down as a measured negative rather than an assumption: src/aihawk/ui is product surface too and 0.67.0 never looked at it. 109 top-level JS bindings, every one named by another file or by the markup; 49 CSS classes, every one applied, confirmed by a second measurement taken a different way. The ten scripts become one concatenated script, so the question is the same one the Python gate asks. No gate here - the page has its own in test_the_browser_workspace.py - and the numbers are in the module docstring. ASYNCIO WAS DECLARED 46 TIMES FOR ONE FACT. pyproject.toml has asyncio_mode = "auto", which marks every async test already; 45 more copies sat in the files as @pytest.mark.asyncio or a module-level pytestmark. Copies of one fact can disagree with it and these did: nine sat on SYNCHRONOUS functions, so every run printed nine warnings saying the marker did not belong. Noise is where a real warning hides. They are gone and the suite prints none. What makes that safe is a gate rather than a hope. Under strict mode pytest-asyncio SKIPS an unmarked async test instead of failing it, so deleting the surviving declaration would leave the suite green while 45 tests quietly stopped running. test_the_suite_declares_asyncio_once.py holds the declaration, proves its own known-bad against a mutated copy of the file, and refuses a file that starts declaring it again - because one re-added marker is harmless on its own, which is exactly how the other 44 would follow. AND THAT LAST CHECK EARNED ITSELF IMMEDIATELY: it found two the removal script had missed, both in list form (pytestmark = [pytest.mark.asyncio, ...]) where the pattern did not match. A partial job that reports success is the thing a gate is for. A must-not-fire case failed on the first run for the second time in two days, and the gate was right both times: a toy module whose outermost function has no caller HAS a dead surface. The real package always has an outer caller; a fixture does not unless it is given one. Suite 664 green from 654, with no warnings. Tests only, nothing under src, so no version: the gate says in its own words that tests alter nothing anybody installs. | 11 天前 | |
The old name is abandoned, and it hands over its data on the way out (#1386) The package rename kept six things, each for a measured reason, and every one of those reasons was about somebody data or somebody position. The answer is not choosing between the name and the data: it is carrying the data along. The variables are INVISIBLE_MCP_HOME, INVISIBLE_MCP_MODEL and INVISIBLE_MCP_SESSION_ID, with env.py the one place that knows them, because each is now two strings. The retired name still answers and says so once, through the logger, since stdout is the protocol channel. The session directory is invisible-playwright-mcp, and the old one is moved onto it at startup, once, printing where to. storage.home() stays a pure answer to where is the directory. The browser three keys are built from one prefix and carried across on the first read; one of them holds an unsent draft. The registry name and the eight wiki slugs were chosen by the owner after reading the cost: the registry gets a second entry with no redirect from the first, and six pages that held the first result for their query lose those positions with no 301. Left on purpose: the LICENSE copyright line, the Telegram community URL, and the retired names themselves, which are what the hand-over reads. Merged with all 14 checks green. | 3 天前 | |
The package, the command and the module are invisible-playwright-mcp (#1385) PyPI has no rename, so the old name was deleted from the index and this takes the name the shim used to hold. The distribution and the command are invisible-playwright-mcp, the module is invisible_playwright_mcp: one is typed at a shell, the other is imported, and pyproject.toml is the name one house. Kept because they name state that already exists, where a rename is not a move but a silent loss: the session directory under %APPDATA%, Application Support and XDG_DATA_HOME, the three localStorage keys, the AIHAWK_ variables and the registry name. Four gates were reporting on a copy of the name rather than on the name, and the worst of them went green: the content gate could no longer find the command in the README fences, so four of its checks were skipped while it printed clean. Merged with all 14 checks green, the releases check among them: it had been red on main since the previous rename, and the fix for a project the index has never heard of closes it for the right reason. | 3 天前 | |
The old name is abandoned, and it hands over its data on the way out (#1386) The package rename kept six things, each for a measured reason, and every one of those reasons was about somebody data or somebody position. The answer is not choosing between the name and the data: it is carrying the data along. The variables are INVISIBLE_MCP_HOME, INVISIBLE_MCP_MODEL and INVISIBLE_MCP_SESSION_ID, with env.py the one place that knows them, because each is now two strings. The retired name still answers and says so once, through the logger, since stdout is the protocol channel. The session directory is invisible-playwright-mcp, and the old one is moved onto it at startup, once, printing where to. storage.home() stays a pure answer to where is the directory. The browser three keys are built from one prefix and carried across on the first read; one of them holds an unsent draft. The registry name and the eight wiki slugs were chosen by the owner after reading the cost: the registry gets a second entry with no redirect from the first, and six pages that held the first result for their query lose those positions with no 301. Left on purpose: the LICENSE copyright line, the Telegram community URL, and the retired names themselves, which are what the hand-over reads. Merged with all 14 checks green. | 3 天前 | |
The package, the command and the module are invisible-playwright-mcp (#1385) PyPI has no rename, so the old name was deleted from the index and this takes the name the shim used to hold. The distribution and the command are invisible-playwright-mcp, the module is invisible_playwright_mcp: one is typed at a shell, the other is imported, and pyproject.toml is the name one house. Kept because they name state that already exists, where a rename is not a move but a silent loss: the session directory under %APPDATA%, Application Support and XDG_DATA_HOME, the three localStorage keys, the AIHAWK_ variables and the registry name. Four gates were reporting on a copy of the name rather than on the name, and the worst of them went green: the content gate could no longer find the command in the README fences, so four of its checks were skipped while it printed clean. Merged with all 14 checks green, the releases check among them: it had been red on main since the previous rename, and the fix for a project the index has never heard of closes it for the right reason. | 3 天前 | |
The old name is abandoned, and it hands over its data on the way out (#1386) The package rename kept six things, each for a measured reason, and every one of those reasons was about somebody data or somebody position. The answer is not choosing between the name and the data: it is carrying the data along. The variables are INVISIBLE_MCP_HOME, INVISIBLE_MCP_MODEL and INVISIBLE_MCP_SESSION_ID, with env.py the one place that knows them, because each is now two strings. The retired name still answers and says so once, through the logger, since stdout is the protocol channel. The session directory is invisible-playwright-mcp, and the old one is moved onto it at startup, once, printing where to. storage.home() stays a pure answer to where is the directory. The browser three keys are built from one prefix and carried across on the first read; one of them holds an unsent draft. The registry name and the eight wiki slugs were chosen by the owner after reading the cost: the registry gets a second entry with no redirect from the first, and six pages that held the first result for their query lose those positions with no 301. Left on purpose: the LICENSE copyright line, the Telegram community URL, and the retired names themselves, which are what the hand-over reads. Merged with all 14 checks green. | 3 天前 | |
The package, the command and the module are invisible-playwright-mcp (#1385) PyPI has no rename, so the old name was deleted from the index and this takes the name the shim used to hold. The distribution and the command are invisible-playwright-mcp, the module is invisible_playwright_mcp: one is typed at a shell, the other is imported, and pyproject.toml is the name one house. Kept because they name state that already exists, where a rename is not a move but a silent loss: the session directory under %APPDATA%, Application Support and XDG_DATA_HOME, the three localStorage keys, the AIHAWK_ variables and the registry name. Four gates were reporting on a copy of the name rather than on the name, and the worst of them went green: the content gate could no longer find the command in the README fences, so four of its checks were skipped while it printed clean. Merged with all 14 checks green, the releases check among them: it had been red on main since the previous rename, and the fix for a project the index has never heard of closes it for the right reason. | 3 天前 | |
0.70.0: the first release under the new name, and the deletion declared (#1390) Both old names were deleted from the index on 2026-09-23 to free the new one: aihawk and the shim that held invisible-playwright-mcp. Four endpoints answer 404 for both (JSON, simple, RSS, the file host) while invisible-playwright answers 200 at the same moment, and PyPI accepted a pending publisher for the new name, which it does only for a name that does not exist. So today `uvx invisible-playwright-mcp` resolves to nothing, and this version is what the README's instructions need to reach. It also takes back a correction that was itself wrong. #1389 called the 404 a transient, on the premise that PyPI does not let a deleted name be registered again. It does, which is what made the rename possible; the deletion was real and propagated unevenly. Three docstrings now say so. The releases check learns the case it was missing. A deleted project answers 404 and so does an index having a bad minute, and nothing the index says can tell them apart, so each distribution carries the day it was deleted, declared like the boundary. Deleted ranges are not asked, and their tags are not evidence that something should be served. The declaration is checked in the one direction the index can answer: a project declared deleted that serves versions fails. The single-version guard is now a skip: the first release under the new name is the only version on the index, and failing on that would be red on every pull request until a second release, for nothing wrong. Proven by three mutations, each red and naming its cause: aihawk declared live, the boundary moved to 0.68.0, and a served project declared deleted. | 2 天前 | |
The package, the command and the module are invisible-playwright-mcp (#1385) PyPI has no rename, so the old name was deleted from the index and this takes the name the shim used to hold. The distribution and the command are invisible-playwright-mcp, the module is invisible_playwright_mcp: one is typed at a shell, the other is imported, and pyproject.toml is the name one house. Kept because they name state that already exists, where a rename is not a move but a silent loss: the session directory under %APPDATA%, Application Support and XDG_DATA_HOME, the three localStorage keys, the AIHAWK_ variables and the registry name. Four gates were reporting on a copy of the name rather than on the name, and the worst of them went green: the content gate could no longer find the command in the README fences, so four of its checks were skipped while it printed clean. Merged with all 14 checks green, the releases check among them: it had been red on main since the previous rename, and the fix for a project the index has never heard of closes it for the right reason. | 3 天前 | |
The package, the command and the module are invisible-playwright-mcp (#1385) PyPI has no rename, so the old name was deleted from the index and this takes the name the shim used to hold. The distribution and the command are invisible-playwright-mcp, the module is invisible_playwright_mcp: one is typed at a shell, the other is imported, and pyproject.toml is the name one house. Kept because they name state that already exists, where a rename is not a move but a silent loss: the session directory under %APPDATA%, Application Support and XDG_DATA_HOME, the three localStorage keys, the AIHAWK_ variables and the registry name. Four gates were reporting on a copy of the name rather than on the name, and the worst of them went green: the content gate could no longer find the command in the README fences, so four of its checks were skipped while it printed clean. Merged with all 14 checks green, the releases check among them: it had been red on main since the previous rename, and the fix for a project the index has never heard of closes it for the right reason. | 3 天前 |
| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 2 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 10 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 13 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 2 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 10 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 11 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 3 天前 | ||
| 2 天前 | ||
| 3 天前 | ||
| 3 天前 |