@nidvue/teamwork 0.0.0-stage → 1.1.1
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.
- package/CHANGELOG.md +343 -0
- package/LICENSE +661 -0
- package/NOTICE +16 -0
- package/README.md +462 -2
- package/SECURITY.md +64 -0
- package/package.json +71 -4
- package/prompts/teamwork-pulse.md +12 -0
- package/prompts/teamwork-review.md +16 -0
- package/skills/teamwork/AGENTS.md +462 -0
- package/skills/teamwork/SKILL.md +795 -0
- package/skills/teamwork/references/Adapters.md +112 -0
- package/skills/teamwork/references/Audit.md +120 -0
- package/skills/teamwork/references/Concurrency.md +160 -0
- package/skills/teamwork/references/Dissent.md +85 -0
- package/skills/teamwork/references/Docs.md +74 -0
- package/skills/teamwork/references/Engineering.md +410 -0
- package/skills/teamwork/references/Evidence.md +140 -0
- package/skills/teamwork/references/Remotes.md +144 -0
- package/skills/teamwork/references/Roles.md +201 -0
- package/skills/teamwork/references/State.md +64 -0
- package/skills/teamwork/references/Testing.md +144 -0
- package/skills/teamwork/roles/architect.md +153 -0
- package/skills/teamwork/roles/ceo.md +218 -0
- package/skills/teamwork/roles/cfo.md +150 -0
- package/skills/teamwork/roles/coo.md +147 -0
- package/skills/teamwork/roles/cto.md +162 -0
- package/skills/teamwork/roles/data-engineer.md +120 -0
- package/skills/teamwork/roles/designer.md +349 -0
- package/skills/teamwork/roles/developer.md +166 -0
- package/skills/teamwork/roles/product-manager.md +151 -0
- package/skills/teamwork/roles/project-manager.md +159 -0
- package/skills/teamwork/roles/release-engineer.md +245 -0
- package/skills/teamwork/roles/reviewer.md +254 -0
- package/skills/teamwork/roles/security-auditor.md +157 -0
- package/skills/teamwork/roles/technical-writer.md +121 -0
- package/skills/teamwork/roles/tester.md +180 -0
- package/skills/teamwork/scripts/build_pi_package.py +200 -0
- package/skills/teamwork/scripts/privacy_scan.py +1185 -0
- package/skills/teamwork/scripts/sync_skill.py +108 -0
- package/skills/teamwork/scripts/teamwork.py +28 -0
- package/skills/teamwork/scripts/verify_release.py +502 -0
- package/skills/teamwork/src/teamwork/__init__.py +18 -0
- package/skills/teamwork/src/teamwork/__main__.py +10 -0
- package/skills/teamwork/src/teamwork/bundle.py +157 -0
- package/skills/teamwork/src/teamwork/cli.py +16 -0
- package/skills/teamwork/src/teamwork/config.py +396 -0
- package/skills/teamwork/src/teamwork/engine.py +10119 -0
- package/skills/teamwork/src/teamwork/gitutil.py +172 -0
- package/skills/teamwork/src/teamwork/imaging.py +124 -0
- package/skills/teamwork/src/teamwork/io.py +144 -0
- package/skills/teamwork/src/teamwork/layout.py +253 -0
- package/skills/teamwork/src/teamwork/names.py +191 -0
- package/skills/teamwork/src/teamwork/portable.py +79 -0
- package/skills/teamwork/src/teamwork/records.py +1220 -0
- package/skills/teamwork/src/teamwork/resources.py +120 -0
- package/skills/teamwork/src/teamwork/version.py +13 -0
- package/skills/teamwork/templates/AGENTS.md +460 -0
- package/skills/teamwork/templates/Docs/Architecture.md +40 -0
- package/skills/teamwork/templates/Docs/Archive.md +8 -0
- package/skills/teamwork/templates/Docs/Board.md +28 -0
- package/skills/teamwork/templates/Docs/Costs.md +30 -0
- package/skills/teamwork/templates/Docs/Decisions.md +26 -0
- package/skills/teamwork/templates/Docs/Design.md +106 -0
- package/skills/teamwork/templates/Docs/Plan.md +24 -0
- package/skills/teamwork/templates/Docs/Project.md +40 -0
- package/skills/teamwork/templates/Docs/Release.md +43 -0
- package/skills/teamwork/templates/Docs/Research.md +36 -0
- package/skills/teamwork/templates/Docs/Risks.md +18 -0
- package/skills/teamwork/templates/TeamMap.md +100 -0
- package/skills/teamwork-pi/SKILL.md +77 -0
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
# Engineering policy
|
|
2
|
+
|
|
3
|
+
Reference for the /teamwork skill. Loaded on demand; `SKILL.md` keeps the
|
|
4
|
+
operating procedure.
|
|
5
|
+
|
|
6
|
+
Related: [Engineering](Engineering.md) | [Evidence](Evidence.md) | [Docs](Docs.md) | [State](State.md) | [Concurrency](Concurrency.md) | [Roles](Roles.md) | [Testing](Testing.md) | [Audit](Audit.md)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
## Commit identity - role mailbox, never instance numbered
|
|
10
|
+
|
|
11
|
+
Every team commit is authored **and** committed by the role:
|
|
12
|
+
|
|
13
|
+
```text
|
|
14
|
+
Developer <developer@agents.nidvue.com>
|
|
15
|
+
Tester <tester@agents.nidvue.com>
|
|
16
|
+
Architect <architect@agents.nidvue.com>
|
|
17
|
+
Product Manager <productmanager@agents.nidvue.com>
|
|
18
|
+
Project Manager <projectmanager@agents.nidvue.com>
|
|
19
|
+
Security Auditor <securityauditor@agents.nidvue.com>
|
|
20
|
+
Designer <designer@agents.nidvue.com>
|
|
21
|
+
Reviewer <reviewer@agents.nidvue.com>
|
|
22
|
+
CEO <ceo@agents.nidvue.com> CTO <cto@agents.nidvue.com> COO <coo@agents.nidvue.com> CFO <cfo@agents.nidvue.com>
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Rules:
|
|
26
|
+
|
|
27
|
+
- Display name is the role; email is the lowercase role id at `agents.nidvue.com`.
|
|
28
|
+
- **Never** use an instance-numbered identity: no `Developer-1`, no
|
|
29
|
+
`developer-1@agents.nidvue.com`.
|
|
30
|
+
- Never use the operator's personal git identity for team work.
|
|
31
|
+
- **The role that does the work commits it.** Developer commits code and unit
|
|
32
|
+
tests, Tester integration/E2E tests, Technical Writer documentation, Architect
|
|
33
|
+
contracts and ADRs, Release Engineer workflows and release changes, Reviewer
|
|
34
|
+
merge commits. The CEO commits only CEO-owned documents (`Project.md`,
|
|
35
|
+
`Plan.md`, `Board.md`, `Decisions.md`) and the bootstrap commit - never another
|
|
36
|
+
role's deliverable in its place.
|
|
37
|
+
- The product identity `Teamwork <teamwork@agents.nidvue.com>` is **never** a valid
|
|
38
|
+
commit identity: it names the skill, not a role.
|
|
39
|
+
- CI enforces this with `teamwork.py identity --audit --range <base>..HEAD`; it
|
|
40
|
+
checks the author, the committer and the `Acting role:` trailer, and allows bot
|
|
41
|
+
dependency updates (`dependabot[bot]`, `github-actions[bot]`, `renovate[bot]`).
|
|
42
|
+
- Apply it per commit, without changing the repository config:
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
git -c user.name="Developer" -c user.email="developer@agents.nidvue.com" commit ...
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
`teamwork.py commit --role <role> ...` does this for you, and
|
|
49
|
+
`teamwork.py identity [--role X]` prints the exact identity.
|
|
50
|
+
`TEAMWORK_IDENTITY_DOMAIN` overrides the email domain.
|
|
51
|
+
|
|
52
|
+
Repo-local identity: the repository's own `user.name`/`user.email` is set to a
|
|
53
|
+
**role** mailbox (never the operator's), so an accidental plain `git commit`
|
|
54
|
+
cannot leak a personal identity. The per-commit `-c` form below still overrides
|
|
55
|
+
it and remains the rule for every deliverable.
|
|
56
|
+
|
|
57
|
+
## Commit batching
|
|
58
|
+
|
|
59
|
+
Accumulate a coherent, locally green change-set and commit once. No per-file,
|
|
60
|
+
per-test-run or per-finding micro-commits, no `WIP` churn. Never bundle unrelated
|
|
61
|
+
issues, mixed owners, or changes with independent rollback risk. Review the staged
|
|
62
|
+
diff, confirm no secrets, and reference the task id.
|
|
63
|
+
|
|
64
|
+
Commit at **staged milestones** - a finished milestone, a reviewed deliverable, a
|
|
65
|
+
closed gate - not on every keystroke.
|
|
66
|
+
|
|
67
|
+
## Commit message style (fixed)
|
|
68
|
+
|
|
69
|
+
Use this shape, in this field order, with these field names:
|
|
70
|
+
|
|
71
|
+
```text
|
|
72
|
+
<type>(<area>): <deliverable summary, <=72 chars>
|
|
73
|
+
|
|
74
|
+
Task: T-0007
|
|
75
|
+
Role: Developer
|
|
76
|
+
Producers: Developer-1, Developer-2
|
|
77
|
+
Goal: <what the task/milestone asked for>
|
|
78
|
+
Deliverable: <what was produced: files, docs, tests>
|
|
79
|
+
Why: <why this change, what evidence drove it>
|
|
80
|
+
Status: <actual state: implemented / reviewed / tested / blocked>
|
|
81
|
+
Result: <observed outcome: command @rev -> result>
|
|
82
|
+
Docs: <related documents>
|
|
83
|
+
Refs: <issues, PRs, disputes>
|
|
84
|
+
|
|
85
|
+
Acting role: Developer
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
- `type` is one of `feat fix test docs design research refactor perf build ci chore revert`.
|
|
89
|
+
- `Producers` = the instances that produced it (never invent one).
|
|
90
|
+
- `Goal`, `Deliverable`, `Why`, `Status`, `Result` are mandatory: they answer who,
|
|
91
|
+
what, why, where it stands and what actually happened.
|
|
92
|
+
- `Status` states the truth, including "blocked on X" or "awaiting review" - never
|
|
93
|
+
a hopeful claim.
|
|
94
|
+
- `Result` carries the evidence pointer (command + revision + observed result).
|
|
95
|
+
|
|
96
|
+
`teamwork.py commit` builds this message and refuses to commit when `--goal`,
|
|
97
|
+
`--deliverable`, `--why`, `--status` or `--result` is missing.
|
|
98
|
+
|
|
99
|
+
## Git LFS archival
|
|
100
|
+
|
|
101
|
+
Large and binary content is stored through Git LFS, not the object store.
|
|
102
|
+
|
|
103
|
+
- `teamwork.py repo` (and `init`) runs `git lfs install --local` and writes
|
|
104
|
+
`.gitattributes` with the LFS patterns: images, audio/video, archives, model
|
|
105
|
+
weights, datasets, fonts, native libraries, 3D assets.
|
|
106
|
+
- `.gitattributes` is committed; it is part of the project output.
|
|
107
|
+
- `teamwork.py commit` refuses to commit a file above `--lfs-threshold`
|
|
108
|
+
(default 1 MB) that no LFS pattern covers.
|
|
109
|
+
- `teamwork.py audit` reports LFS readiness and any untracked large file.
|
|
110
|
+
|
|
111
|
+
## Branch, PR and merge flow
|
|
112
|
+
|
|
113
|
+
`main` only ever receives merges performed by the **Reviewer**. No agent commits
|
|
114
|
+
to `main`, and no agent merges its own work.
|
|
115
|
+
|
|
116
|
+
```text
|
|
117
|
+
branch start -> work + commit -> SelfCheck -> pr open -> review pass/fail
|
|
118
|
+
|
|
|
119
|
+
(pass) pr merge --by reviewer
|
|
120
|
+
v
|
|
121
|
+
main
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
```sh
|
|
125
|
+
# 1. every instance works on its own branch
|
|
126
|
+
teamwork.py branch start --agent developer-1 --task T-0007 # [--worktree]
|
|
127
|
+
# branch name: developer-1/t-0007-<slug>
|
|
128
|
+
# 2. commit staged milestones on that branch (commit refuses on main)
|
|
129
|
+
teamwork.py commit --role developer --type feat --task T-0007 ... --all
|
|
130
|
+
# 3. your own review + test, then hand a PR to the Reviewer
|
|
131
|
+
teamwork.py task set developer T-0007 --status selfcheck
|
|
132
|
+
teamwork.py selfcheck developer T-0007 --by Developer-1 --note "..." --test "..."
|
|
133
|
+
teamwork.py pr open --agent developer-1 --task T-0007 [--push]
|
|
134
|
+
# 4. the Reviewer verifies and rules
|
|
135
|
+
teamwork.py review developer T-0007 --by reviewer --result fail --findings "..."
|
|
136
|
+
teamwork.py review developer T-0007 --by reviewer --result pass --evidence "..."
|
|
137
|
+
# 5. only the Reviewer merges, and only after a pass
|
|
138
|
+
teamwork.py pr merge --pr P-0003 --by reviewer-2 [--squash] [--delete-branch]
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Rules enforced mechanically:
|
|
142
|
+
|
|
143
|
+
- `commit` refuses to run on `main` (`--allow-main` overrides, and must be
|
|
144
|
+
justified); work belongs on a task branch.
|
|
145
|
+
- `pr open` refuses without a branch and without a recorded self-check.
|
|
146
|
+
- `pr merge` refuses if `review_status != passed`, and refuses a merger that is
|
|
147
|
+
not the Reviewer - an author can never merge their own work.
|
|
148
|
+
- a merge conflict aborts cleanly and comes back to the owner to rebase.
|
|
149
|
+
- **the merged branch is deleted** (`pr merge` retires it, including its worktree;
|
|
150
|
+
`--keep-branch` opts out). `audit` and `loop` report merged-but-still-open
|
|
151
|
+
branches until they are gone.
|
|
152
|
+
- a passing review merges the PR itself: the lane that verified the revision runs
|
|
153
|
+
the merge and deletes the branch, so an approved deliverable never waits for a
|
|
154
|
+
second lane. Independence is enforced against the **author** (never their own
|
|
155
|
+
review or merge), not against a second Reviewer; `--no-merge` separates them when
|
|
156
|
+
a project wants two pairs of eyes on the landing step.
|
|
157
|
+
- the merge commit is authored by `Reviewer <reviewer@agents.nidvue.com>` and carries
|
|
158
|
+
the fixed message style (`chore(merge): ...`, evidence pointer to the review).
|
|
159
|
+
- generated records (Archive.md, Board.md, Plan.md) are committed by the Reviewer
|
|
160
|
+
as `chore(records): ...` immediately before the merge, so the ledger matches the
|
|
161
|
+
merged revision.
|
|
162
|
+
- the archive entry is written at review time, before the merge revision exists,
|
|
163
|
+
so its `branch / merge` field says `pending`; `pr merge` repoints that one line
|
|
164
|
+
to the merge revision and commits the rewrite as a second `chore(records): ...`
|
|
165
|
+
on the base branch (ledger `pr.merge.archive`). The rewrite is never left as an
|
|
166
|
+
uncommitted edit, which would keep `pending` in HEAD and block the next merge
|
|
167
|
+
on a dirty tree. Only an entry still saying `pending` is repointed, and of
|
|
168
|
+
several such entries for one branch only the newest: a reworked task reuses its
|
|
169
|
+
branch name, so rewriting every match would erase the earlier merge revision.
|
|
170
|
+
- PR records live in `.pi/Teamwork/Teams/<Team>/Reviews.md` (hidden local state);
|
|
171
|
+
the merged revision is recorded on the task as `merge_commit`. `find_pr` and
|
|
172
|
+
`find_pr_exact` take the branch as an optional third argument, and every PR
|
|
173
|
+
lookup in the merge path passes it: a task reworked after a merge keeps the old
|
|
174
|
+
PR record, so matching an id or a task alone can return the branch that is
|
|
175
|
+
already in the base.
|
|
176
|
+
|
|
177
|
+
`teamwork.py branch list` shows branch -> PR -> merged state;
|
|
178
|
+
`teamwork.py pr list [--open]` is the Reviewer's PR inbox; `audit` and `loop`
|
|
179
|
+
report branches that are not merged.
|
|
180
|
+
|
|
181
|
+
## Push policy - reviewed and staged, never batched
|
|
182
|
+
|
|
183
|
+
The **Release Engineer** is the role that pushes to the shared remote, and only
|
|
184
|
+
after the **Reviewer** has passed the revision with no open finding.
|
|
185
|
+
|
|
186
|
+
- **Per stage.** A stage ends with a push, not with a merge: once a coherent
|
|
187
|
+
stage is squashed, rebased and merged and the gates below are green on that
|
|
188
|
+
revision, push it, so the remote does not drift far from local `main`. Do not
|
|
189
|
+
sit on a stack of unreviewed commits and do not wait for the release to push.
|
|
190
|
+
- **Pre-push gates on the exact revision:** build, tests, `privacy_scan.py
|
|
191
|
+
--tree --history`, and the link check all green. A red gate is not pushed.
|
|
192
|
+
- **Post-push:** watch CI and confirm green **on that SHA**; record the revision,
|
|
193
|
+
run ids and conclusions.
|
|
194
|
+
- **Red run -> route it.** Code -> Developer, test -> Tester, contract ->
|
|
195
|
+
Architect, workflow/packaging/flake -> Release Engineer, scope -> CEO. Re-run
|
|
196
|
+
after the fix.
|
|
197
|
+
- **Red lines:** force-pushing a shared branch, rewriting published history or
|
|
198
|
+
retagging a release needs the CEO's explicit authorization and is recorded with
|
|
199
|
+
`teamwork.py redline record`. Tags and public releases are the CEO's step,
|
|
200
|
+
prepared and verified by the Release Engineer.
|
|
201
|
+
- **Never push a secret or local state.** The privacy scan is the gate: it fails
|
|
202
|
+
on credentials, on private agent-host configuration (auth, settings, sessions,
|
|
203
|
+
model stores) and on tracked local state (`.pi/`, virtualenvs, build output,
|
|
204
|
+
caches, `Scratch/`).
|
|
205
|
+
|
|
206
|
+
## Worktrees (optional but recommended for parallel writers)
|
|
207
|
+
|
|
208
|
+
`branch start --agent <Instance> --task <T-id> --worktree` creates the branch,
|
|
209
|
+
adds a worktree at `<Team>/Runtime/Worktrees/<Instance>/` and records both on the
|
|
210
|
+
task. The main tree stays on its own branch; the agent works inside the worktree.
|
|
211
|
+
|
|
212
|
+
- Run `teamwork.py` from the worktree: it resolves the team from the path
|
|
213
|
+
(`Runtime/Worktrees/<Instance>` -> team root), so you never need `--project`,
|
|
214
|
+
and it never creates a second team tree.
|
|
215
|
+
- From anywhere else, pass `--project <repo>` or set `TEAMWORK_ROOT`.
|
|
216
|
+
- `pr merge --delete-branch` also retires the worktree when the branch is still
|
|
217
|
+
checked out there.
|
|
218
|
+
|
|
219
|
+
## Worktree location
|
|
220
|
+
|
|
221
|
+
All worktrees, clones and scratch state live inside the repository at
|
|
222
|
+
`<Team>/Runtime/Worktrees/<Instance>/` (managed by `branch start --worktree`). Never create a
|
|
223
|
+
worktree, clone or scratch workspace in `$HOME`, `/tmp`, a sibling directory, or
|
|
224
|
+
any path outside the repository.
|
|
225
|
+
|
|
226
|
+
## Repo-local working state
|
|
227
|
+
|
|
228
|
+
A repository's wiki clone lives at `<repo>/.pi/wiki/`, never beside it. All
|
|
229
|
+
per-repository working state stays under that repository's own `.pi/`.
|
|
230
|
+
|
|
231
|
+
## Worktree hygiene
|
|
232
|
+
|
|
233
|
+
At the start and end of each task remove your own scratch: temp logs, one-off
|
|
234
|
+
dumps, finished-task artifacts. Cleanup is untracked/ignored-only; never delete
|
|
235
|
+
tracked, uncommitted, unmerged or evidence-bearing files, and never run
|
|
236
|
+
`git clean -fdx`. Prefer `teamwork.py clean` (temp patterns) and
|
|
237
|
+
`teamwork.py clean --all` (your `Scratch/`). Keep `Artifacts/` and `Reports/` for
|
|
238
|
+
things that are actually deliverables or evidence.
|
|
239
|
+
|
|
240
|
+
## Build economy
|
|
241
|
+
|
|
242
|
+
Never delete build caches to get a "clean slate": no `cargo clean`,
|
|
243
|
+
`rm -rf target/`, `rm -rf node_modules/`, `rm -rf dist/ build/ .venv/`. Build
|
|
244
|
+
only the touched scope; run the workspace-wide suite only at the pre-merge gate.
|
|
245
|
+
Reuse or cite an existing green run on the same revision instead of re-running
|
|
246
|
+
it. Report `BUILD: <command> · built|reused · <seconds>`.
|
|
247
|
+
|
|
248
|
+
## Linting, formatting and type checking
|
|
249
|
+
|
|
250
|
+
Style is not a matter of taste and not a review topic. It is **automated**: a
|
|
251
|
+
machine formats and lints the code, the CI fails when it would have changed
|
|
252
|
+
anything, and the reviewer reviews behaviour instead of whitespace. A human never
|
|
253
|
+
hand-formats, never argues about line length, and never disables a rule without a
|
|
254
|
+
recorded reason.
|
|
255
|
+
|
|
256
|
+
Rules:
|
|
257
|
+
|
|
258
|
+
- **One canonical toolchain per language**, configured in the repository and
|
|
259
|
+
reviewed like code. Do not introduce a second formatter or a competing config.
|
|
260
|
+
- **Run the fixer before you commit**, then the checker: `make format && make
|
|
261
|
+
lint` (or the language equivalent). The CI form check is not a suggestion -
|
|
262
|
+
unformatted code does not merge.
|
|
263
|
+
- **Type-check where the language supports it** (and run the static analyser
|
|
264
|
+
where it exists). A type error is a defect, not a style opinion.
|
|
265
|
+
- **Never weaken the gate to pass**: no blanket `# noqa`, no rule removed from the
|
|
266
|
+
config, no formatter excluded from a directory, no `--fix` on a file you did not
|
|
267
|
+
read. If a rule is genuinely wrong for this codebase, disable it *narrowly* with
|
|
268
|
+
a one-line reason in the config and record the decision.
|
|
269
|
+
- **Generated code is excluded explicitly**, never left unformatted by accident.
|
|
270
|
+
- **Evidence**: the lint/format command and its result go in the task evidence,
|
|
271
|
+
on the same revision as the tests.
|
|
272
|
+
|
|
273
|
+
| Language | Formatter | Linter | Types / static analysis |
|
|
274
|
+
|---|---|---|---|
|
|
275
|
+
| Python | `ruff format` | `ruff check` | `mypy` |
|
|
276
|
+
| JavaScript / TypeScript | `prettier --write` | `eslint` | `tsc --noEmit` |
|
|
277
|
+
| Go | `gofmt` / `goimports` | `go vet`, `staticcheck` | the compiler |
|
|
278
|
+
| Rust | `cargo fmt` | `cargo clippy -- -D warnings` | the compiler |
|
|
279
|
+
| Java / Kotlin | `spotless:apply` | `checkstyle` / `ktlint` | the compiler |
|
|
280
|
+
| C / C++ | `clang-format` | `clang-tidy` | `-Wall -Wextra -Werror` |
|
|
281
|
+
| Shell | `shfmt -w` | `shellcheck` | - |
|
|
282
|
+
| YAML | `prettier` / `yapf`-style | `yamllint` | - |
|
|
283
|
+
| Markdown | `prettier` / `markdownlint --fix` | `markdownlint` | - |
|
|
284
|
+
| JSON | language formatter | schema check | - |
|
|
285
|
+
| Terraform | `terraform fmt` | `tflint` | `terraform validate` |
|
|
286
|
+
| Dockerfile | `hadolint` | `hadolint` | - |
|
|
287
|
+
|
|
288
|
+
This repository uses the Python row: `ruff check .`, `ruff format --check .` and
|
|
289
|
+
`mypy src/teamwork` run in CI (see `pyproject.toml`), and `make lint` /
|
|
290
|
+
`make format` wrap them.
|
|
291
|
+
|
|
292
|
+
## Naming - PascalCase, camelCase, and the ecosystem's rule
|
|
293
|
+
|
|
294
|
+
Team-created **directories** are PascalCase (`docs/Team/`, `Roles/Developer/`,
|
|
295
|
+
`Agents/Tester-1/`, `Runtime/Locks/`). **File names** follow the ecosystem, and
|
|
296
|
+
PascalCase or camelCase are perfectly acceptable wherever the ecosystem allows
|
|
297
|
+
them - a name is wrong only when it fights its language or its neighbours.
|
|
298
|
+
|
|
299
|
+
| Kind | Convention | Example |
|
|
300
|
+
|---|---|---|
|
|
301
|
+
| Team directory | PascalCase | `Agents/Developer-1/`, `docs/Team/` |
|
|
302
|
+
| Docs page | PascalCase, kebab only for multi-word slugs | `Architecture.md`, `quick-start.md` |
|
|
303
|
+
| Python module / package | `lower_snake_case` (it *is* the import name) | `resources.py`, `teamwork/` |
|
|
304
|
+
| Python class / exception | `PascalCase` | `SkillRoot`, `VerificationError` |
|
|
305
|
+
| JS / TS component | `PascalCase` file | `ButtonGroup.tsx` |
|
|
306
|
+
| JS / TS module, helper | `camelCase` file | `buildIndex.ts` |
|
|
307
|
+
| Function / variable | snake_case (Python), camelCase (JS/TS) | `read_text`, `readText` |
|
|
308
|
+
| Constant | `UPPER_SNAKE_CASE` | `IDENTITY_DOMAIN` |
|
|
309
|
+
| Test file | source name + the ecosystem's test affix | `test_imaging.py`, `Button.test.tsx` |
|
|
310
|
+
| Tool-mandated file | the tool's name, never renamed | `pyproject.toml`, `Makefile`, `AGENTS.md` |
|
|
311
|
+
|
|
312
|
+
Rules: be consistent inside a directory; never rename a file just to satisfy
|
|
313
|
+
taste; never break an import name, a case-sensitive module path or a tool's
|
|
314
|
+
mandated filename for a naming preference; and if two conventions collide, the
|
|
315
|
+
ecosystem's rule wins over a local habit.
|
|
316
|
+
|
|
317
|
+
## Commit hygiene - rebase and squash before review
|
|
318
|
+
|
|
319
|
+
Commit while you work, then **clean up before the review**. A reviewer reads the
|
|
320
|
+
final diff; the intermediate noise is your problem, not theirs.
|
|
321
|
+
|
|
322
|
+
- `git rebase -i` onto the latest default branch, squash `wip` / `fixup!` /
|
|
323
|
+
"oops" commits, reorder into a logical sequence, and drop debug leftovers.
|
|
324
|
+
- Each commit is one coherent, self-contained change-set that follows the commit
|
|
325
|
+
style. A commit whose only purpose is to repair the previous commit is noise.
|
|
326
|
+
- **Target one commit per task.** Squash-merge into the default branch produces
|
|
327
|
+
exactly that, so the history reads as one idea per task.
|
|
328
|
+
- Rebase onto the default branch before opening or updating the request, and
|
|
329
|
+
resolve conflicts locally - never in the merge UI.
|
|
330
|
+
- **Never rebase or force-push a shared branch**, and never rewrite a commit that
|
|
331
|
+
is already on the default branch or a published tag: rewrite only your own
|
|
332
|
+
unpushed work. Anything else is a red line needing the CEO's authorization.
|
|
333
|
+
- Rebasing is not a way to hide a review: the Reviewer sees the squashed diff and
|
|
334
|
+
the conversation that produced it.
|
|
335
|
+
|
|
336
|
+
## Warnings are errors
|
|
337
|
+
|
|
338
|
+
A warning is a defect that has not broken anything **yet**. Treat every one as a
|
|
339
|
+
failure: the build, the tests, the linter, the type checker, the compiler and the
|
|
340
|
+
CI annotations must all come out clean, and "it is only a warning" is not an
|
|
341
|
+
argument a reviewer accepts.
|
|
342
|
+
|
|
343
|
+
- **Make the tool fail on warnings**, in the config, not in a habit:
|
|
344
|
+
`ruff check` (any finding fails), `mypy --warn-unused-ignores` +
|
|
345
|
+
`--warn-redundant-casts`, `pytest -W error` (plus
|
|
346
|
+
`filterwarnings = ["error"]` in `pyproject.toml`), `cargo clippy -- -D warnings`,
|
|
347
|
+
`go vet ./...`, `eslint --max-warnings 0`, `tsc --noEmit` (strict),
|
|
348
|
+
`-Wall -Wextra -Werror`, `shellcheck -S style`, `hadolint --failure-threshold style`.
|
|
349
|
+
- **Fix the cause.** Upgrade the dependency, replace the deprecated call, delete the
|
|
350
|
+
dead branch, annotate the type. A warning whose root cause is fixable is not
|
|
351
|
+
exempted.
|
|
352
|
+
- **Suppress narrowly when the cause is genuinely external** (a third-party
|
|
353
|
+
deprecation that no version fixes yet): one line, one rule, one path - never a
|
|
354
|
+
project-wide blanket - always with a reason and, where possible, the version or
|
|
355
|
+
date at which the exemption is re-checked. A blanket `# noqa`, a global
|
|
356
|
+
`filterwarnings = ["ignore"]` or a deleted rule is a red line.
|
|
357
|
+
- **CI annotations count.** A "Node.js 20 is deprecated", an unpinned action, a
|
|
358
|
+
cache-path notice or a deprecation banner in a workflow log is a warning: bump
|
|
359
|
+
the action, add the cache step or remove the step that produces it.
|
|
360
|
+
- **Test output counts.** Warnings raised by the project's own code fail the suite;
|
|
361
|
+
warnings from a dependency get a narrow, reasoned filter entry.
|
|
362
|
+
- **Evidence**: the clean run - `pytest -q` with zero warnings, `ruff check` clean,
|
|
363
|
+
`mypy` clean - goes in the task evidence on the same revision as the tests.
|
|
364
|
+
|
|
365
|
+
## File discipline
|
|
366
|
+
|
|
367
|
+
Keep only what the project needs. Update an existing document instead of creating
|
|
368
|
+
a near-duplicate; delete superseded drafts; don't commit generated files, caches,
|
|
369
|
+
editor noise or local state. Every file in the repository should be something the
|
|
370
|
+
project needs to build, run, test, document or ship.
|
|
371
|
+
|
|
372
|
+
### Comments - write none that the code already says
|
|
373
|
+
|
|
374
|
+
A comment is a maintenance liability: it is not compiled, it is not tested, and
|
|
375
|
+
it goes stale silently. Add one only when the *why* cannot be expressed in the
|
|
376
|
+
code itself.
|
|
377
|
+
|
|
378
|
+
Write a comment **only** for: a non-obvious reason or constraint (a spec, a bug
|
|
379
|
+
workaround with its reference, a platform quirk, a security decision), a public
|
|
380
|
+
API contract that a caller cannot infer, or a unit that is genuinely ambiguous.
|
|
381
|
+
|
|
382
|
+
Never write:
|
|
383
|
+
|
|
384
|
+
- a comment that restates the next line (`# increment i`);
|
|
385
|
+
- section banners for self-evident code (`# --- helpers ---` over three helpers);
|
|
386
|
+
- a docstring that repeats the function name (`"""Return the name."""`);
|
|
387
|
+
- changelog-in-code (`# added in v1.2`, `# removed the old branch`);
|
|
388
|
+
- commented-out code - delete it, git remembers;
|
|
389
|
+
- `TODO` / `FIXME` / `XXX` / `HACK` with no owner and no tracked task; if it
|
|
390
|
+
matters, file it as a task and cite the id, otherwise drop it;
|
|
391
|
+
- a comment that contradicts the code. A stale comment is a defect: fix or delete
|
|
392
|
+
it in the same change that made it stale.
|
|
393
|
+
|
|
394
|
+
Prefer a clear name, a small function or an explicit type over an explanatory
|
|
395
|
+
comment. When a comment is warranted, write what the code cannot say, in one line.
|
|
396
|
+
|
|
397
|
+
### Working tree - clean, structured, current
|
|
398
|
+
|
|
399
|
+
- **One canonical home per file.** Do not scatter drafts next to the real thing.
|
|
400
|
+
- **Delete temp and stale files as you go**: `*.orig`, `*.rej`, `*.bak`, `*~`,
|
|
401
|
+
`*.tmp`, `*.log`, `.DS_Store`, `Thumbs.db`, generated caches, scratch copies,
|
|
402
|
+
superseded drafts, empty directories. `teamwork.py clean` removes the patterns
|
|
403
|
+
it knows; do the rest by hand in the same task, not "later".
|
|
404
|
+
- **Never commit** build output, caches, local state, editor noise, secrets, or a
|
|
405
|
+
file whose only purpose is to be regenerated.
|
|
406
|
+
- **Scratch stays private and ephemeral**: `Agents/<Instance>/Scratch/`, gitignored,
|
|
407
|
+
emptied before the task closes. If a scratch artefact is worth keeping, move it
|
|
408
|
+
to its canonical path and commit it; if not, delete it.
|
|
409
|
+
- **Leave the tree cleaner than you found it.** A reviewer who cannot tell
|
|
410
|
+
deliverable from debris will fail the task.
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# Evidence, red lines and dissent
|
|
2
|
+
|
|
3
|
+
Reference for the /teamwork skill. Loaded on demand; `SKILL.md` keeps the
|
|
4
|
+
operating procedure.
|
|
5
|
+
|
|
6
|
+
Related: [Engineering](Engineering.md) | [Evidence](Evidence.md) | [Docs](Docs.md) | [State](State.md) | [Concurrency](Concurrency.md) | [Roles](Roles.md) | [Testing](Testing.md) | [Audit](Audit.md)
|
|
7
|
+
|
|
8
|
+
## Anti-hallucination protocol
|
|
9
|
+
|
|
10
|
+
**EVIDENCE GATE.** Every task completion and every report entry carries evidence
|
|
11
|
+
in this shape:
|
|
12
|
+
|
|
13
|
+
```text
|
|
14
|
+
<command or action> @ <revision> -> <observed result> [artifact path]
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Examples: `go test ./internal/api @a1b2c3d -> ok, 14 tests, 0.8s
|
|
18
|
+
[Reports/T-0002-test.log]`, `rg "func Adjudicate" internal/risk @a1b2c3d -> 1
|
|
19
|
+
match [internal/risk/kernel.go:42]`.
|
|
20
|
+
|
|
21
|
+
Claim discipline, per message and per artifact:
|
|
22
|
+
|
|
23
|
+
1. Separate **fact** (executed/read, with pointer), **assumption** (stated, to be
|
|
24
|
+
verified), **hypothesis** (being tested), **unknown** (with the check needed).
|
|
25
|
+
2. Never state an API, flag, path, version, schema field or config key you have
|
|
26
|
+
not read in this repository or its documentation. Check first.
|
|
27
|
+
3. Never claim tests pass, CI is green, a PR is merged, an issue is closed, or a
|
|
28
|
+
requirement is satisfied without the command output or state you observed.
|
|
29
|
+
4. External facts (market data, benchmarks, competitor behaviour) require a
|
|
30
|
+
source and a date, or they are marked `UNVERIFIED` and cannot justify a
|
|
31
|
+
decision.
|
|
32
|
+
5. Revision binding: evidence is valid for one revision. If the tree changed
|
|
33
|
+
after the run, the evidence is stale and must be regenerated.
|
|
34
|
+
6. Contradiction check: before asserting a shared fact, `recall` global memory
|
|
35
|
+
and your long-term memory; if it contradicts, resolve or escalate.
|
|
36
|
+
7. Blast-radius check: if your change touches files or interfaces outside the
|
|
37
|
+
task, either get it authorized or revert it.
|
|
38
|
+
8. Self-claims are not acceptance: Tester verifies integration, Reviewer verifies
|
|
39
|
+
before merge, and the CEO only closes an acceptance criterion with evidence
|
|
40
|
+
produced or reproduced by a role other than the author.
|
|
41
|
+
|
|
42
|
+
### The evidence packet
|
|
43
|
+
|
|
44
|
+
A one-line claim is a pointer, not proof. Stronger evidence has five parts, and
|
|
45
|
+
`tests run` / `selfcheck` / `review` record them as fields (artifacts are hashed
|
|
46
|
+
into `Ledger.jsonl`, so editing the file after the fact breaks the match):
|
|
47
|
+
|
|
48
|
+
| Part | Question it answers | Flag |
|
|
49
|
+
|---|---|---|
|
|
50
|
+
| baseline | what state did the run start from? | `--baseline '<empty cache>'` |
|
|
51
|
+
| action | what exactly was executed? | `--evidence '<cmd> @<rev> -> <result>'` |
|
|
52
|
+
| result | what did the real artifact return? | same line |
|
|
53
|
+
| artifact | where is the proof a later agent can re-open? | `--artifact <path>` (repeatable) |
|
|
54
|
+
| replay | how does another agent reproduce it? | `--replay '<cmd or path>'` |
|
|
55
|
+
|
|
56
|
+
A **defect fix adds a sixth**: the failing run must precede the passing one.
|
|
57
|
+
`task add ... --bug` marks the defect, and its self-check is refused until the
|
|
58
|
+
task itself carries the transition:
|
|
59
|
+
|
|
60
|
+
```sh
|
|
61
|
+
teamwork.py tests repro T-0007 --by developer-1 \
|
|
62
|
+
--pre-rev aaa111 --pre-evidence "pytest tests/unit/test_x.py @aaa111 -> 3 failed" \
|
|
63
|
+
--post-rev bbb222 --post-evidence "pytest tests/unit/test_x.py @bbb222 -> 12 passed"
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
The proof lives on the task, not on a layer record: a repro names one defect, so
|
|
67
|
+
it cannot leak to a sibling bug in the same area. Task ids are unique per queue,
|
|
68
|
+
not per workspace, so when `T-0001` exists on two queues, name the owner with
|
|
69
|
+
`--role <role>`. `tests list` shows layer evidence; `task list` shows the repro
|
|
70
|
+
line.
|
|
71
|
+
|
|
72
|
+
`tests repro` refuses a single revision, a pre-run that does not read as failing,
|
|
73
|
+
and (in a git workspace) a pre-revision that is not an ancestor of the
|
|
74
|
+
post-revision. `audit` reports a `--bug` task that closed with no repro record.
|
|
75
|
+
|
|
76
|
+
Mechanical enforcement: a task cannot reach `done` without evidence, a recorded
|
|
77
|
+
self-check, a PR and a passing review. Every gate override needs a reason:
|
|
78
|
+
|
|
79
|
+
```sh
|
|
80
|
+
teamwork.py task set <role> <T-id> --status done --force "<why the gate is bypassed>"
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
A bare `--force` is refused; the reason is stored on the task (`forced:`) and
|
|
84
|
+
listed by `teamwork.py loop` and `teamwork.py audit`. Actors are validated, not
|
|
85
|
+
trusted: `--by` must name an existing instance on every command that takes one -
|
|
86
|
+
including the dispute tribunal (`dispute sign --by cto` is refused when no CTO
|
|
87
|
+
exists). The author's instance cannot review or merge its own work, a self-check
|
|
88
|
+
belongs to the instance that claimed the task, and `criteria verify` refuses a
|
|
89
|
+
verifier from the owning role.
|
|
90
|
+
|
|
91
|
+
`loop` applies the completion gates directly (criteria, test layers and role
|
|
92
|
+
coverage, task states, merged/undeleted branches, gate overrides, provenance, the
|
|
93
|
+
ledger chain); `audit` is the wider health check (links, LFS, duplicates,
|
|
94
|
+
ownership sanity, PR flow). Run both before declaring the goal met.
|
|
95
|
+
`teamwork.py audit` lists `done` tasks without evidence, stale in-progress work,
|
|
96
|
+
near-duplicate tasks across agents, and memory cap violations. The CEO runs it
|
|
97
|
+
every loop and treats every listed item as a defect.
|
|
98
|
+
|
|
99
|
+
## RED LINES - forbidden, escalate instead
|
|
100
|
+
|
|
101
|
+
Stop the action, record it, escalate to the CEO. Never argue past a red line.
|
|
102
|
+
|
|
103
|
+
**Filesystem / repository**
|
|
104
|
+
|
|
105
|
+
- `rm -rf` on anything outside the agent's own `Scratch/` or worktree; deleting
|
|
106
|
+
files you did not create; `git clean -fdx`.
|
|
107
|
+
- `git push --force`, history rewrite, `git reset --hard` on shared work,
|
|
108
|
+
deleting branches or tags you did not create.
|
|
109
|
+
- Committing secrets, credentials, `.env` contents, large binaries, build output,
|
|
110
|
+
caches, or another agent's uncommitted work.
|
|
111
|
+
|
|
112
|
+
**Security**
|
|
113
|
+
|
|
114
|
+
- Disabling authentication, authorization, TLS or certificate verification;
|
|
115
|
+
`chmod 777`; piping remote scripts into a shell; unpinned installs from
|
|
116
|
+
untrusted sources; exfiltrating data anywhere.
|
|
117
|
+
- Reading, printing or storing secrets outside their intended runtime use.
|
|
118
|
+
|
|
119
|
+
**World actions (irreversible / external)**
|
|
120
|
+
|
|
121
|
+
- Publishing, posting, emailing, purchasing, deploying, calling production APIs,
|
|
122
|
+
executing trades, creating accounts, contacting anyone outside this machine.
|
|
123
|
+
- These require explicit **user** authorization relayed through the CEO and
|
|
124
|
+
recorded in `Decisions.md`.
|
|
125
|
+
|
|
126
|
+
**Integrity**
|
|
127
|
+
|
|
128
|
+
- Faking evidence, editing logs or CI config to hide a failure, weakening,
|
|
129
|
+
skipping or deleting tests to pass, marking `done` without execution, or
|
|
130
|
+
reporting a merge/approval that did not happen.
|
|
131
|
+
|
|
132
|
+
**Scope**
|
|
133
|
+
|
|
134
|
+
- Editing outside the assigned component/worktree, overwriting another agent's
|
|
135
|
+
artifacts or memory, or bypassing the Reviewer's merge gate.
|
|
136
|
+
|
|
137
|
+
Escalation protocol: `STOP` -> write the attempted action, why it is a red line,
|
|
138
|
+
the safe alternative, and the exact decision needed -> DM the CEO (CC CTO or
|
|
139
|
+
Security Auditor for technical/security lines) -> continue with non-blocked work
|
|
140
|
+
while waiting; never idle on it.
|