dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
Enterprise ontology and governance layer for DeepSeek Harness (DSH)
An enterprise agent has to know what a project is, who owns it, which customer it belongs to, and what it is allowed to touch. DeepWork is where an enterprise writes that down — and where an agent's tools and permissions are derived from it, and enforced.
It is deliberately not part of an agent. The world it describes belongs to the enterprise, so the second agent, the third, and the one after that read the same one.
DeepWork is a platform built on DeepSeek Harness (DSH). DSH ships a complete agent harness; DeepWork adds the one thing it does not ship — the enterprise's own world, and the rules for acting in it. A plugin, not a fork, and a new domain costs YAML rather than code.
The rules are enforced against declarations, not against behaviour. A capability says what its tool touches — which argument is a path it writes, which program it starts — and the guard judges every call against that plus the domain's grants, before it runs and in the audit trail afterwards. Nothing verifies the declaration against what the tool actually does. A capability that described itself dishonestly would be trusted, and a tool that reaches the world through its own code rather than through the shell it declared is outside the door entirely.
So the guarantee here is advisory: a capability that declares honestly is governed, refused when it must be, and recorded every time — and reviewing that capability is what makes its declaration true. What this repository does not claim is that nothing can exceed its authority. Claiming that needs a boundary the current composition cannot express: one where the only way to touch the world is a channel the guard can see, so that "undeclared" and "impossible" become the same thing. That is the direction this project is built to move in, and it is not where it is today. The architecture document says which branches pass without judging anything, so a reader can check the claim against the code.
Every part of this repository is one step of the same journey: a world is declared, an agent is equipped from it, and what that agent does is governed on the way out.
the enterprise's world what the agent gets
────────────────────── ────────────────────
① declared objects, relations, states, → a domain is data: `schema.yaml` and the
who may write what instances beside it
② derived read tools, the write tool, → a capability is declared, not coded —
declared actions and queries nothing in TypeScript to add or remove
③ authorised `written_by` per type, → the host's own file and shell tools are
roles per deployment covered too; no roles means read-only
④ gated states, the moves between → a move needing a second pair of eyes is
them, and what each needs refused without a verdict from somebody
other than the person making the move
⑤ recorded the audit trail and write → every attempt, refusals included; field
provenance names and never field values
⑥ checked `npm run validate` → a declaration that did not take effect is
a failure, not a silence
Read it top to bottom and this repository is one thing. Read the sections below out of order and it is a list of mechanisms.
The same line as a picture:
flowchart TB
subgraph assembly["assembly"]
prof["a profile: which plugins, which roles, which domain, which mode — changing the deployment changes only this layer"]
end
subgraph data["a domain — data, not code"]
schema["schema.yaml — objects · relations · functions · states and transitions · who may write · actions · queries · situation · skill"]
inst["the instances beside it"]
end
subgraph dw["DeepWork — a plugin, not a fork"]
eng["the engine — reads the domain, builds the graph, derives the edges"]
der["derivation — the read tools and query modes, the write tool, declared actions, the lifecycle's requirements"]
gov["governance — the guard mounted globally in front of every call, permissions derived from written_by, review checked against provenance, an audit of field names and never field values"]
inj["injection — the rules the situation marks, in the prompt and in the catalogue"]
cap["a capability — a second plugin, declaring what its tools touch"]
end
subgraph hosted["the host — DeepSeek Harness"]
loop["the agent loop · the tool registry · the skill and prompt registries · the session"]
own["its own file and shell tools"]
end
prof --> dw
schema --> eng
inst --> eng
eng --> der
eng --> gov
eng --> inj
der -->|"the tool surface an agent is given"| loop
inj -->|"the rules block, and the catalogue"| loop
gov -->|"judges each call before it runs"| loop
cap -->|"declares, so it is judged too"| gov
gov -->|"or the host's own tools are the way around it"| own
loop -->|"a write that was allowed"| wrote["the instance file, and one structured audit entry"]
gov --> refused["a refusal, and one structured audit entry naming the rule that refused"]
Two places in that picture answer questions people expect one place to answer, so they are worth
naming. The guard is the door: before any tool runs, may this call touch this path at all. The write
path is the desk: may this content be written, by this caller, in this state. A capability's own
tools stop at the door; this plugin's write tool passes the door unjudged and is settled at the desk,
because nothing declares ontology_write and it is not in the built-in table — so its authority
lives inside the tool rather than in the mounted guard.
docs/architecture.md is the same route written out — the layers, one write end to end, and the limits named; and the same document in Chinese is there for a reader who works in Chinese.
Anyone putting an agent into a real business system. A forward-deployed engineer standing up the first use case; a platform team that has to answer "what is this agent allowed to touch, and who approved it"; the team that inherits it six months later.
packages/ontology/examples/engagement is the whole line at small scale: four stages, three of
them gated on a signature scoped to that stage, one declared action, one relation.
corepack pnpm install # once, right after cloning — nothing else is needed
npm run validate # is it sound? exit 0 or a list of what did not take effect
node packages/ontology/scripts/show-derivation.ts packages/ontology/examples/engagement
The second command prints what came out of the declaration — and note what it prints with no roles configured: three read tools, no write tool, and no actions derived, because an unconfigured deployment is a read-only one.
Then packages/ontology/src/examples.test.ts runs it for real — a stage cannot be entered
without its signature, a signature for one stage does not open the next, and the role that
makes a move cannot sign for it. Those three sentences are the project, and they are a test
rather than a paragraph.
DSH ships a complete agent harness — loop, tools, skills, workflows, plan mode, approval,
subagents, sandboxing. What it does not ship is any notion of the enterprise world the
agent is working in. A general agent sees document_001, project_782, user_23891. An
enterprise agent needs to know what a project is, who owns it, which customer it belongs
to, and what it is allowed to touch.
That gap is semantic, not mechanical. This project fills it, and nothing else.
There is a third layer between the model and the harness, and this project is it. A model reasons; a harness executes; neither knows what the enterprise is. That layer has to be declared, and that word is doing the work. A context assembled per request out of whatever a search surfaced is a guess about relevance — a good guess, and still a guess, and different on Tuesday. A context declared as objects, relations and rules is a fact the enterprise can be asked about, diffed, and held to, and the same question asked twice answers the same way.
It also has to distinguish what somebody vouched for from what merely got recorded. A layer that cannot tell a rule a person signed off on from a note an agent wrote yesterday has made its own trustworthiness a second thing nobody can check — so that distinction is a lifecycle here, and only the vouched-for half ever reaches an agent.
DSH provides DeepWork adds
────────────── ──────────────
agent loop ontology entities, relations, declared queries
tools governance written_by, file_location, required_fields
skills injection the vouched-for rules, marked for the situation in hand
audit every write attempt, refusals included
workflow
plan mode
human review
sandbox
A domain author writes YAML. The agent gets tools. Nobody writes TypeScript.
functions:
open_issues_of:
description: Issues still open against a given project.
use: traverse
relation: reported_on
direction: incoming
by: project_id
where: { status: open }
Those eight lines produce a callable mode, with its argument typed from the field declaration it names. Adding a type makes it queryable. Deleting a function removes the mode. Neither touches the plugin.
Governance works the same way. written_by on a type is the policy; there is no per-tool
check anyone has to remember to add. With no roles configured the write tool is not
registered at all, so an unconfigured deployment is a read-only one rather than a
permissive one.
The engine depends on nothing from the host, so a domain can be watched deriving its tools without installing one — no runtime, no API key, no agent. The same domain, declared twice: with nobody authorised to write, then with one role declared.
The picture is generated from the command below, not drawn, so it cannot drift from the
output (node packages/ontology/scripts/render-demo-svg.ts).
corepack pnpm install # once, right after cloning
node packages/ontology/scripts/show-derivation.ts packages/ontology/examples/project-delivery
domain packages/ontology/examples/project-delivery
5 object types, 16 instances, 6 relations (22 edges)
tools 4 read, 0 write
ontology_get
ontology_find
ontology_links
ontology_query
no write tool — with no roles configured, the deployment is read-only
objects
Customer key=customer_id instances=2 may write: delivery-lead
Project key=project_id instances=3 may write: delivery-lead, system
Person key=employee_id instances=3 may write: delivery-lead
Issue key=issue_id instances=5 may write: delivery-lead, engineer
Document key=document_id instances=3 may write: delivery-lead
Say who may write and the write tool appears, along with a tool per declared action. Declare a lifecycle and the states arrive with the rules that govern them — who may move something, and which moves need somebody else's verdict:
node packages/ontology/scripts/show-derivation.ts packages/ontology/tests/fixtures/review-delivery --roles '[{"prefix":"session-","role":"engineer"}]'
tools 3 read, 1 write
ontology_get
ontology_find
ontology_links
ontology_write (registered because roles are configured)
objects
Deliverable key=deliverable_id instances=1 may write: engineer
states: draft → signed_off
sign_off: draft → signed_off by: engineer needs a Signoff (decision=signed)
Signoff key=signoff_id instances=1 may write: reviewer
That second run is a governance model in fifteen lines, and not one of them was written by hand: it is the domain, read back. The enforcement behind those lines is described under Governance and checked by 393 tests.
A real session, with the query modes the agent chose and the answer it reached — including two details that only a declared world can produce: it refused to invent a project name the schema does not declare, and it drew a conclusion that needed the graph rather than a lookup.
docs/agent-session.md — and the same domain asked in Chinese, where the agent reached the same four declared queries
Working and demonstrated, not finished.
| Milestone | State |
|---|---|
| Plugin route — a third-party package installs and mounts in DSH | ✅ verified end to end |
| Ontology engine — schema parsing, instance loading, relation derivation | ✅ covered by the suite |
| Derived tool surface — reads | ✅ verified with real agent turns |
| Derived governance — writes, permissions, audit | ✅ verified with a real refusal and a real write |
| Write guard — every tool call, not only ours | ✅ mounted globally; a real refusal and a real shell-redirect refusal observed, both audited |
| Declared lifecycle — states, transitions, who may move them | ✅ enforced on the write path; a real refusal and a real promotion observed, both audited |
| Reads default to the vouched-for state | ✅ and say how many they left out, rather than narrowing quietly |
| Declared counters — who may record usage | ✅ granted apart from written_by; verified live by a role that may count and may not author |
| Declared actions — a named way to write, not only the generic tool | ✅ one tool per declaration; verified live, preconditions and role narrowing included |
| Declared review — a move that needs an independent verdict | ✅ enforced against provenance the platform recorded; a promotion went through on another session's verdict and was refused without one |
Declared value sets — a field's values as a closed set, not a hint | ✅ a value outside it is refused with value-not-declared, through the generic write tool and through a declared action |
| Declared-domain validation — an exit code a pipeline can read | ✅ a sound domain passes, a malformed one fails naming the declaration that was dropped |
| Example domains — five of them, one mechanism each | ✅ end to end; the fifth describes the systems outside the deployment, and is the first to declare a tool_grants entry |
| Capability layer — a second plugin that adds an ability | ✅ three packages: a project's tests, a language server, and the lineage around a session; two declare what they touch, and the third is a read that declares nothing |
| Mode role — who a mode's agents are, and the prompt they work under | ✅ its own package; it registers no tool, and the role it publishes is the one filter the rules block applies |
| Architecture — the route written down | ✅ docs/architecture.md, with each limit named beside the file that states it |
| Workspace UI | ✅ a page inside DSH's own interface, not a second server |
| Published to npm | prepared, not published |
393 tests in total.
The engine and every derivation are testable without a runtime, an API key, or an agent, because the package depends on nothing from DSH. That is why the test suite runs in under a second.
Scope is a design decision, so what this project refuses is worth naming as plainly as what it does. Each of these was considered and declined, not overlooked.
packages/external runs a program the deployment configured and reports what it did.
There is no client library per vendor and no protocol implemented here, so the repository still
holds no knowledge of anybody's API — it holds the mechanism, the grant and the trail.And the honest half — what a reader will find missing:
| Missing | Where it stands |
|---|---|
| One artefact showing a task start to finish — a recording, not a description | sessions are recorded as documents and refusals as audit entries, but there is no single thing a stranger can watch |
deepwork init — a domain to copy and rename | the six examples are the starter material |
| Validation on several real domains | one production domain has been through it — 17 object types, 269 instances, 214 relations — and that run is what put the two-level diagnostics in. One is not several |
| A connector for any particular system | the mechanism is in packages/external — one tool that runs a program the deployment configures — so what is missing is not the call but the other half of a connector: no client per vendor, no protocol per product, and no vendor is named anywhere in this repository |
git clone <this repo> && cd deepwork
corepack pnpm install
mkdir -p dist
cd packages/ontology && corepack pnpm run build && npm pack --pack-destination ../../dist && cd ../..
# point a DSH profile at the example domain
export DSH_HOME="$(pwd)/.dsh-home"
./node_modules/.bin/dsh --profile headless --dump-config > /dev/null
./node_modules/.bin/dsh plugin --profile headless add ./dist/deepwork-ontology-0.1.0.tgz
export DEEPWORK_ONTOLOGY_ROOT="$(pwd)/packages/ontology/examples/project-delivery"
./node_modules/.bin/dsh headless "Analyse the risk on project P-2026-001 and give me a management briefing."
To allow writes, say who may write. The role map is the gate:
export DEEPWORK_ONTOLOGY_ROLES='[{"prefix":"session-","role":"delivery-lead"}]'
A rule whose prefix is * matches every caller, and is how a deployment states the role it
acts as instead of inferring one from ids it does not generate. Prefer it unless one process
hosts several kinds of agent: an id-shaped rule is an assumption about the host's naming, and
when the host renames its agents the rule stops matching and every write is refused — which
reads as a permissions problem rather than as the stale assumption it is. * is one character,
so any real prefix still beats it and a mixed deployment can name its agents individually.
The panel lives inside DSH's own interface rather than beside it: one process, one origin, no second server to run and no RPC layer. Install the plugin into a profile, open DSH's web UI, and the Ontology row in the sidebar shows what the engine derived from the domain — the rules a type declares and who may make each move, the declared actions, the tool definitions with the JSON Schema of every argument, the object types with who may write them, and the relations with the field each one reads.
Put a role map in the roles box and the write tool appears in the listing; leave it empty
and the page explains why it does not. That is the governance model answering a question out
loud, from the running system, instead of from a document.
The panel answers from the domain the deployment loaded, and only that one: no path arrives from
the browser, so a request cannot name a domain at all. Reading some other domain would mean
starting another process with DEEPWORK_ONTOLOGY_ROOT pointing at it.
The panel answers "what did this domain derive". npm run validate answers "did any of it
fail to happen", which is the question that matters before a domain is deployed:
npm run validate
npm run validate -- packages/ontology/tests/fixtures/broken
Exit 0 means every declaration took effect. Exit 1 lists what did not, each with the name of
the thing that was dropped — an action pointing at an undeclared type, a field the type does
not have, a function whose mode is unavailable. Pass --role prefix=role to make the write and
action halves reachable; without it the command says so rather than reporting a shorter list
as a clean one, because with no roles nothing derives there and "declared equals derived" has
nothing to compare.
A schema file that cannot be read at all is the one failure that stops before there is a domain to check, so it is reported as a failing domain rather than as a diagnostic.
A report has two levels, and the line between them is who has to act.
Problems need somebody to act, and they fail the run: a declaration that cannot take effect (an action pointing at a type that does not exist, a field the type does not have, a transition naming a state that was never declared), or an instance file that could not be read. Notes are facts about the data that need nobody to act, and never fail: a declared directory with nothing in it yet, a relation no instance has wired, an instance whose identity fell back to its filename. Notes are still counted and printed — "nothing to fix" must not read as "nothing to see", since an empty query result is exactly what those notes explain.
The line was drawn by real data, not by taste. A production domain — 17 object types, 269 instances, 214 relations — loaded and answered correctly and produced nine unwired relations and three empty directories. Judged as failures, that report had nothing green in it, and a check that is always red is a check nobody reads. Split, the same run says what it should: four things the data has not grown into yet, and no defects at all.
Because the first version of that command did not split them, and because the fixture domains it
was built against were small, new, and written by the same hand, nothing caught it until a real
domain was put through. packages/ontology/tests/fixtures/ahead-of-its-data now pins the policy.
| Path | What it is |
|---|---|
| `packages/ontol |