Skip to content

Commit b0bafcc

Browse files
ncrmroclaude
andcommitted
docs: Add job porting design document
Documents the design for `/deepwork_jobs.port`, covering global vs project scope mapping, portability tensions, the `scope` field proposal, and required infrastructure changes. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 77402b2 commit b0bafcc

1 file changed

Lines changed: 143 additions & 0 deletions

File tree

doc/job-porting.md

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
# Job Porting: Global and Project Scope
2+
3+
Design document for `/deepwork_jobs.port` — a skill that ports DeepWork jobs between project-local and global (`~/.deepwork/`) scope.
4+
5+
## Problem
6+
7+
All DeepWork jobs are project-scoped today. Every path, hook, doc spec, and output reference assumes a project root. A global job needs to work in any project, which means it cannot assume any specific project structure exists.
8+
9+
## Scope Mapping
10+
11+
The global directory structure mirrors the project-local one:
12+
13+
| Scope | Jobs | Doc Specs | Skills | Config |
14+
|---------|----------------------|---------------------------|---------------------|------------------------|
15+
| Project | `.deepwork/jobs/` | `.deepwork/doc_specs/` | `.claude/skills/` | `.deepwork/config.yml` |
16+
| Global | `~/.deepwork/jobs/` | `~/.deepwork/doc_specs/` | `~/.claude/skills/` | `~/.deepwork/config.yml` |
17+
18+
This mirrors the existing convention where `.claude/CLAUDE.md` (project) and `~/.claude/CLAUDE.md` (global) coexist.
19+
20+
## Portability Tensions
21+
22+
### 1. Output Paths
23+
24+
Project-local jobs have concrete output paths:
25+
26+
```yaml
27+
outputs:
28+
- competitive_research/competitors_list.md
29+
- competitive_research/[competitor_name]/research.md
30+
```
31+
32+
These assume the project wants a `competitive_research/` directory. A global job cannot assume that. The recommended approach is to parameterize the output root:
33+
34+
```yaml
35+
inputs:
36+
- name: output_dir
37+
description: "Directory for job outputs"
38+
outputs:
39+
- "{output_dir}/competitors_list.md"
40+
- "{output_dir}/[competitor_name]/research.md"
41+
```
42+
43+
This aligns with how inputs already work in `job.yml` and avoids imposing structure on the target project.
44+
45+
### 2. Doc Specs
46+
47+
Doc specs define quality criteria, not project structure, so they are generally portable. The port operation must:
48+
49+
- Copy referenced doc specs from `.deepwork/doc_specs/` to `~/.deepwork/doc_specs/`.
50+
- Rewrite `doc_spec:` references in `job.yml` from `.deepwork/doc_specs/X.md` to `~/.deepwork/doc_specs/X.md`.
51+
- Handle name collisions when a global doc spec with the same name already exists.
52+
53+
### 3. Step Instructions
54+
55+
Step instruction files (`steps/*.md`) may contain:
56+
57+
- **Hardcoded project paths** (`src/components/`, `db/migrate/`) — not portable.
58+
- **References to project tools** ("run `npm test`", "use the Rails console") — not portable.
59+
- **Generic workflow guidance** ("ask the user for requirements", "validate against doc spec") — fully portable.
60+
61+
The port operation must audit instructions for project-specific references and flag them for the user to resolve.
62+
63+
### 4. Hook Scripts
64+
65+
Hook scripts (`.sh` files in `hooks/`) are the most fragile:
66+
67+
- They may reference project-specific binaries, paths, or environment.
68+
- Their paths in generated skills resolve as absolute from project root.
69+
- Global hooks must live at `~/.deepwork/jobs/{name}/hooks/`.
70+
71+
Prompt-based hooks (`prompt:` and `prompt_file:`) are inherently more portable than `script:` hooks. The port operation should warn or block on script hooks that are not obviously portable.
72+
73+
### 5. AGENTS.md
74+
75+
`AGENTS.md` files contain project-specific context by definition (bespoke learnings from `/deepwork_jobs.learn`). When porting to global, the operation should either strip the file entirely or extract only generalizable content and flag the rest for review.
76+
77+
When porting from global to project, the `AGENTS.md` starts empty and accumulates project-specific learnings via `/deepwork_jobs.learn` as normal.
78+
79+
## Precedence and Override Model
80+
81+
Following the pattern established by standard jobs and `CLAUDE.md`:
82+
83+
```
84+
Global job (baseline) -> Project-local job (override)
85+
```
86+
87+
- If a project has a local job with the same name as a global job, local wins.
88+
- `deepwork sync` generates skills from both scopes, with local taking precedence.
89+
- This allows users to install a global job and then customize it per-project.
90+
91+
## The `scope` Field
92+
93+
Rather than retrofitting portability onto existing jobs, add a `scope` field to `job.yml`:
94+
95+
```yaml
96+
name: code_review
97+
scope: portable # or "local" (default)
98+
version: "1.0.0"
99+
```
100+
101+
When `scope: portable`:
102+
103+
- `/deepwork_jobs.define` enforces parameterized output paths.
104+
- `/deepwork_jobs.review_job_spec` adds portability criteria to its validation.
105+
- `/deepwork_jobs.implement` generates instructions without project-specific references.
106+
- `/deepwork_jobs.learn` separates generalizable learnings from bespoke ones more aggressively.
107+
108+
This makes portability a design-time decision rather than a post-hoc transformation.
109+
110+
## Port Operations
111+
112+
### Project to Global
113+
114+
1. **Select job** — ask which local job to port.
115+
2. **Portability audit** — scan for:
116+
- Hardcoded project paths in step instructions (patterns like `src/`, `app/`, stack-specific file extensions).
117+
- Script hooks (warn, suggest converting to prompt hooks).
118+
- `AGENTS.md` content (strip or flag).
119+
- Output paths without parameterization.
120+
3. **Transform** —
121+
- Rewrite output paths to use `{output_dir}` parameter or ask the user for a strategy.
122+
- Add `output_dir` as an input to the first step if not already present.
123+
- Rewrite `doc_spec:` paths from `.deepwork/` to `~/.deepwork/`.
124+
- Remove or generalize `AGENTS.md`.
125+
4. **Copy** — write to `~/.deepwork/jobs/{name}/` and `~/.deepwork/doc_specs/`.
126+
5. **Sync global** — run `deepwork sync --global` to generate skills in `~/.claude/skills/`.
127+
128+
### Global to Project
129+
130+
1. **Select job** — list available global jobs.
131+
2. **Copy** — inject from `~/.deepwork/jobs/{name}/` to `.deepwork/jobs/{name}/`.
132+
3. **Localize** — rewrite `doc_spec:` paths to `.deepwork/doc_specs/`, copy doc specs into the project.
133+
4. **Optionally concretize** — ask if the user wants to replace `{output_dir}` with a concrete project path.
134+
5. **Sync** — run normal `deepwork sync`.
135+
136+
## Infrastructure Changes
137+
138+
The port skill depends on changes to the DeepWork CLI and sync pipeline:
139+
140+
1. **`~/.deepwork/` directory convention** — the CLI must recognize this as the global job store.
141+
2. **`deepwork sync --global`** — sync must be scope-aware, generating skills to `~/.claude/skills/` from `~/.deepwork/jobs/`.
142+
3. **Precedence in sync** — when both global and local jobs exist with the same name, local wins. The merged set gets synced.
143+
4. **`deepwork install` awareness** — optionally inject global user jobs into projects, or let sync handle the merge at skill generation time.

0 commit comments

Comments
 (0)