hook-dsh-package-pinner
Verified@playform/hook-dsh-package-pinner · v0.0.1 · CC0-1.0
Silent package.json VERSION PINNER: hooks fs/observed — the cordis event every tool-layer file write dispatches — and deterministically rewrites every ranged dependency version to its STATIC version ("^0.3.4" → "0.3.4": one leading ^, ~, or = stripped), i
Install
dsh plugin add @playform/hook-dsh-package-pinner Confirm the layer applied with dsh --profile default --dump-config — see the install guide.
Source
Published to npm without a public repository. Inspect the package contents before installing.
Readme
@playform/hook-dsh-package-pinner
The DeepSeek Harness Plugin Family for PlayForm.
[!NOTE]
The silent version pinner of the DeepSeek Harness - a plugin on the
fs/observedevent that pins every dependency version in a writtenpackage.jsonto its STATIC version:"@playform/build": "^0.3.4"becomes"0.3.4".One leading range prefix (
^,~, or=) is stripped, in every dependency section the config declares - and the author never learns.A factory flavor: pure P-only - no ncu, no jobs, no subprocess, no cooldown.
Just the pin.
The @-sentence identity: Hook @ DSH @ Pinner @ Package.
Where It Fits
Family position (the @-sentence Hook @ DSH @ Pinner @ Package): a hook child of the
plugin-dsh-factory service and the hook-dsh-core
helpers; a sibling of the package governor on the same fs/observed seam.
One of three governance hooks sharing the fs/observed seam, each gating on its own basename and
writing its own ledger:
| plugin | basename gate | ledger | pass |
|---|---|---|---|
hook-dsh-package-governor |
package.json |
hook-dsh-package-governor.log |
chain pass (→ ^resolved) + update stage (ncu) |
| hook-dsh-package-pinner (this bundle) | package.json |
hook-dsh-package-pinner.log |
pin pass (^0.3.4 → 0.3.4; keep-list wins) |
hook-dsh-cargo-governor |
Cargo.toml |
hook-dsh-cargo-governor.log |
chain pass (bare caret / =exact) + cargo upgrade |
Composition semantics: pin → bump-exact (the pinner pins ^0.3.4 → 0.3.4; a fully pinned
manifest then leaves the governor's update stage nothing to do, while its chain pass may still
re-canonicalize chain pins), keep-list wins (the pinner's pin-policy.json keeps ranges as
authored).
The ledgers are separate (hook-dsh-package-pinner.log vs
hook-dsh-package-governor.log); activating one never implies another - order between two npm
listeners is defined only by registration.
Machinery-wise it is a factory flavor: inject: ["fs", "pluginFactory"]
- the gate, the discovery, the union keep-list, the guarded write, the refresh, the continuation,
the effects and the schema come from
plugin-dsh-factory; the refusal guard and the suppression composer come fromhook-dsh-core. This bundle keeps the module leaf: the range law (Function/Pin), the decode, and every ledger string. Besides thefs/observedevent path, its chain pass is registered with the factory's direct-govern registry at apply (Factory.RegisterGovern("package.json", "pin", …)— factory SCHEME.md §2.16), so theraw-writetool's per-callgovernselection can drive the same pin pass directly through Factory.Govern (Function/Direct — same machinery, same ledger strings).
The DSH plugin family is the DeepSeek Harness plugin layer of the PlayForm ecosystem:
TypeScript-first Source/ → Target/, the deterministic @playform build, prepublishOnly-only -
the same conventions as every other @playform package.
Install
- Remote / dependency install (auto-activation):
pnpm add @playform/hook-dsh-package-pinnerin the profile dir (+ the package name indsh.profile.bundles, ordsh plugin add) - installed automatically and activated at the next host start. - Local git clone: clone →
pnpm install --ignore-workspace(the bundle carries its own node_modules) →npx Build 'Source/**/*.ts' --ESBuild Configuration/ESBuild.ts→dsh plugin --profile <name> add <this directory>. - Native dsh install:
dsh plugin --profile <name> add ./local-hook-dsh-package-pinner-<v>.tgz.
All three end the same way: the loader activates the entry from Target/, cordis.patch.yml
inserts the hook-dsh-package-pinner row, and the ledger logs activated (pinner, ...) at the next
host start.
CAVEAT (verified live): pnpm does NOT auto-install a linked package's dependencies - the
linked checkout must carry its own node_modules or the entry load fails silently (no activation
line).
Usage
The bundle is configured through its cordis.patch.yml row (or the profile's dsh.bundle
manifest) - the full config block is in The Config:
- insert:
- id: hook-dsh-package-pinner
name: "@playform/hook-dsh-package-pinner"
config:
log: true
logFile: ~/.dsh/hook-dsh-package-pinner.log
sections: [dependencies, devDependencies, peerDependencies, optionalDependencies]
The Problem
Ranged versions make builds drift: "^0.3.4" today is "0.3.5" next week.
Teams that want reproducible installs want static versions - but writing them by hand (or remembering to) is exactly the kind of discipline an agent workflow loses.
The pinner makes static versions the default outcome of every write, invisibly.
How It Works
The pipeline P = Rewrite ∘ Pin ∘ Resolve ∘ Decode
fs/observed (target, {kind:"present", version}, actor)
── fired by the TOOL LAYER ONLY, for every harness write/edit, any thread ──►
│
▼
G1 Factory.Gate ── displayPath → actor ∈ mutationTools → kind "present" →
│ Stash idempotence → basename "package.json" → excluded?
│ excluded ──► ledger `skipped (excluded) <path>` (every other gate
▼ outcome is silent) outcome proceeds)
G2 Factory.Discover ── nearest registry.json walk-up (an exempt plain-fs
│ probe - it exists ONLY as a location for the co-located
│ pin-policy.json); Stash seed (targetKey, version)
▼
g3 PIN PASS (detached, contained - Factory.Continue; the listener never
│ awaits) ── ctx.fs.readText → union keep-list (ResolvePolicy: global
│ policyFile → the file's own directory → registry-adjacent → built-in
│ default) → Decode (JSON.parse, null on failure) → the RANGE LAW
│ (Function/Pin - ONE leading ^/~/= stripped per dep) → the REFUSAL
│ GUARD (core's Refusal) → GuardedWrite (replaceIfVersion + the P4
│ fence) → ledger `pinned <path> (<N> versions)` → Refresh (P3
│ re-emit, same actor)
▼
SILENCE: the tool result shows exactly what the author wrote.
The pinned state is discoverable only by a subsequent read - or in
the ledger.
The range law (the transform, exactly) - for each dependency value (after the keep-list gate), in order:
| # | Condition | Action | Examples |
|---|---|---|---|
| 1 | not a string | untouched | "foo": {"imports": ...} |
| 2 | first char not in {^, ~, =} |
untouched | "0.3.4", "1.2.3-rc.1", "*", "", ">=1.0.0", "workspace:*", "file:../x", "link:...", "git+https://...", "npm:[email protected]" |
| 3 | whitespace in value | untouched | "^1.0.0 || 2.0.0", "^1.0.0 <2.0.0" |
| 4 | otherwise | strip the one leading prefix | "^0.3.4" → "0.3.4", "~1.2.3" → "1.2.3", "=2.0.0" → "2.0.0" |
- Idempotent: an already-static version has no leading prefix, so rule 2 passes it through -
pinning a pinned file is a no-op rewrite (the ledger shows
no changes to pin for ...).P(P(c)) = P(c). - Keep-list policy: a pin-policy.json (
{ "keep": ["tailwindcss"] }) protects packages whose ranges must stay EXACTLY as the author wrote them; the effective keep-list is the union of every readable discovered policy, and the P3 chain-keys interlock means the governor's^resolvedchain pins are never stripped. A file that exists but does not parse is logged (unreadable pin-policy.json at ... - using built-in default) and contributes nothing. - Documented edge decision:
"^1.*"IS stripped to"1.*"- the law strips the notation (the prefix) and leaves the content untouched; protect wildcards with the keep-list if you need them preserved. - Refusal guard: non-dependency sections (
name,version,description,scripts, ...) are NEVER touched - if the pinner's own logic would ever change one, the rewrite is REFUSED and logged (REFUSED rewrite of ...) instead of applied. - Version coherence: the rewrite carries
replaceIfVersionat the observed version; a racing author write makes it fail safely (no clobber), and the service-issued fresh version is re-emitted with the same actor so the author's next guarded write never failsFS_STALE_VERSION. The re-emit re-enters this listener; the Stash token gate makes it a no-op.
The Source Layout
TypeScript-first, built with @playform/build (ESBuild + tsc type-check):
hook-dsh-package-pinner/
├── Source/ ← TypeScript (NOT shipped)
│ ├── Library.ts ← entry: name / apply / Config / inject
│ │ + default { name, apply, Config, inject }
│ ├── Function/ ← the module leaf - Apply.ts (thin wire-up),
│ │ Observe.ts (thin listener), Transform.ts
│ │ (the range law), Pin.ts, Direct.ts (the
│ │ direct-govern driver), Decode.ts
│ ├── Interface/ ← typed contracts (State, Factory, Manifest, ...)
│ └── Variable/ ← constants, defaults, the Config schema
├── Configuration/
│ └── ESBuild.ts ← the @playform/build custom config (+ .js twin)
├── Target/ ← built output (SHIPPED: .js + .d.ts)
├── cordis.patch.yml ← the loader row (name: the package identity)
├── package.json ← main → Target/Library.js
└── README.md / SCHEME.md ← usage + the design document
The published artifact contains only the built output - files whitelists Target/,
cordis.patch.yml, and the docs; Source/ never ships.
There are no build/watch npm scripts:
the only npm script is prepublishOnly
(Build 'Source/**/*.ts' --ESBuild Configuration/ESBuild.ts --TypeScript Configuration/TypeScript.noemit.json && tsc -p tsconfig.json && tsc-alias -f -p tsconfig.json).
The Hard Lessons
injectandConfigmust sit on the DEFAULT export object - the loader builds the fiber from the default object; named-only exports are shadowed and service accessors throwcannot get property "fs" without inject.applymust return nothing - a returned value silently kills event delivery. Test probes read the state through the__pinnerStatecontext attachment.ctx.fs.writeTextfrom a root plugin needs an explicit sandbox policy- the deployment default (
workspace-write) denies paths outside the canonical workspace; the pinner passes{ mode: "danger-full-access" }because its own exclude list IS its fence.
- the deployment default (
The Config
The exported Config schema (the factory's Schema helper extended with sections) validates and
fills every default at load - invalid configuration fails loudly.
New patch entries are declared
with insert:.
- insert:
- id: hook-dsh-package-pinner
name: "@playform/hook-dsh-package-pinner"
config:
log: true
logFile: ~/.dsh/hook-dsh-package-pinner.log # SEPARATE ledger (own plugin)
mutationTools: [write, edit, str_replace_editor, raw-write]
policyFile: "" # optional global pin-policy.json (else discovery, else built-in)
updateCooldownMs: 3000 # carried by the shared block, never read (no update stage)
sections: [dependencies, devDependencies, peerDependencies, optionalDependencies]
exclude: [node_modules, .git, .dsh, .pnpm, .store, DeepSeek Harness.app]
In Action
One pinned write.
The author drops a package.json with two ranged versions and a keep-listed
package nearby:
{
"name": "@acme/tool",
"scripts": { "build": "tsc" },
"dependencies": {
"@playform/build": "^0.3.4",
"tailwindcss": "^3.0.5",
"@acme/core": "~1.2.3"
}
}
A pin-policy.json ({"keep":["tailwindcss"]}) sits beside the file, so tailwindcss keeps its
range; the other two dependencies are pinned.
The transcript shows only what the author wrote; the ledger shows the pin:
[2026-10-03T09:15:22.411Z] activated (pinner, logFile=~/.dsh/hook-dsh-package-pinner.log, sections=[dependencies, devDependencies, peerDependencies, optionalDependencies], exclude=[node_modules, .git, .dsh, .pnpm, .store, DeepSeek Harness.app])
[2026-10-03T09:16:01.880Z] pinned ~/Projects/acme/tool/package.json (2 versions)
Read the file back and "@playform/build" is "0.3.4", "@acme/core" is "1.2.3",
"tailwindcss" is still "^3.0.5", and "scripts" is byte-identical.
Write the pinned file again
and the pass is a no-op with its own line: no changes to pin for ....
Write inside
node_modules/.git/.dsh and the ledger gains skipped (excluded) ... while the file stays
untouched.
(A non-JSON package.json - or a refusal, if a non-dependency section would change -
gets its own line, e.g. observed non-JSON package.json ... - skipped, before the silence.)
The Ledger
One global log (logFile, default ~/.dsh/hook-dsh-package-pinner.log - SEPARATE from the
governor's ledger) records activation, exclusions, non-JSON skips, refusals, and every pin result.
The strings this module composes (the hook-dsh-package-pinner: logger prefix is the factory's
Append; each line is [<ISO>] <message> in the file):
activated (pinner, logFile=..., sections=[...], exclude=[...])
skipped (excluded) <path>
observed non-JSON package.json <path>
pinned <path> (N versions)
no changes to pin for <path>
REFUSED rewrite of <path>: non-dependency section "<name>" would change
(The non-JSON line ends with an em dash followed by skipped - part of the literal string, so its
byte-exact form appears only in the In Action excerpt above.)
The activation line is written by apply() - "did it activate" must be answerable from the ledger
alone.
The two release groups (CLASSIC vs EFFECT-TS)
Two published groups, one contract: this package is the CLASSIC build - plain TypeScript,
zero framework dependencies: import ... from "@playform/hook-dsh-package-pinner" resolves to Target/.
The EFFECT-TS implementation of the same contract is the separate package @playform/ets-hook-dsh-package-pinner -
effect-backed, built on the shared @playform/ets-base-dsh base with effect v4.0.2 as
its runtime dependency. Install the group you run and never mix the groups in one graph
(the effect-ts Update returns Effect envelopes, not the classic dispatch envelope).
License 📜
CC0-1.0.