nodeengine 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,31 @@
1
+ {
2
+ "$schema": "https://anthropic.com/claude-code/marketplace.schema.json",
3
+ "name": "node-engine",
4
+ "description": "Hash-and-compare guards so derived things report stale instead of silently lying",
5
+ "owner": {
6
+ "name": "Alexyodude",
7
+ "email": "jihoonhotmail.com@gmail.com"
8
+ },
9
+ "plugins": [
10
+ {
11
+ "name": "node-engine",
12
+ "description": "Make staleness fail a check instead of relying on someone remembering. Sets up hash-and-compare guards for summaries, translations, generated files and any fact restated in prose. Carries the discipline too: fix the class not the instance, and a new check is guilty until it has failed on demand.",
13
+ "version": "0.1.0",
14
+ "author": {
15
+ "name": "Alexyodude",
16
+ "email": "jihoonhotmail.com@gmail.com"
17
+ },
18
+ "source": "./",
19
+ "category": "quality",
20
+ "homepage": "https://github.com/Alexyodude/NodeEngine",
21
+ "tags": [
22
+ "drift",
23
+ "consistency",
24
+ "documentation",
25
+ "checks",
26
+ "content-addressing"
27
+ ]
28
+ }
29
+ ],
30
+ "version": "0.1.0"
31
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "node-engine",
3
+ "version": "0.1.0",
4
+ "description": "Make staleness fail a check instead of relying on someone remembering. Hash-and-compare guards for derived facts, generated artefacts and translations.",
5
+ "author": {
6
+ "name": "Alexyodude",
7
+ "email": "jihoonhotmail.com@gmail.com"
8
+ },
9
+ "repository": "https://github.com/Alexyodude/NodeEngine",
10
+ "homepage": "https://github.com/Alexyodude/NodeEngine",
11
+ "license": "MIT",
12
+ "keywords": [
13
+ "claude-code",
14
+ "plugin",
15
+ "documentation",
16
+ "drift",
17
+ "consistency",
18
+ "checks",
19
+ "provenance"
20
+ ],
21
+ "skills": "./skills/"
22
+ }
@@ -0,0 +1,6 @@
1
+ .omc/
2
+ __pycache__/
3
+ *.pyc
4
+ .build/
5
+ dist/
6
+ .playwright-mcp/
@@ -0,0 +1,151 @@
1
+ # NodeEngine
2
+
3
+ A Claude Code **plugin** that makes staleness fail a check instead of relying on
4
+ someone remembering. It ships one skill and a copyable scaffold.
5
+
6
+ **This repo is mostly prose, and the prose is the product.** The scaffold is
7
+ ~150 lines of Python plus a self-contained HTML viewer; the value is in
8
+ `SKILL.md` and `reference/`. Edits that make the guidance vaguer make the
9
+ plugin worse, even when they make it shorter.
10
+
11
+ ## Commands
12
+
13
+ | Command | Description |
14
+ |---|---|
15
+ | `python skills/node-engine/scaffold/stale.py` | No CLI — it is a module. Import it to smoke-test. |
16
+ | `python -c "import sys; sys.path.insert(0,'skills/node-engine/scaffold'); import stale"` | Confirm the scaffold imports |
17
+ | `python skills/node-engine/scaffold/checkall.py --prove` | Print how to break each check in the runner |
18
+ | `python tools/check_claude_md.py` | Is this file still true? Paths exist, versions agree, sections vs the template |
19
+ | `python install.py --dry-run` | Show what installing into the current repo would write |
20
+ | `python install.py --into <dir>` | Copy the scaffold elsewhere; finds the git root, refuses to overwrite |
21
+ | `uvx --from <this repo> nodeengine --dry-run` | The same installer via its packaged entry point — exercises `pyproject.toml` |
22
+
23
+ There is no build and no test suite. The scaffold is copied into other projects,
24
+ not executed here — `install.py` is the copier, and `commands/install.md` is the
25
+ `/node-engine:install` command that runs it and then walks the wiring-up.
26
+
27
+ ## Architecture
28
+
29
+ ```
30
+ NodeEngine/
31
+ install.py copies the scaffold into another repo
32
+ pyproject.toml packages install.py ONLY, so `uvx nodeengine` works
33
+ commands/
34
+ install.md /node-engine:install — copy, then wire it up
35
+ tools/
36
+ check_claude_md.py is CLAUDE.md still true? (see docs/SYNCING.md)
37
+ docs/
38
+ SYNCING.md why the template is checked, not synced
39
+ .claude-plugin/
40
+ plugin.json the manifest; `skills` points at ./skills/
41
+ marketplace.json makes the repo installable as its own marketplace
42
+ skills/node-engine/
43
+ SKILL.md the method, the rule, when NOT to use it
44
+ reference/
45
+ patterns.md the three shapes, with implementations
46
+ traps.md ten checks that could not fail — all real
47
+ taxonomy.md thirteen defect classes
48
+ scaffold/
49
+ stale.py store + comparators, meant to be read and edited
50
+ checkall.py the runner
51
+ viewer.html browser search over the stores; keyOf must match key_of
52
+ ```
53
+
54
+ **The version appears in four places** — `plugin.json`, twice in
55
+ `marketplace.json` (the plugin entry and the top-level field), and
56
+ `pyproject.toml`. They must agree. This is precisely the class of defect the
57
+ plugin exists to catch; `tools/check_claude_md.py` fails if they disagree,
58
+ including the TOML one — its JSON glob never sees `pyproject.toml`, so that
59
+ copy needed its own read, proven by breaking it (`0.9.9` → exit 1).
60
+
61
+ ## Key files
62
+
63
+ - `skills/node-engine/SKILL.md` — what an agent loads. Frontmatter `description`
64
+ is what makes it fire, so it must name the symptoms someone would actually
65
+ type ("stop this drifting", "why did that go stale"), not just the concept.
66
+ - `skills/node-engine/reference/traps.md` — the highest-value file. Ten worked
67
+ examples of checks that shipped unable to fail.
68
+ - `skills/node-engine/scaffold/stale.py` — deliberately not a library.
69
+
70
+ ## Editing conventions
71
+
72
+ **Keep the examples concrete and real.** Every example in `reference/` is from a
73
+ project that actually shipped the defect. `"A check compared PDFs to themselves
74
+ and reported 9 rendered and current"` transfers; `"ensure comparison operands
75
+ differ"` does not. Do not generalise an example to make it tidier.
76
+
77
+ **The scaffold is copied, not imported.** Its docstrings say so. Do not add
78
+ dependencies or packaging *to the scaffold* — a dependency you cannot read is
79
+ one you will trust when it is wrong, which is the failure the plugin exists to
80
+ prevent. The root `pyproject.toml` is not an exception: it packages the
81
+ *installer* as the `nodeengine` entry point, and what that entry point does is
82
+ still copy readable files into `tools/`. If a change would make the scaffold
83
+ itself installable or importable, it is wrong.
84
+
85
+ **Do not strip the dense docstrings.** They record the measured defect each
86
+ guard was built to catch. That is institutional knowledge, not slop.
87
+
88
+ ## Gotchas
89
+
90
+ - **`.omc/` reappears constantly.** OMC writes state into whatever directory a
91
+ command runs from, including this one and `skills/node-engine/scaffold/`. It is
92
+ gitignored; check `git status` before committing anyway.
93
+ - **`__pycache__/` appears in `scaffold/`** the moment anything imports `stale.py`
94
+ from there. Also gitignored.
95
+ - **Git reports LF→CRLF warnings on every commit** on Windows. Harmless.
96
+ - **Installing from a local path is not the same as from GitHub.** Test with
97
+ `/plugin marketplace add <path>` before pushing, then again from the remote —
98
+ the manifest is only exercised properly on a real install.
99
+
100
+ ## Publishing
101
+
102
+ ```
103
+ git push -u origin main
104
+ /plugin marketplace add Alexyodude/NodeEngine
105
+ /plugin install node-engine@node-engine
106
+ ```
107
+
108
+ Bump the version in **all four places** together — `plugin.json`, twice in
109
+ `marketplace.json`, `pyproject.toml` — or the install will resolve to something
110
+ that does not exist. `check_claude_md.py` catches a missed one.
111
+
112
+ ## Known gaps
113
+
114
+ - ~~The one-line installer 404s until the repo is public.~~ **Closed 2026-08-31**
115
+ — the repo is public and the happy path is verified: both
116
+ `curl -fsSL .../install.py | python` and `uv run <github raw URL>` installed
117
+ `stale.py` + `checkall.py` into a fresh repo's `tools/`, exit 0. Before the
118
+ push, a 404 body was piped straight into the interpreter (`<!DOCTYPE html>`
119
+ SyntaxError) — `curl` needs `-f`, and `uv run` does not check HTTP status.
120
+
121
+
122
+ Stated plainly because this plugin is about not letting claims drift:
123
+
124
+ - ~~The version is restated in three places and nothing checks it.~~ **Closed**
125
+ — `tools/check_claude_md.py` fails if the manifests disagree. Proven by
126
+ setting `plugin.json` to `0.2.0` and watching it fire.
127
+ - **`nodeengine` is not on PyPI**, so the bare `uvx nodeengine` / `pipx run
128
+ nodeengine` does not resolve. What works without a publish is
129
+ `uvx --from git+https://github.com/Alexyodude/NodeEngine nodeengine`. The
130
+ name was free on PyPI as of 2026-08-31 — publishing would claim it and make
131
+ the two-word form real.
132
+ - **The scaffold has no tests.** Its correctness is asserted by the reference
133
+ docs, not demonstrated. `checkall.py --prove` prints how to break the checks
134
+ it describes, but nothing runs them here.
135
+ - The skill has never been invoked cold in an unfamiliar repo. Until it has, the
136
+ claim that it "sets up guards in any repo" is untested.
137
+
138
+ ## Upstream template
139
+
140
+ `CLAUDE.md` here follows the template in the `claude-md-management` plugin
141
+ (`skills/claude-md-improver/references/templates.md`). To re-check this file
142
+ against the current upstream guidance:
143
+
144
+ ```
145
+ /plugin marketplace update claude-plugins-official
146
+ /revise-claude-md
147
+ ```
148
+
149
+ The template is *guidance*, not a file to copy — there is no automatic sync, and
150
+ `/revise-claude-md` reads the session for learnings rather than diffing against
151
+ the template. See `docs/SYNCING.md` for what can and cannot be automated.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Alexyodude
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,173 @@
1
+ Metadata-Version: 2.5
2
+ Name: nodeengine
3
+ Version: 0.1.0
4
+ Summary: Install the NodeEngine staleness-guard scaffold into the current repo
5
+ Project-URL: Homepage, https://github.com/Alexyodude/NodeEngine
6
+ License: MIT
7
+ License-File: LICENSE
8
+ Requires-Python: >=3.9
9
+ Description-Content-Type: text/markdown
10
+
11
+ # NodeEngine
12
+
13
+ A Claude Code plugin. Makes staleness **fail a check** instead of relying on
14
+ someone remembering.
15
+
16
+ *The name is literal: what it builds is a graph of **nodes** — clauses, blocks,
17
+ generated files — each holding the hash of the source it was derived from. The
18
+ engine walks that graph and reports every edge whose source has moved.*
19
+
20
+ A fact stated twice is a fact that will disagree with itself — not might, will,
21
+ usually within hours, because the two copies are edited by different people at
22
+ different times for different reasons.
23
+
24
+ The usual response is to be careful. That fails, because carefulness does not
25
+ survive a deadline. What works is to make the second copy *derived*, and then
26
+ make derivation *checkable*.
27
+
28
+ ## The idea, in one line
29
+
30
+ > **Store the hash of the source beside the derived thing. Compare on every run.**
31
+
32
+ ```json
33
+ "6.2B": { "hash": "3e40ff04…", "summary": "The reservations preserve rights as partners only…" }
34
+ ^^^^^^^^^^^^^^^^^ the source text when a human last confirmed
35
+ this summary was true of it
36
+ ```
37
+
38
+ Change the source and its hash changes; the summary no longer matches its
39
+ anchor; the check says `summary-stale: 6.2B`. Nobody had to remember. The
40
+ staleness is not caught by cleverness — it is **structurally unable to hide**.
41
+
42
+ ## Install
43
+
44
+ One line, in any repo:
45
+
46
+ ```
47
+ curl -sL https://raw.githubusercontent.com/Alexyodude/NodeEngine/main/install.py | python -
48
+ ```
49
+
50
+ That copies `stale.py`, `checkall.py` and `viewer.html` into `./tools/` and
51
+ prints what to do next. No clone, no plugin, no dependencies. Add
52
+ `--into scripts` or `--dry-run` after `python -` if you want them.
53
+
54
+ If you have [uv](https://docs.astral.sh/uv/), the same installer runs as a
55
+ packaged tool — same files land, same refusal to overwrite:
56
+
57
+ ```
58
+ uvx --from git+https://github.com/Alexyodude/NodeEngine nodeengine
59
+ ```
60
+
61
+ *It runs code fetched over the network, which is worth being deliberate about.
62
+ To read it first:*
63
+
64
+ ```
65
+ curl -sL https://raw.githubusercontent.com/Alexyodude/NodeEngine/main/install.py -o install.py
66
+ less install.py && python install.py
67
+ ```
68
+
69
+ **As a Claude Code plugin**, if you also want the skill and the guided setup:
70
+
71
+ ```
72
+ /plugin marketplace add Alexyodude/NodeEngine
73
+ /plugin install node-engine@node-engine
74
+ /node-engine:install
75
+ ```
76
+
77
+ The plugin adds the method itself — an agent that knows the three shapes, the
78
+ defect taxonomy, and the rule that a new check is guilty until it has failed on
79
+ demand. The one-liner just gives you the files.
80
+
81
+ ## What it covers
82
+
83
+ Three shapes, because different relationships need different guarantees:
84
+
85
+ | Shape | For | Guarantee |
86
+ |---|---|---|
87
+ | **Anchored** | a human judgement about a source — summaries, descriptions, a sentence citing a spec | re-anchoring is an explicit act; you cannot clear a stale flag by accident |
88
+ | **Content-addressed** | anything that must track an original exactly — translations, mirrors | the hash *is* the key, so a changed source has no entry rather than the wrong one |
89
+ | **Ordered** | files a human generates by running a command | catches the case the others cannot: nobody ran it |
90
+
91
+ Plus the cheapest win in most repos: **a number restated in prose should be
92
+ computed at check time and compared** — version, file count, step count, size.
93
+ No hash needed; the artefact is the source of truth.
94
+
95
+ ## Two files carry the human side
96
+
97
+ **`tools/DUPLICATION.md`** is the survey: what this repo states twice, where
98
+ both copies live, which shape guards each, and what is knowingly left
99
+ unguarded. The wiring-up writes it first, because a survey that lives only in
100
+ a conversation is gone when the session is.
101
+
102
+ **`tools/viewer.html`** is the search UI. Open it in a browser — no server, no
103
+ dependencies — drop in the store JSONs your checks keep, and search every id,
104
+ hash and summary. Paste a piece of source text and it computes the same key
105
+ `stale.py` computes, then tells you whether anything still anchors that exact
106
+ text. Read-only on purpose: re-anchoring stays a deliberate act in code,
107
+ because the one action that must remain expensive is clearing a stale flag
108
+ without looking.
109
+
110
+ ## It carries the discipline, not just the machinery
111
+
112
+ When a defect is found:
113
+
114
+ 1. Fix the instance.
115
+ 2. **Name the class.**
116
+ 3. **Measure what else has that shape** — grep for the *claim*, not the sentence.
117
+ 4. Fix the class.
118
+ 5. **Add a check, and make it fail on purpose before believing it.**
119
+
120
+ Step 5 is where this is won or lost. **A new check that passes has told you
121
+ nothing.** It might be correct; it might be structurally incapable of failing,
122
+ and you cannot tell those apart by reading it.
123
+
124
+ ## Why that last point is not paranoia
125
+
126
+ `reference/traps.md` documents ten checks that shipped, each reporting a clean
127
+ pass, each unable to fail. In **eight of ten the failure mode was a clean
128
+ result** — not a crash, not a wrong answer, a pass. Examples:
129
+
130
+ - `glob_newer_than("*.pdf", ".pdf", ".pdf")` — compared every file to itself and
131
+ reported *"9 rendered and current"*
132
+ - a regex using `[^.]` to span `2.4 … 11.1`, where every id contains a period —
133
+ returned zero across the whole corpus, three times, by someone who had already
134
+ documented the bug twice
135
+ - `if not X: return {}` upstream of `if X:` downstream — an unparseable input
136
+ silently switched off every check that depended on it, while the run printed `ok`
137
+ - `if not path.exists(): continue` in a checker — a moved file quietly left the
138
+ watch list and the run still said `clean`
139
+
140
+ Remembering these does not prevent them. Breaking the check does.
141
+
142
+ ## Contents
143
+
144
+ ```
145
+ skills/node-engine/
146
+ SKILL.md the method, the rule, and when not to use it
147
+ reference/
148
+ patterns.md the three shapes, with implementations
149
+ traps.md ten checks that could not fail — all real
150
+ taxonomy.md thirteen defect classes, ranked by how many each produced
151
+ scaffold/
152
+ stale.py the store and comparators (~150 lines, meant to be read)
153
+ checkall.py the runner; `--prove` prints how to break each check
154
+ viewer.html search the stores in a browser; paste text, see what anchors it
155
+ ```
156
+
157
+ The scaffold is deliberately **not** a library. Copy it in, delete what you do
158
+ not need, change what does not fit. A dependency you cannot read is one you will
159
+ trust when it is wrong — which is the exact failure this plugin exists to prevent.
160
+
161
+ ## Origin
162
+
163
+ Extracted from a bilingual legal package: nine documents making claims about a
164
+ tenth, in two languages, with a generated digest in the middle. Thirteen defect
165
+ classes and about forty real defects informed it.
166
+
167
+ The examples throughout stay concrete on purpose. *"A check compared PDFs to
168
+ themselves and reported 9 rendered and current"* transfers. *"Ensure comparison
169
+ operands differ"* does not.
170
+
171
+ ## Licence
172
+
173
+ MIT
@@ -0,0 +1,163 @@
1
+ # NodeEngine
2
+
3
+ A Claude Code plugin. Makes staleness **fail a check** instead of relying on
4
+ someone remembering.
5
+
6
+ *The name is literal: what it builds is a graph of **nodes** — clauses, blocks,
7
+ generated files — each holding the hash of the source it was derived from. The
8
+ engine walks that graph and reports every edge whose source has moved.*
9
+
10
+ A fact stated twice is a fact that will disagree with itself — not might, will,
11
+ usually within hours, because the two copies are edited by different people at
12
+ different times for different reasons.
13
+
14
+ The usual response is to be careful. That fails, because carefulness does not
15
+ survive a deadline. What works is to make the second copy *derived*, and then
16
+ make derivation *checkable*.
17
+
18
+ ## The idea, in one line
19
+
20
+ > **Store the hash of the source beside the derived thing. Compare on every run.**
21
+
22
+ ```json
23
+ "6.2B": { "hash": "3e40ff04…", "summary": "The reservations preserve rights as partners only…" }
24
+ ^^^^^^^^^^^^^^^^^ the source text when a human last confirmed
25
+ this summary was true of it
26
+ ```
27
+
28
+ Change the source and its hash changes; the summary no longer matches its
29
+ anchor; the check says `summary-stale: 6.2B`. Nobody had to remember. The
30
+ staleness is not caught by cleverness — it is **structurally unable to hide**.
31
+
32
+ ## Install
33
+
34
+ One line, in any repo:
35
+
36
+ ```
37
+ curl -sL https://raw.githubusercontent.com/Alexyodude/NodeEngine/main/install.py | python -
38
+ ```
39
+
40
+ That copies `stale.py`, `checkall.py` and `viewer.html` into `./tools/` and
41
+ prints what to do next. No clone, no plugin, no dependencies. Add
42
+ `--into scripts` or `--dry-run` after `python -` if you want them.
43
+
44
+ If you have [uv](https://docs.astral.sh/uv/), the same installer runs as a
45
+ packaged tool — same files land, same refusal to overwrite:
46
+
47
+ ```
48
+ uvx --from git+https://github.com/Alexyodude/NodeEngine nodeengine
49
+ ```
50
+
51
+ *It runs code fetched over the network, which is worth being deliberate about.
52
+ To read it first:*
53
+
54
+ ```
55
+ curl -sL https://raw.githubusercontent.com/Alexyodude/NodeEngine/main/install.py -o install.py
56
+ less install.py && python install.py
57
+ ```
58
+
59
+ **As a Claude Code plugin**, if you also want the skill and the guided setup:
60
+
61
+ ```
62
+ /plugin marketplace add Alexyodude/NodeEngine
63
+ /plugin install node-engine@node-engine
64
+ /node-engine:install
65
+ ```
66
+
67
+ The plugin adds the method itself — an agent that knows the three shapes, the
68
+ defect taxonomy, and the rule that a new check is guilty until it has failed on
69
+ demand. The one-liner just gives you the files.
70
+
71
+ ## What it covers
72
+
73
+ Three shapes, because different relationships need different guarantees:
74
+
75
+ | Shape | For | Guarantee |
76
+ |---|---|---|
77
+ | **Anchored** | a human judgement about a source — summaries, descriptions, a sentence citing a spec | re-anchoring is an explicit act; you cannot clear a stale flag by accident |
78
+ | **Content-addressed** | anything that must track an original exactly — translations, mirrors | the hash *is* the key, so a changed source has no entry rather than the wrong one |
79
+ | **Ordered** | files a human generates by running a command | catches the case the others cannot: nobody ran it |
80
+
81
+ Plus the cheapest win in most repos: **a number restated in prose should be
82
+ computed at check time and compared** — version, file count, step count, size.
83
+ No hash needed; the artefact is the source of truth.
84
+
85
+ ## Two files carry the human side
86
+
87
+ **`tools/DUPLICATION.md`** is the survey: what this repo states twice, where
88
+ both copies live, which shape guards each, and what is knowingly left
89
+ unguarded. The wiring-up writes it first, because a survey that lives only in
90
+ a conversation is gone when the session is.
91
+
92
+ **`tools/viewer.html`** is the search UI. Open it in a browser — no server, no
93
+ dependencies — drop in the store JSONs your checks keep, and search every id,
94
+ hash and summary. Paste a piece of source text and it computes the same key
95
+ `stale.py` computes, then tells you whether anything still anchors that exact
96
+ text. Read-only on purpose: re-anchoring stays a deliberate act in code,
97
+ because the one action that must remain expensive is clearing a stale flag
98
+ without looking.
99
+
100
+ ## It carries the discipline, not just the machinery
101
+
102
+ When a defect is found:
103
+
104
+ 1. Fix the instance.
105
+ 2. **Name the class.**
106
+ 3. **Measure what else has that shape** — grep for the *claim*, not the sentence.
107
+ 4. Fix the class.
108
+ 5. **Add a check, and make it fail on purpose before believing it.**
109
+
110
+ Step 5 is where this is won or lost. **A new check that passes has told you
111
+ nothing.** It might be correct; it might be structurally incapable of failing,
112
+ and you cannot tell those apart by reading it.
113
+
114
+ ## Why that last point is not paranoia
115
+
116
+ `reference/traps.md` documents ten checks that shipped, each reporting a clean
117
+ pass, each unable to fail. In **eight of ten the failure mode was a clean
118
+ result** — not a crash, not a wrong answer, a pass. Examples:
119
+
120
+ - `glob_newer_than("*.pdf", ".pdf", ".pdf")` — compared every file to itself and
121
+ reported *"9 rendered and current"*
122
+ - a regex using `[^.]` to span `2.4 … 11.1`, where every id contains a period —
123
+ returned zero across the whole corpus, three times, by someone who had already
124
+ documented the bug twice
125
+ - `if not X: return {}` upstream of `if X:` downstream — an unparseable input
126
+ silently switched off every check that depended on it, while the run printed `ok`
127
+ - `if not path.exists(): continue` in a checker — a moved file quietly left the
128
+ watch list and the run still said `clean`
129
+
130
+ Remembering these does not prevent them. Breaking the check does.
131
+
132
+ ## Contents
133
+
134
+ ```
135
+ skills/node-engine/
136
+ SKILL.md the method, the rule, and when not to use it
137
+ reference/
138
+ patterns.md the three shapes, with implementations
139
+ traps.md ten checks that could not fail — all real
140
+ taxonomy.md thirteen defect classes, ranked by how many each produced
141
+ scaffold/
142
+ stale.py the store and comparators (~150 lines, meant to be read)
143
+ checkall.py the runner; `--prove` prints how to break each check
144
+ viewer.html search the stores in a browser; paste text, see what anchors it
145
+ ```
146
+
147
+ The scaffold is deliberately **not** a library. Copy it in, delete what you do
148
+ not need, change what does not fit. A dependency you cannot read is one you will
149
+ trust when it is wrong — which is the exact failure this plugin exists to prevent.
150
+
151
+ ## Origin
152
+
153
+ Extracted from a bilingual legal package: nine documents making claims about a
154
+ tenth, in two languages, with a generated digest in the middle. Thirteen defect
155
+ classes and about forty real defects informed it.
156
+
157
+ The examples throughout stay concrete on purpose. *"A check compared PDFs to
158
+ themselves and reported 9 rendered and current"* transfers. *"Ensure comparison
159
+ operands differ"* does not.
160
+
161
+ ## Licence
162
+
163
+ MIT
@@ -0,0 +1,92 @@
1
+ ---
2
+ description: Install NodeEngine's staleness guards into the current repository
3
+ allowed-tools: Bash, Read, Write, Edit, Glob, Grep
4
+ ---
5
+
6
+ Install the NodeEngine scaffold here, then wire it to what this repository
7
+ actually duplicates. Copying files is the trivial part; step 2 is the work.
8
+
9
+ ## Step 1 — Copy the scaffold
10
+
11
+ ```bash
12
+ python "${CLAUDE_PLUGIN_ROOT}/install.py"
13
+ ```
14
+
15
+ Add `--into <dir>` if this project does not use `tools/`. It refuses to
16
+ overwrite existing files, so it is safe to re-run.
17
+
18
+ ## Step 2 — Find what is stated twice
19
+
20
+ This is the whole job, and it cannot be done from a template. Survey the repo
21
+ and build a real list. Look for:
22
+
23
+ - **Numbers in prose** — versions, counts, sizes, "three steps", "nine files".
24
+ These are the most common and the cheapest to guard: compute them at check
25
+ time and compare.
26
+ - **The same version in several manifests** — `package.json`, a lockfile, a
27
+ `__version__`, a badge in the README.
28
+ - **Docs describing structure** — a README or CLAUDE.md with a directory tree,
29
+ a list of commands, a table of modules. Paths rot silently.
30
+ - **Generated files** a human regenerates by running something.
31
+ - **Anything translated or mirrored** — i18n, a second-language README.
32
+ - **Summaries of code** — docstrings or docs that describe behaviour someone
33
+ can change without touching the description.
34
+
35
+ Write the list to `tools/DUPLICATION.md` — each item, where both copies live,
36
+ and (once decided) which shape guards it or why it is left unguarded. This file
37
+ is the survey's permanent home; a list that lives only in the conversation is
38
+ gone when the session is. Then report it to the user. Ask which matter; do not
39
+ guard everything, and say plainly which ones you think are not worth it.
40
+
41
+ ## Step 3 — Pick a shape for each
42
+
43
+ Read `${CLAUDE_PLUGIN_ROOT}/skills/node-engine/reference/patterns.md`.
44
+
45
+ | The derived thing is… | Shape |
46
+ |---|---|
47
+ | a human judgement about a source | **anchored** — hash stored beside it, `--confirm` to re-anchor |
48
+ | a mechanical transform that must match exactly | **content-addressed** — the hash is the key |
49
+ | produced by a command someone runs | **ordered**, or have the generator self-check |
50
+ | a count, size or inventory | **derive it live** — no hash needed, the artefact is the truth |
51
+
52
+ That last row usually covers most of what you found.
53
+
54
+ ## Step 4 — Write the table, not the checks
55
+
56
+ Edit `tools/checkall.py` so its `CHECKS` table names the real checks. Each row
57
+ carries a fourth column: **how to make this one fail**. That column is not
58
+ documentation — it is the verification instruction, and if you cannot fill it
59
+ in, you do not yet know whether the check can fail.
60
+
61
+ Adding a watched thing must mean adding a row. If it means writing a function,
62
+ the design has drifted: that is how you get one guard per instance and a gap
63
+ wherever nobody has been bitten yet.
64
+
65
+ ## Step 5 — Break every one
66
+
67
+ ```bash
68
+ python tools/checkall.py --prove # prints how to break each
69
+ python tools/checkall.py # should be green first
70
+ ```
71
+
72
+ Then actually do it, one at a time: make the change, confirm the check fails,
73
+ revert, confirm it passes. **Report the evidence** — the failing output, not
74
+ "verified".
75
+
76
+ Read `${CLAUDE_PLUGIN_ROOT}/skills/node-engine/reference/traps.md` before this
77
+ step. Ten checks documented there shipped unable to fail, and in eight of ten
78
+ the failure mode was a clean pass. The most common causes:
79
+
80
+ - comparing a thing to itself
81
+ - a pattern that cannot match the shape the text is in
82
+ - a sweep returning zero, which reads as "clean"
83
+ - an empty or missing input treated as "nothing to check" rather than as a finding
84
+ - `if not path.exists(): continue` inside a checker
85
+
86
+ ## Step 6 — Record it
87
+
88
+ Add a short section to `CLAUDE.md` (or the README) saying what is guarded, what
89
+ is not, and how to run the checks. State the gaps plainly — a checking system
90
+ that overstates its own coverage is the first thing to mislead someone.
91
+
92
+ Then commit, with the evidence from step 5 in the message.