271 lines
14 KiB
Markdown
271 lines
14 KiB
Markdown
# The work cycle — what happens at the end of a piece of work
|
|
|
|
```
|
|
Status: Current
|
|
Owner: <who maintains this>
|
|
Last reviewed: <YYYY-MM-DD>
|
|
Governs: what must be true before a piece of work counts as finished
|
|
Review trigger: Any change to what the Command Center reads, or to which of
|
|
those channels a person rather than an agent has to write
|
|
```
|
|
|
|
> **This is a procedure, not a status board.** Nothing here records what is open,
|
|
> what is next, or what is blocked — those live in the tracker and on
|
|
> privacyllc.dev, and a copy of them in this file would be the second disagreeing
|
|
> record that `DOC_TRUST_MAP.md` exists to prevent.
|
|
|
|
## Why this file exists
|
|
|
|
A piece of work ends in more than one place. The code is committed; the issue
|
|
that asked for it is still open; the document the change contradicts still says
|
|
the old thing; and the project screen at
|
|
[privacyllc.dev](https://privacyllc.dev) still shows last week's next action to
|
|
whoever opens it.
|
|
|
|
None of those catch up on their own. Two of them cannot be caught up later by
|
|
anybody but the person who did the work, because by then nobody knows what the
|
|
next action was meant to be.
|
|
|
|
## The cycle
|
|
|
|
Run all of it, in this order, every time. It is short on purpose.
|
|
|
|
1. **Close what you finished.** `closes #N` in the commit that does the work, so
|
|
the record comes from the thing that happened rather than a date typed
|
|
afterwards. If no single commit finished it, close it by hand with the
|
|
evidence — a path, a symbol, a test name, or the command that proves it.
|
|
*"Done" is not a close.*
|
|
2. **File what you found.** A defect noticed on the way past is an issue with a
|
|
severity label and the build SHA it was seen at, not a memory. Filing it costs
|
|
a minute; the alternative is finding it again from scratch, or shipping it.
|
|
3. **Close the milestone if the batch landed.** A milestone with every issue
|
|
closed and itself still open reads as a batch still in progress — see
|
|
[Open and closed are not bookkeeping](#open-and-closed-are-not-bookkeeping).
|
|
4. **Update the documents this change triggered.** Read the `Review trigger`
|
|
lines: a new module, a changed data shape, a new migration, a new boundary
|
|
something crosses. Those edits go in **the same commit as the code**, for the
|
|
reason in [Docs travel with the push](#docs-travel-with-the-push).
|
|
5. **Push.** Nothing above is visible off this machine until you do, and step 7
|
|
reports on what was pushed.
|
|
6. **Write the log entry** in `docs/history/DEVELOPMENT_LOG.md`: what changed,
|
|
what it proved, **Next action**, and **Blockers**. Dated, append-only, newest
|
|
first.
|
|
7. **Tell the Command Center**, which is three calls: reconcile, so it re-reads
|
|
the tracker and the pushed docs; `PATCH` the project's summary and next
|
|
action, which nothing else writes; and a check-in if what changed is worth a
|
|
timestamped note. Commands are [at the bottom](#the-commands).
|
|
|
|
Steps 6 and 7 are the two that get skipped, and they are the two nobody else can
|
|
do afterwards.
|
|
|
|
## Next action — where it lives
|
|
|
|
| Copy | Where | What it is |
|
|
| --- | --- | --- |
|
|
| The current one | `nextAction` on the project, privacyllc.dev | the live answer to "what happens next", shown to whoever opens the project screen |
|
|
| The dated one | the newest entry in `DEVELOPMENT_LOG.md` | what the next action was **at that point** — history, not status |
|
|
|
|
These are not two records of the same thing, and the distinction is worth
|
|
holding on to. The field is overwritten every time and always describes now. The
|
|
log entry is never edited and describes a moment — which is what makes it safe
|
|
to keep, and why an old entry naming a next action that has since been done is
|
|
not stale, it is a receipt.
|
|
|
|
Write the next action as an **action**: the thing a person would start on
|
|
Monday, specific enough to begin without asking a question. "Continue the work"
|
|
is not one. If the honest answer is that you do not know, that is a real answer —
|
|
say what has to be decided and by whom.
|
|
|
|
**Filing an issue can change what the project card says next, without anyone
|
|
choosing that.** The dashboard's next action is the *newest open issue in the
|
|
current milestone* — not the most severe one; severity labels have no influence
|
|
on it at all. So a routine `P2` filed into the batch you are working in replaces
|
|
whatever the card was showing, and it will keep showing that until something
|
|
newer arrives. The `nextAction` field is the only way to say something different
|
|
on purpose, which is most of why step 7 exists.
|
|
|
|
`currentSummary`, `nextAction` and `description` are **write-only**: they are
|
|
deliberately absent from every API response, because free text can name a
|
|
customer or an unannounced product. Only the admin screen shows them back. Never
|
|
report them as empty because a `GET` did not return them.
|
|
|
|
## Blockers — where they live
|
|
|
|
A blocker is recorded in up to three places, and **an agent can write only the
|
|
first and the third**:
|
|
|
|
| Where | What it holds | Who writes it |
|
|
| --- | --- | --- |
|
|
| The tracker | the work itself — an issue labelled `release-blocker`, or `P0` when it ships broken | anyone, including an agent |
|
|
| The blockers table on privacyllc.dev | the business-facing blocker, with a severity, an owner and a resolution note | **a human, in the admin UI** |
|
|
| A check-in's `blockers` field | narrative: what is stuck, said in a timestamped note | anyone, including an agent |
|
|
|
|
The agent API has no route that creates, edits or resolves a blocker on the
|
|
site. Posting a check-in whose `blockers` field says something is stuck records
|
|
*narrative* — it does not touch the blockers table, and it does not clear
|
|
anything. An agent that reports "blocker filed" after a check-in has told the
|
|
truth about the note and a falsehood about the table.
|
|
|
|
So: **file the issue** — that is the copy the work is actually tracked in — and
|
|
when it belongs in front of a stakeholder, say so plainly and let a human enter
|
|
it. Before treating a site blocker as resolved, restate its title and status and
|
|
get explicit confirmation; the admin UI requires a resolution note that the API
|
|
cannot supply.
|
|
|
|
If the work is blocked and nothing is filed anywhere, the project simply looks
|
|
slow.
|
|
|
|
## Open and closed are not bookkeeping
|
|
|
|
Every open issue is a denominator, and not in the abstract: the percentage on
|
|
the project screen **is** closed issues over all issues in this tracker. Nothing
|
|
else produces it. That has three consequences worth stating in full:
|
|
|
|
- **An issue left open after the work is done** understates the project
|
|
permanently, and the understatement compounds — a fortnight of finished work
|
|
with unclosed issues reads as a fortnight of no progress.
|
|
- **An issue closed without evidence** cannot be reopened with confidence,
|
|
because nothing in it says what "fixed" meant. That is why the close comment
|
|
carries the path, symbol, test or command.
|
|
- **Invented future work** makes every percentage wrong, permanently and in one
|
|
direction. Do not pad the tracker. If the real answer is one milestone and
|
|
three issues, file exactly that.
|
|
|
|
Milestones are the same argument at batch scale, and they are counted the same
|
|
way: milestones closed over milestones total is the second figure on the project
|
|
screen. Closing the last issue under a milestone does not close the milestone,
|
|
so a tracker full of complete-but-open batches reports a project as less
|
|
finished than it is — and cannot answer "what shipped".
|
|
|
|
**File every issue into a milestone.** One filed outside still counts against
|
|
the headline percentage while being invisible to the milestone figure, which is
|
|
how two readings of the same project come to describe different amounts of work.
|
|
The site measures the gap rather than ignoring it.
|
|
|
|
One trap that costs an afternoon, and it is about a *card* rather than a figure:
|
|
the Milestones list on privacyllc.dev reads the Command Center's own table,
|
|
which only an admin can write. A repository whose milestones are being counted
|
|
in the figure above can still show *"No milestones have been added yet"* in that
|
|
list. It is not a sync failure and no amount of reconciling changes it.
|
|
|
|
## Docs travel with the push
|
|
|
|
The Command Center reads this repository's documents at a commit, and stores the
|
|
SHA it read them from. When that SHA falls behind the repository's newest
|
|
commit, the docs report is marked **stale** — not wrong, not missing, *stale*,
|
|
which is the honest description of a document that was accurate at a commit
|
|
nobody is running any more.
|
|
|
|
Two ways to produce it, and both are ordinary carelessness rather than bad luck:
|
|
|
|
- **Code pushed, documents not updated.** The report is recomputed at the new
|
|
SHA against prose describing the old behaviour. Nothing flags this; the
|
|
document is simply confidently wrong now, and its `Last reviewed` line still
|
|
looks recent.
|
|
- **Documents updated, not pushed.** The site keeps reporting the old ones. A
|
|
correction that exists only on your machine has not been made.
|
|
|
|
Hence step 4's insistence that documentation edits ride in the same commit as
|
|
the change that caused them. It is not tidiness — a doc commit that comes "after
|
|
this next thing" is the commit that does not get written, and the manual's
|
|
migration table in the project this template came from sat six migrations behind
|
|
before anybody noticed. Every reader in between trusted it.
|
|
|
|
## What the Command Center reads, and who writes it
|
|
|
|
Four independent channels, and **only two of them are automatic**:
|
|
|
|
| On the project screen | Source | How it gets there |
|
|
| --- | --- | --- |
|
|
| Headline % — issues closed / all issues | the repository's tracker | automatic — on reconcile, and immediately on a webhook delivery |
|
|
| Second figure — milestones closed / all milestones | the repository's **milestones** | same read, same moment |
|
|
| Milestone coverage — issues that sit in no milestone | the repository's tracker | same read |
|
|
| QA verdict — round, build SHA, overall sentence | `docs/qa/ClaudeReport.md` | push the repository, then reconcile |
|
|
| Current summary / Next action | manual fields on the project | `PATCH /agent/projects/<slug>` — nothing else writes them |
|
|
| The Milestones card, and a typed weighted plan | the Command Center's **own** milestone table | admin UI only |
|
|
| Blockers | the Command Center's **own** blockers table | admin UI only |
|
|
|
|
The first three are why steps 1 and 3 are steps: **closing an issue and closing
|
|
a milestone each move a figure a stakeholder can see, that day.** The last two
|
|
are lists rather than figures, and they are the ones an agent cannot write — a
|
|
repository whose milestones are counted in the second figure can still show
|
|
*"No milestones have been added yet"* on the card, because that card reads a
|
|
table only an admin fills in.
|
|
|
|
A repository that has not adopted the four label names is reported as *not
|
|
adopted* rather than as zero defects, and one with its tracker switched off is
|
|
reported as switched off rather than as an empty backlog. Absence is never
|
|
rendered as a measurement — which is exactly why a real backlog nobody filed
|
|
looks like nothing at all.
|
|
|
|
## The commands
|
|
|
|
The tracker is the Forgejo instance at
|
|
**[dream.scheller.ltd](https://dream.scheller.ltd)**, and steps 1 to 3 happen
|
|
there. Its credentials, the Cloudflare trap and the reason it has to be that
|
|
instance rather than any tracker are in the project README's *Where the tracker
|
|
is* — one copy, named once:
|
|
|
|
```bash
|
|
set -a; . ~/.openclaw/docker-registry.env; set +a
|
|
python3 docs/architecture/scripts/forgejo-issue.py list
|
|
python3 docs/architecture/scripts/forgejo-issue.py close 42 "Fixed in a1b2c3d; tests/foo.test.js covers it."
|
|
```
|
|
|
|
Step 7 talks to the Command Center instead:
|
|
|
|
```bash
|
|
# The token lives in this machine's credential store, never in the repository.
|
|
TOKEN="$PRIVACY_LLC_TOKEN"
|
|
BASE="https://privacyllc.dev/api/internal/v1"
|
|
AUTH="Authorization: Bearer $TOKEN"
|
|
```
|
|
|
|
**Reconcile** — re-read the tracker and the pushed documents. Do this after the
|
|
push, not before:
|
|
|
|
```bash
|
|
curl -sk -X POST -H "$AUTH" -H "Content-Type: application/json" \
|
|
-d '{"kind":"reconcile_all"}' "$BASE/agent/jobs"
|
|
```
|
|
|
|
**Summary and next action** — read the project first for its `version`, then
|
|
send a flat body carrying that version. A stale version is rejected rather than
|
|
silently overwriting somebody else's edit:
|
|
|
|
```bash
|
|
curl -sk -H "$AUTH" "$BASE/agent/projects/<slug>" # for version + state
|
|
|
|
curl -sk -X PATCH -H "$AUTH" -H "Content-Type: application/json" \
|
|
-d '{"version":<n>,"health":"on_track",
|
|
"currentSummary":"<where the project stands, in a sentence or two>",
|
|
"nextAction":"<the next concrete thing, specific enough to start>"}' \
|
|
"$BASE/agent/projects/<slug>"
|
|
```
|
|
|
|
**A check-in** — a timestamped "what changed", when there is something real to
|
|
report. `summary` is required and must say something; the API refuses an empty
|
|
"no change" update, deliberately:
|
|
|
|
```bash
|
|
curl -sk -X POST -H "$AUTH" -H "Content-Type: application/json" \
|
|
-d '{"projectId":"<slug>","health":"on_track",
|
|
"summary":"<what changed>","accomplishments":"<what landed>",
|
|
"blockers":"<what is stuck, or omit>","nextActions":"<what is next>"}' \
|
|
"$BASE/agent/updates"
|
|
```
|
|
|
|
Health is one of `on_track`, `caution`, `off_track`, `unknown`. Never invent
|
|
one, and never report progress the API did not return.
|
|
|
|
## What this file is not
|
|
|
|
- **Not the work list.** That is the tracker: milestones are batches, issues are
|
|
deliverables.
|
|
- **Not the release procedure.** That is `scripts/release.sh`
|
|
and `docs/security/SECURITY_CHECKLIST.md`.
|
|
- **Not the QA procedure.** That is `docs/qa/ClaudeQAPlan.md`, which ends in its
|
|
own version of step 7.
|
|
- **Not a place to record status.** If you are about to add "current state" or a
|
|
list of outstanding items below this line, the tracker is where it goes.
|