feat(plan): six sections every plan must name, and the files an agent reads first
WORK_CYCLE.md covered only the end of the cycle. A cycle has two ends, and
the same six questions kept having to be asked out loud on every piece of
work. They are now mandatory in every plan, each justified by something this
household has actually paid for:
unified code eight copies of secrets.sh once existed here and five of
seven could not detect the most common secret shape --
INCLUDING THE TEMPLATE, so every project scaffolded from
it inherited a blind scanner
error handling the recurring fault is the silent pass, not the crash
logging an append-only log is unbounded by construction
blind spots named ones get fixed
landmine fixes the trap found while passing is cheapest to fix while
passing
hardcode little derive it, or justify the constant
GUARDS.md was five sections behind the project that has been learning; 11,
12 and 13 are backported, genericised to match the template's style. 13 is
the narrow form of the sixth rule, and WORK_CYCLE now cites it -- so
backporting it is what makes that citation true rather than a broken
reference.
Also adds the three files an agent reads BEFORE it reads docs/:
CLAUDE.md short, and it POINTS at DOC_TRUST_MAP rather than
repeating it -- a second copy of the map is the
failure that map exists to prevent. Carries the
exit-code table, the commit gates, and two standing
instructions: flag what looks wrong even when it is
not what you were asked about, and never print a
credential -- not from a file, not from a command's
output, not from a config subtree "with the secrets
filtered out", because that filter has failed before
by matching key NAMES while the secret sat inside an
object whose name was innocent
.claudeignore excludes artifacts and NEVER docs/. The Command
Center reads this repository's documents at a commit;
a generic ignore file that sweeps "documentation" or
"data" starves both the agent and the reconcile, and
everything still runs, just blind
.claude/settings.json deny rules in the double-slash absolute form. A
tilde-style rule looks right in review and silently
matches nothing. It closes the Read TOOL only -- a
shell reads a file a hundred ways -- so it catches
the accidental read, not the determined one
scaffold.sh gains a ROOT array for the three, kept apart from DOCS so the
H1-plus-status-block check stays meaningful rather than being loosened into
a warning that is always wrong (GUARDS.md 5).
Verified: scaffold --dry-run into a scratch repo creates 22 files including
all three, with no HEADERLESS warning; doc-claims passes with 124 claimed
paths, all present.
Does not touch docs/architecture/scripts/secrets.sh, which carries someone
else's uncommitted improvement.
2026-09-01 21:44:00 -05:00
# The work cycle — what a plan must name, and what must be true at the end
chore(repo): put the template under version control
The basis for every project here was itself unversioned: no .git, no remote,
no history. Changes to it had no diff and no revert, and two of its own guards
could not run at all -- doc-claims.sh and doc-triggers.py both read git
history, so the script written to catch documentation drift could not be run
against the documents that define drift.
This is the tree as it stands, including work that until now existed only as
loose files on disk: WORK_CYCLE.md, TOOLS.md, the Portainer image-line fix in
deploy.py, the status vocabulary corrected to the four words the conformance
checker actually enforces, the Exempt: mechanism documented, and the Forgejo
instance named in README.md.
secrets.sh --tracked reports one candidate, migrate.sh:480. It is the comment
documenting the three Postgres credential shapes that script redacts, with
literal placeholders, and it is left alone deliberately: GUARDS.md section 2
is that a source-grep guard must tell code from the comment about code, and
deleting an explanation to quiet a scanner is the failure it names.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 22:44:26 -05:00
```
Status: Current
Owner: < who maintains this >
Last reviewed: < YYYY-MM-DD >
feat(plan): six sections every plan must name, and the files an agent reads first
WORK_CYCLE.md covered only the end of the cycle. A cycle has two ends, and
the same six questions kept having to be asked out loud on every piece of
work. They are now mandatory in every plan, each justified by something this
household has actually paid for:
unified code eight copies of secrets.sh once existed here and five of
seven could not detect the most common secret shape --
INCLUDING THE TEMPLATE, so every project scaffolded from
it inherited a blind scanner
error handling the recurring fault is the silent pass, not the crash
logging an append-only log is unbounded by construction
blind spots named ones get fixed
landmine fixes the trap found while passing is cheapest to fix while
passing
hardcode little derive it, or justify the constant
GUARDS.md was five sections behind the project that has been learning; 11,
12 and 13 are backported, genericised to match the template's style. 13 is
the narrow form of the sixth rule, and WORK_CYCLE now cites it -- so
backporting it is what makes that citation true rather than a broken
reference.
Also adds the three files an agent reads BEFORE it reads docs/:
CLAUDE.md short, and it POINTS at DOC_TRUST_MAP rather than
repeating it -- a second copy of the map is the
failure that map exists to prevent. Carries the
exit-code table, the commit gates, and two standing
instructions: flag what looks wrong even when it is
not what you were asked about, and never print a
credential -- not from a file, not from a command's
output, not from a config subtree "with the secrets
filtered out", because that filter has failed before
by matching key NAMES while the secret sat inside an
object whose name was innocent
.claudeignore excludes artifacts and NEVER docs/. The Command
Center reads this repository's documents at a commit;
a generic ignore file that sweeps "documentation" or
"data" starves both the agent and the reconcile, and
everything still runs, just blind
.claude/settings.json deny rules in the double-slash absolute form. A
tilde-style rule looks right in review and silently
matches nothing. It closes the Read TOOL only -- a
shell reads a file a hundred ways -- so it catches
the accidental read, not the determined one
scaffold.sh gains a ROOT array for the three, kept apart from DOCS so the
H1-plus-status-block check stays meaningful rather than being loosened into
a warning that is always wrong (GUARDS.md 5).
Verified: scaffold --dry-run into a scratch repo creates 22 files including
all three, with no HEADERLESS warning; doc-claims passes with 124 claimed
paths, all present.
Does not touch docs/architecture/scripts/secrets.sh, which carries someone
else's uncommitted improvement.
2026-09-01 21:44:00 -05:00
Governs: what every plan must name before work starts, and what must be true
before that work counts as finished
chore(repo): put the template under version control
The basis for every project here was itself unversioned: no .git, no remote,
no history. Changes to it had no diff and no revert, and two of its own guards
could not run at all -- doc-claims.sh and doc-triggers.py both read git
history, so the script written to catch documentation drift could not be run
against the documents that define drift.
This is the tree as it stands, including work that until now existed only as
loose files on disk: WORK_CYCLE.md, TOOLS.md, the Portainer image-line fix in
deploy.py, the status vocabulary corrected to the four words the conformance
checker actually enforces, the Exempt: mechanism documented, and the Forgejo
instance named in README.md.
secrets.sh --tracked reports one candidate, migrate.sh:480. It is the comment
documenting the three Postgres credential shapes that script redacts, with
literal placeholders, and it is left alone deliberately: GUARDS.md section 2
is that a source-grep guard must tell code from the comment about code, and
deleting an explanation to quiet a scanner is the failure it names.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 22:44:26 -05:00
Review trigger: Any change to what the Command Center reads, or to which of
feat(plan): six sections every plan must name, and the files an agent reads first
WORK_CYCLE.md covered only the end of the cycle. A cycle has two ends, and
the same six questions kept having to be asked out loud on every piece of
work. They are now mandatory in every plan, each justified by something this
household has actually paid for:
unified code eight copies of secrets.sh once existed here and five of
seven could not detect the most common secret shape --
INCLUDING THE TEMPLATE, so every project scaffolded from
it inherited a blind scanner
error handling the recurring fault is the silent pass, not the crash
logging an append-only log is unbounded by construction
blind spots named ones get fixed
landmine fixes the trap found while passing is cheapest to fix while
passing
hardcode little derive it, or justify the constant
GUARDS.md was five sections behind the project that has been learning; 11,
12 and 13 are backported, genericised to match the template's style. 13 is
the narrow form of the sixth rule, and WORK_CYCLE now cites it -- so
backporting it is what makes that citation true rather than a broken
reference.
Also adds the three files an agent reads BEFORE it reads docs/:
CLAUDE.md short, and it POINTS at DOC_TRUST_MAP rather than
repeating it -- a second copy of the map is the
failure that map exists to prevent. Carries the
exit-code table, the commit gates, and two standing
instructions: flag what looks wrong even when it is
not what you were asked about, and never print a
credential -- not from a file, not from a command's
output, not from a config subtree "with the secrets
filtered out", because that filter has failed before
by matching key NAMES while the secret sat inside an
object whose name was innocent
.claudeignore excludes artifacts and NEVER docs/. The Command
Center reads this repository's documents at a commit;
a generic ignore file that sweeps "documentation" or
"data" starves both the agent and the reconcile, and
everything still runs, just blind
.claude/settings.json deny rules in the double-slash absolute form. A
tilde-style rule looks right in review and silently
matches nothing. It closes the Read TOOL only -- a
shell reads a file a hundred ways -- so it catches
the accidental read, not the determined one
scaffold.sh gains a ROOT array for the three, kept apart from DOCS so the
H1-plus-status-block check stays meaningful rather than being loosened into
a warning that is always wrong (GUARDS.md 5).
Verified: scaffold --dry-run into a scratch repo creates 22 files including
all three, with no HEADERLESS warning; doc-claims passes with 124 claimed
paths, all present.
Does not touch docs/architecture/scripts/secrets.sh, which carries someone
else's uncommitted improvement.
2026-09-01 21:44:00 -05:00
those channels a person rather than an agent has to write; any
change to what a plan is required to contain
chore(repo): put the template under version control
The basis for every project here was itself unversioned: no .git, no remote,
no history. Changes to it had no diff and no revert, and two of its own guards
could not run at all -- doc-claims.sh and doc-triggers.py both read git
history, so the script written to catch documentation drift could not be run
against the documents that define drift.
This is the tree as it stands, including work that until now existed only as
loose files on disk: WORK_CYCLE.md, TOOLS.md, the Portainer image-line fix in
deploy.py, the status vocabulary corrected to the four words the conformance
checker actually enforces, the Exempt: mechanism documented, and the Forgejo
instance named in README.md.
secrets.sh --tracked reports one candidate, migrate.sh:480. It is the comment
documenting the three Postgres credential shapes that script redacts, with
literal placeholders, and it is left alone deliberately: GUARDS.md section 2
is that a source-grep guard must tell code from the comment about code, and
deleting an explanation to quiet a scanner is the failure it names.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 22:44:26 -05:00
```
> **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.
feat(plan): six sections every plan must name, and the files an agent reads first
WORK_CYCLE.md covered only the end of the cycle. A cycle has two ends, and
the same six questions kept having to be asked out loud on every piece of
work. They are now mandatory in every plan, each justified by something this
household has actually paid for:
unified code eight copies of secrets.sh once existed here and five of
seven could not detect the most common secret shape --
INCLUDING THE TEMPLATE, so every project scaffolded from
it inherited a blind scanner
error handling the recurring fault is the silent pass, not the crash
logging an append-only log is unbounded by construction
blind spots named ones get fixed
landmine fixes the trap found while passing is cheapest to fix while
passing
hardcode little derive it, or justify the constant
GUARDS.md was five sections behind the project that has been learning; 11,
12 and 13 are backported, genericised to match the template's style. 13 is
the narrow form of the sixth rule, and WORK_CYCLE now cites it -- so
backporting it is what makes that citation true rather than a broken
reference.
Also adds the three files an agent reads BEFORE it reads docs/:
CLAUDE.md short, and it POINTS at DOC_TRUST_MAP rather than
repeating it -- a second copy of the map is the
failure that map exists to prevent. Carries the
exit-code table, the commit gates, and two standing
instructions: flag what looks wrong even when it is
not what you were asked about, and never print a
credential -- not from a file, not from a command's
output, not from a config subtree "with the secrets
filtered out", because that filter has failed before
by matching key NAMES while the secret sat inside an
object whose name was innocent
.claudeignore excludes artifacts and NEVER docs/. The Command
Center reads this repository's documents at a commit;
a generic ignore file that sweeps "documentation" or
"data" starves both the agent and the reconcile, and
everything still runs, just blind
.claude/settings.json deny rules in the double-slash absolute form. A
tilde-style rule looks right in review and silently
matches nothing. It closes the Read TOOL only -- a
shell reads a file a hundred ways -- so it catches
the accidental read, not the determined one
scaffold.sh gains a ROOT array for the three, kept apart from DOCS so the
H1-plus-status-block check stays meaningful rather than being loosened into
a warning that is always wrong (GUARDS.md 5).
Verified: scaffold --dry-run into a scratch repo creates 22 files including
all three, with no HEADERLESS warning; doc-claims passes with 124 claimed
paths, all present.
Does not touch docs/architecture/scripts/secrets.sh, which carries someone
else's uncommitted improvement.
2026-09-01 21:44:00 -05:00
## Before you start — what every plan must name
A cycle has two ends. These six are **mandatory in every plan** , and each one is
here because its absence has cost this household something real.
| Section | The question it answers | Why it is mandatory |
| --- | --- | --- |
| **Unified code** | What already exists that this should use instead of a new copy? | Eight copies of `secrets.sh` once existed here and five of seven could not detect the most common secret shape — *including the template* , so every project scaffolded from it inherited a blind scanner |
| **Error handling** | What happens when each step fails, and can the failure be told from success? | The recurring fault is not the crash but the **silent pass** : a wrapper that swallowed every job's output, a check that could not run reading as clean, an alert path that posted successfully to nobody |
| **Logging** | What is written, who reads it, and what bounds it? | An append-only log is unbounded by construction. The moment it matters is the moment it is already a problem |
| **Blind spots** | What would this change make invisible? | Named ones get fixed. Every serious defect found here recently was found by asking what would *not* be visible, not by looking where the work was |
| **Roll in landmine fixes** | What did you trip over on the way, and is it fixed or explicitly deferred? | The trap found while passing is cheapest to fix while passing. A known bug that ships is a decision, and it is never yours to make silently |
| **Hardcode as little as possible** | Where is the authority for each value, and why is this a copy of it? | See below |
None of these is a heading to fill in. A plan that says "Error handling: yes" has
answered nothing; the section exists to make you name the failure and say what
happens when it arrives.
### Hardcode as little as possible
**Derive it, or justify the constant.** A value copied from somewhere else will
drift from the thing it copied. If a list, a path, a schedule or a threshold
already exists anywhere in the system, read it from there. Ask the daemon, parse
the config, walk the crontab — do not restate it. And where a constant genuinely
must be written down, say in a comment **where the authority is** and what would
make it wrong.
`GUARDS.md` states the narrow form — *a guard that restates the list is a copy of
the list* — and it is true of everything else too, not only guards.
Two limits, so it does not become a slogan:
- **Something has to be the root.** A ledger path, a channel id, a threshold
taken from a real incident: these *are* the authority, not copies of one. The
rule is against the **second** copy.
- **Derive the input, never the assertion.** A probe that derives its own
expectation from the thing it is testing proves nothing at all.
chore(repo): put the template under version control
The basis for every project here was itself unversioned: no .git, no remote,
no history. Changes to it had no diff and no revert, and two of its own guards
could not run at all -- doc-claims.sh and doc-triggers.py both read git
history, so the script written to catch documentation drift could not be run
against the documents that define drift.
This is the tree as it stands, including work that until now existed only as
loose files on disk: WORK_CYCLE.md, TOOLS.md, the Portainer image-line fix in
deploy.py, the status vocabulary corrected to the four words the conformance
checker actually enforces, the Exempt: mechanism documented, and the Forgejo
instance named in README.md.
secrets.sh --tracked reports one candidate, migrate.sh:480. It is the comment
documenting the three Postgres credential shapes that script redacts, with
literal placeholders, and it is left alone deliberately: GUARDS.md section 2
is that a source-grep guard must tell code from the comment about code, and
deleting an explanation to quiet a scanner is the failure it names.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 22:44:26 -05:00
## 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.
2026-08-17 22:49:23 -05:00
**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.
chore(repo): put the template under version control
The basis for every project here was itself unversioned: no .git, no remote,
no history. Changes to it had no diff and no revert, and two of its own guards
could not run at all -- doc-claims.sh and doc-triggers.py both read git
history, so the script written to catch documentation drift could not be run
against the documents that define drift.
This is the tree as it stands, including work that until now existed only as
loose files on disk: WORK_CYCLE.md, TOOLS.md, the Portainer image-line fix in
deploy.py, the status vocabulary corrected to the four words the conformance
checker actually enforces, the Exempt: mechanism documented, and the Forgejo
instance named in README.md.
secrets.sh --tracked reports one candidate, migrate.sh:480. It is the comment
documenting the three Postgres credential shapes that script redacts, with
literal placeholders, and it is left alone deliberately: GUARDS.md section 2
is that a source-grep guard must tell code from the comment about code, and
deleting an explanation to quiet a scanner is the failure it names.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 22:44:26 -05:00
`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
feat(plan): six sections every plan must name, and the files an agent reads first
WORK_CYCLE.md covered only the end of the cycle. A cycle has two ends, and
the same six questions kept having to be asked out loud on every piece of
work. They are now mandatory in every plan, each justified by something this
household has actually paid for:
unified code eight copies of secrets.sh once existed here and five of
seven could not detect the most common secret shape --
INCLUDING THE TEMPLATE, so every project scaffolded from
it inherited a blind scanner
error handling the recurring fault is the silent pass, not the crash
logging an append-only log is unbounded by construction
blind spots named ones get fixed
landmine fixes the trap found while passing is cheapest to fix while
passing
hardcode little derive it, or justify the constant
GUARDS.md was five sections behind the project that has been learning; 11,
12 and 13 are backported, genericised to match the template's style. 13 is
the narrow form of the sixth rule, and WORK_CYCLE now cites it -- so
backporting it is what makes that citation true rather than a broken
reference.
Also adds the three files an agent reads BEFORE it reads docs/:
CLAUDE.md short, and it POINTS at DOC_TRUST_MAP rather than
repeating it -- a second copy of the map is the
failure that map exists to prevent. Carries the
exit-code table, the commit gates, and two standing
instructions: flag what looks wrong even when it is
not what you were asked about, and never print a
credential -- not from a file, not from a command's
output, not from a config subtree "with the secrets
filtered out", because that filter has failed before
by matching key NAMES while the secret sat inside an
object whose name was innocent
.claudeignore excludes artifacts and NEVER docs/. The Command
Center reads this repository's documents at a commit;
a generic ignore file that sweeps "documentation" or
"data" starves both the agent and the reconcile, and
everything still runs, just blind
.claude/settings.json deny rules in the double-slash absolute form. A
tilde-style rule looks right in review and silently
matches nothing. It closes the Read TOOL only -- a
shell reads a file a hundred ways -- so it catches
the accidental read, not the determined one
scaffold.sh gains a ROOT array for the three, kept apart from DOCS so the
H1-plus-status-block check stays meaningful rather than being loosened into
a warning that is always wrong (GUARDS.md 5).
Verified: scaffold --dry-run into a scratch repo creates 22 files including
all three, with no HEADERLESS warning; doc-claims passes with 124 claimed
paths, all present.
Does not touch docs/architecture/scripts/secrets.sh, which carries someone
else's uncommitted improvement.
2026-09-01 21:44:00 -05:00
Steps 1 to 3 happen in the tracker. Where it is, how to authenticate to it, the
Cloudflare trap and the reason it has to be Forgejo rather than any tracker are
in the project README's *Where the tracker is* — one copy, named once:
chore(repo): put the template under version control
The basis for every project here was itself unversioned: no .git, no remote,
no history. Changes to it had no diff and no revert, and two of its own guards
could not run at all -- doc-claims.sh and doc-triggers.py both read git
history, so the script written to catch documentation drift could not be run
against the documents that define drift.
This is the tree as it stands, including work that until now existed only as
loose files on disk: WORK_CYCLE.md, TOOLS.md, the Portainer image-line fix in
deploy.py, the status vocabulary corrected to the four words the conformance
checker actually enforces, the Exempt: mechanism documented, and the Forgejo
instance named in README.md.
secrets.sh --tracked reports one candidate, migrate.sh:480. It is the comment
documenting the three Postgres credential shapes that script redacts, with
literal placeholders, and it is left alone deliberately: GUARDS.md section 2
is that a source-grep guard must tell code from the comment about code, and
deleting an explanation to quiet a scanner is the failure it names.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 22:44:26 -05:00
```bash
feat(plan): six sections every plan must name, and the files an agent reads first
WORK_CYCLE.md covered only the end of the cycle. A cycle has two ends, and
the same six questions kept having to be asked out loud on every piece of
work. They are now mandatory in every plan, each justified by something this
household has actually paid for:
unified code eight copies of secrets.sh once existed here and five of
seven could not detect the most common secret shape --
INCLUDING THE TEMPLATE, so every project scaffolded from
it inherited a blind scanner
error handling the recurring fault is the silent pass, not the crash
logging an append-only log is unbounded by construction
blind spots named ones get fixed
landmine fixes the trap found while passing is cheapest to fix while
passing
hardcode little derive it, or justify the constant
GUARDS.md was five sections behind the project that has been learning; 11,
12 and 13 are backported, genericised to match the template's style. 13 is
the narrow form of the sixth rule, and WORK_CYCLE now cites it -- so
backporting it is what makes that citation true rather than a broken
reference.
Also adds the three files an agent reads BEFORE it reads docs/:
CLAUDE.md short, and it POINTS at DOC_TRUST_MAP rather than
repeating it -- a second copy of the map is the
failure that map exists to prevent. Carries the
exit-code table, the commit gates, and two standing
instructions: flag what looks wrong even when it is
not what you were asked about, and never print a
credential -- not from a file, not from a command's
output, not from a config subtree "with the secrets
filtered out", because that filter has failed before
by matching key NAMES while the secret sat inside an
object whose name was innocent
.claudeignore excludes artifacts and NEVER docs/. The Command
Center reads this repository's documents at a commit;
a generic ignore file that sweeps "documentation" or
"data" starves both the agent and the reconcile, and
everything still runs, just blind
.claude/settings.json deny rules in the double-slash absolute form. A
tilde-style rule looks right in review and silently
matches nothing. It closes the Read TOOL only -- a
shell reads a file a hundred ways -- so it catches
the accidental read, not the determined one
scaffold.sh gains a ROOT array for the three, kept apart from DOCS so the
H1-plus-status-block check stays meaningful rather than being loosened into
a warning that is always wrong (GUARDS.md 5).
Verified: scaffold --dry-run into a scratch repo creates 22 files including
all three, with no HEADERLESS warning; doc-claims passes with 124 claimed
paths, all present.
Does not touch docs/architecture/scripts/secrets.sh, which carries someone
else's uncommitted improvement.
2026-09-01 21:44:00 -05:00
# The tracker credentials live in this machine's credential store, never in the
# repository. Load them the way that README describes, then:
chore(repo): put the template under version control
The basis for every project here was itself unversioned: no .git, no remote,
no history. Changes to it had no diff and no revert, and two of its own guards
could not run at all -- doc-claims.sh and doc-triggers.py both read git
history, so the script written to catch documentation drift could not be run
against the documents that define drift.
This is the tree as it stands, including work that until now existed only as
loose files on disk: WORK_CYCLE.md, TOOLS.md, the Portainer image-line fix in
deploy.py, the status vocabulary corrected to the four words the conformance
checker actually enforces, the Exempt: mechanism documented, and the Forgejo
instance named in README.md.
secrets.sh --tracked reports one candidate, migrate.sh:480. It is the comment
documenting the three Postgres credential shapes that script redacts, with
literal placeholders, and it is left alone deliberately: GUARDS.md section 2
is that a source-grep guard must tell code from the comment about code, and
deleting an explanation to quiet a scanner is the failure it names.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 22:44:26 -05:00
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.
feat(plan): six sections every plan must name, and the files an agent reads first
WORK_CYCLE.md covered only the end of the cycle. A cycle has two ends, and
the same six questions kept having to be asked out loud on every piece of
work. They are now mandatory in every plan, each justified by something this
household has actually paid for:
unified code eight copies of secrets.sh once existed here and five of
seven could not detect the most common secret shape --
INCLUDING THE TEMPLATE, so every project scaffolded from
it inherited a blind scanner
error handling the recurring fault is the silent pass, not the crash
logging an append-only log is unbounded by construction
blind spots named ones get fixed
landmine fixes the trap found while passing is cheapest to fix while
passing
hardcode little derive it, or justify the constant
GUARDS.md was five sections behind the project that has been learning; 11,
12 and 13 are backported, genericised to match the template's style. 13 is
the narrow form of the sixth rule, and WORK_CYCLE now cites it -- so
backporting it is what makes that citation true rather than a broken
reference.
Also adds the three files an agent reads BEFORE it reads docs/:
CLAUDE.md short, and it POINTS at DOC_TRUST_MAP rather than
repeating it -- a second copy of the map is the
failure that map exists to prevent. Carries the
exit-code table, the commit gates, and two standing
instructions: flag what looks wrong even when it is
not what you were asked about, and never print a
credential -- not from a file, not from a command's
output, not from a config subtree "with the secrets
filtered out", because that filter has failed before
by matching key NAMES while the secret sat inside an
object whose name was innocent
.claudeignore excludes artifacts and NEVER docs/. The Command
Center reads this repository's documents at a commit;
a generic ignore file that sweeps "documentation" or
"data" starves both the agent and the reconcile, and
everything still runs, just blind
.claude/settings.json deny rules in the double-slash absolute form. A
tilde-style rule looks right in review and silently
matches nothing. It closes the Read TOOL only -- a
shell reads a file a hundred ways -- so it catches
the accidental read, not the determined one
scaffold.sh gains a ROOT array for the three, kept apart from DOCS so the
H1-plus-status-block check stays meaningful rather than being loosened into
a warning that is always wrong (GUARDS.md 5).
Verified: scaffold --dry-run into a scratch repo creates 22 files including
all three, with no HEADERLESS warning; doc-claims passes with 124 claimed
paths, all present.
Does not touch docs/architecture/scripts/secrets.sh, which carries someone
else's uncommitted improvement.
2026-09-01 21:44:00 -05:00
- **Not the release procedure.** That is `docs/architecture/scripts/release.sh`
chore(repo): put the template under version control
The basis for every project here was itself unversioned: no .git, no remote,
no history. Changes to it had no diff and no revert, and two of its own guards
could not run at all -- doc-claims.sh and doc-triggers.py both read git
history, so the script written to catch documentation drift could not be run
against the documents that define drift.
This is the tree as it stands, including work that until now existed only as
loose files on disk: WORK_CYCLE.md, TOOLS.md, the Portainer image-line fix in
deploy.py, the status vocabulary corrected to the four words the conformance
checker actually enforces, the Exempt: mechanism documented, and the Forgejo
instance named in README.md.
secrets.sh --tracked reports one candidate, migrate.sh:480. It is the comment
documenting the three Postgres credential shapes that script redacts, with
literal placeholders, and it is left alone deliberately: GUARDS.md section 2
is that a source-grep guard must tell code from the comment about code, and
deleting an explanation to quiet a scanner is the failure it names.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 22:44:26 -05:00
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.