The human answered the report's open questions: the game-operating mirror exists (a controlled re-probe shows Gitea hides repo existence behind an auth prompt, so the anonymous negative was inconclusive -- withdrawn in F-007); component dormancy is intentional and staged (F-009 addendum); any F-002/F-003 remediation must ship an old->new Zuordnung in the proven style of commit-zuordnung-2026-08-07 (F-002).
18 KiB
REPORT.md — Neckbeard field test on the axion1337.chat management repo
Session 1 of 2, analysis only. Measured against neckbeard v0.1.1
(823a08cac6b03a47d7e2f661200a49ac6e09d38d, main, clean) as pinned in
SCOPE.md. Raw data reproducible from zero with
bash analysis/scripts/run_all.sh; 16 findings in findings/.
Executive summary
The management repo is 11 days old, holds 44 files and 86 commits, and steers five component repos plus itself. Its home-grown approach is not decayed — it is unevenly enforced. Where a tool can hold a rule, the rule holds perfectly: every one of 71 open issues has exactly one milestone and at most one status label, the WIP limit is respected, no legacy ID is reused across 23 issues, and the management repo's 161 document links contain zero broken targets. Where nothing enforces anything — prose, git refs, commit metadata, agreement between two files — the same rule set fails, and it fails in the same four ways every time.
The most consequential finding is not documentation drift. The 2026-08-07 history rewrite
set 251 commits to 12:00 UTC so that personal working hours could not be read out of the
history. That goal is met in one of six repos. 237 commits by the project's own
identities still carry real clock times, including 41 on an abandoned branch in
axion1337.chat-gitops clustered at 21:00–01:00. Two component repos were never rewritten
at all. Both hosts are private today, so nothing has leaked; the cost is that the
protection is believed to be in place and is not, so any future decision to push outward —
to GitHub, or by opening a project — would be taken on a false premise, and history once
pushed cannot be recalled. The rule's own caveat in CLAUDE.md:143 lists push times, issue
timestamps and pipelines as residual exposure, but not the git history itself, so a reader
concludes the opposite of what is true. See F-002,
F-003,
F-006.
Second: a decision that was made, executed and is already load-bearing exists in no
steering document. Milestone M5 — Härtung was created on 2026-08-09 with 14 issues moved
out of M1. roadmap.md, committed the same day, still poses it as an open question and
still prints the pre-split distribution; CLAUDE.md:98 still binds every issue to "M1–M4";
no ADR covers it, though the repo's own rules make one mandatory for process decisions. An
agent following the canonical file would silently undo the split.
See F-001.
What must survive migration is substantial and specific. The mirror topology is documented with its reasoning, its counter-argument, its rescue procedure and its single justified exception — and all six mirrors measure in sync. The rewrite mapping list verifies 251 of 251 rows against the live repositories, with zero contradictions. The repo names its own unresolved problems, files them as issues, and records a near-miss as luck rather than design. That candour is why this analysis was possible at all: every finding here is downstream of a claim precise enough to be wrong.
Bottom line for Session 2. This project already works the way neckbeard assumes. The migration's value is not new discipline but moving the existing discipline from places where only a human can check it into places where a script can. Four framework gaps stand in the way, listed below; the sharpest is that ADR-0001 solves one-repo-many-harnesses and this project is many-repos-one-ruleset.
Findings by root-cause pattern, most impactful first
Pattern B — A rule is declared repo-wide and applied to a subset
The declaration and the application live in different places, and nothing compares them.
| Finding | Impact | |
|---|---|---|
| F-002 | Anonymisation reaches 1 of 6 repos; 237 commits carry real hours | Stated privacy goal unmet while believed met; blocks any safe future push outward |
| F-003 | 5 author identities of one person survive, one malformed | Same exposure class; one person renders as 4–5 contributors |
| F-011 | 4 of 5 components have no CLAUDE.md |
The distribution channel for the rules is itself only partly applied — a plausible cause of F-002/F-003 |
| F-008 | Five components, four naming schemes | No deterministic path from display name to repo; this session had to ask |
Pattern A — A decision is executed in the tool; the documentation is not carried along
| Finding | Impact | |
|---|---|---|
| F-001 | M5 decided and populated; docs still call it open | Every new session is mis-primed by the canonical file |
| F-007 | Mirror count stated as five and six on the same day (the game-operating negative was withdrawn post-analysis — mirror exists, not anonymously readable) |
Two canonical documents assert different repo counts simultaneously |
| F-005 | Live doc routes to the tracker three docs declare dead, under an ambiguous number | A high-priority open decision is reachable only through a retired system |
| F-010 | Hand-written "Stand" labels older than their own file's last commit | Trains readers to distrust current content; gives no signal when content really is stale |
| F-017 | Prose asserts states the tracker already resolved: a closed issue called open, a "pending" decision whose premise was executed 60 lines earlier | Sentences a reader would act on; found only by the systematic claim sweep |
Pattern C — Two backlogs, one rule
| Finding | Impact | |
|---|---|---|
| F-004 | Open next steps only in hosts/; OVERMIND-01, CFGMON-11/12/13, MATRIX-05 have no issue |
Items invisible to board, milestone, priority and refinement |
| F-009 | gitops holds half the backlog and is absent from the vision | Session-start reading mis-weights prioritisation |
Pattern D — Artifacts outlive their purpose without an owner
| Finding | Impact | |
|---|---|---|
| F-006 | 3 abandoned branches, one carrying 41 pre-rewrite commits; wiki branch is a 3-month-old parallel truth |
Undoes the rewrite for 42 commits; two truths about the same docs |
| F-012 | 6 unresolvable SHA citations, all benign — but nothing could check them | Evidence-by-citation depends entirely on human diligence at rewrite time |
What works and must be preserved
| Finding | Why it must survive | |
|---|---|---|
| F-014 | Milestone duty 100%, one status label 100%, WIP limit held, no ID reuse, 0 broken links | Proof the team already works the way neckbeard assumes |
| F-013 | All six mirrors in sync; decision recorded with reason, counter-argument, rescue path, one bounded exception | The form is the value: this is an ADR in all but frontmatter |
| F-015 | 251/251 mapping rows verified, 0 contradictions; near-miss recorded as luck | Shows a destructive operation made auditable by hand |
| F-016 | Known problems named and filed; "zwei Wahrheiten … schlimmer als eine unvollständige" | Falsifiable claims are what made this analysis possible |
Pattern → neckbeard mechanism → migration implication
| Pattern | Neckbeard mechanism (v0.1.1) | Implication for Session 2 |
|---|---|---|
| B — rule declared repo-wide, applied to a subset | Largely a gap. ADR-0001 (docs/adr/0001-agents-md-canonical.md) removes per-harness duplication within one repo; schema.yaml filename patterns + validate.py ("filename does not match", "id does not match filename prefix") show the framework already holds that names must be mechanically derivable |
Decide how five repos share one AGENTS.md before anything else — vendoring copies re-creates the drift ADR-0001 rejects; a cross-repo link breaks ADR-0003 portability. Then introduce a components artifact that names each repo's canonical slug, so F-008 becomes checkable |
| A — decision executed, docs not carried along | AGENTS.md:79 + scripts/gen_status.py: STATUS.md is generated, "do not edit by hand". AGENTS.md:81: ADRs binding, "never edited, only superseded". WORKFLOW.md:128: STATUS review on the refinement agenda. WORKFLOW.md:136-138: "Contradictions are resolved or explicitly flagged — never left silently coexisting" |
Replace every hand-written count and "Stand" label with generated output. Port decisions/0001-0009 to docs/adr/ with schema.yaml frontmatter — they are already ADRs in substance. Then file the missing one for M5. |
| C — two backlogs, one rule | ADR-0002 (docs/adr/0002-in-repo-issues.md): issues as docs/issues/NNNN-slug.md, status in frontmatter, STATUS.md as index; schema.yaml:76-84 enum [open, in-progress, done, rejected] enforced by validate.py check_fields |
The biggest decision of Session 2: 71 open issues currently live in GitLab with milestones, priority:* labels and a group board. ADR-0002 Option C (repo canonical, mirrored to the forge) exists precisely for this and is the only option that does not throw away F-014's proven discipline. Do not migrate by deleting the board |
| D — artifacts outlive their purpose | Gap for refs. schema.yaml's warn_if_orphan shows "reachable from nowhere" is already an accepted reportable condition — for documents. WORKFLOW.md:122,126: refinement backlog triage and wiki lint |
Add a branch/ref hygiene step to the refinement ritual, and a SHA-resolution check (analysis/scripts/inv_shas.py is a working reference implementation) |
Neckbeard gaps this field test exposed
Listed only, not filed as issues in the neckbeard repo — that is a separate act.
- Many repos, one ruleset. ADR-0001 decides one-repo-many-harnesses. Nothing says how
a five-component project shares a governing
AGENTS.mdwithout either vendoring copies (the drift ADR-0001 rejects) or cross-repo links (which ADR-0003 portability disallows). Sharpest gap found. → F-011 - No components artifact. No artifact type declares "these are the repos and these are
their canonical names", so slug drift and cross-repo status are unrepresentable.
gen_status.pycovers one repo. → F-008, F-009 - No milestone or delivery-bucket concept.
schema.yamlhas no field grouping issues by what they pay into. This project uses milestones on 100% of open issues. → F-001 validate.pydoes not resolve commit SHAs cited in prose.check_body_linkscovers markdown link targets only. Resolving a cited SHA is a textbook deterministic job underAGENTS.md:101-103. → F-012- No git-level hygiene at all — commit metadata, author identity, branch lifetime are outside the framework's field of view, while in this project they carry its most sensitive claims. → F-002, F-003, F-006
- External link targets are never checked. A document pointing at a retired external tracker stays green. → F-005
- Field-test evidence on a deliberately rejected idea. The creation AAR lists "priority
field on issues (YAGNI, revisit via refinement)" among ideas not adopted. This project
carries
priority:*on 101 of 111 issues and treats it as distinct from the milestone ("priority:*sagt wie dringend, der Meilenstein sagt worauf es einzahlt",CLAUDE.md:99-101). Recorded as evidence for the refinement that ADR-flagged revisit, not re-proposed here. → F-014
Appendix — the systematic claim verification
analysis/scripts/verify_claims.py gave every one of the 813 extracted claim rows a
mechanical disposition (analysis/data/claims_verification.tsv): 205 checked-ok
(a path, issue reference or state assertion verified against tree or tracker),
207 informational (tokens classed as runtime/net/image/forge references — correctly
outside the analysed trees), 360 prose-or-runtime (no mechanically checkable token;
their semantic truth remains unchecked, stated as a limit, not passed silently),
13 in code blocks, 28 flagged for hand adjudication.
The 28 flags resolve as: 10 references into out-of-scope repos (homelab/wiki,
wiki-bookstack, vendor, the retired gitops wiki) — consistent with their own context;
7 host/runtime artifacts that correctly are not in any tree (lab.conf,
runner-data/, an untracked .npmrc the doc itself calls untracked, npm tarball
contents); 3 historically removed files whose removal the surrounding text records;
2 enumerations of a hypothetical revert, not claims; 1 tokenizer artifact
(text/html); 3 bare/ambiguous issue references; 2 genuine drift → F-017.
Bonus verification: all of roadmap.md's gitops references (#25, #45, #46, #47, #48,
#49) match their GitLab titles — post-migration references are consistently
GitLab-numbered, strengthening F-014.
Open questions for the human
- Where do the 71 open issues go? ADR-0002 Option C (repo canonical, mirrored to GitLab) preserves the board, the milestones and the labels that F-014 shows are working. Pure Option B is cleaner and loses all three. This decides the shape of Session 2.
- F-002/F-003 are a live exposure, not a documentation defect. Do you want the remediation treated as an incident now — separately from and ahead of the migration? This session recorded it and changed nothing, per mandate.
game-operatingmirror: is it absent, or does it mirror under a name other thansorb/game-operating? The negative result rests on the naming convention.- Are
thread-net-git(4 files) andthreadnet-operating(0 issues, 7 days idle) dormant by design? If yes, the vision document should say so; if no, they are under-tracked. Either way the docs currently imply five equal product lines. - The M5 ADR — file it as ADR-0010 in the current scheme now, or let it land as the
first ADR in the migrated
docs/adr/?
Answers received at session close (2026-08-10)
- (Issue location) — deferred to Session 2, as proposed.
- (F-002/F-003 remediation) — binding constraint recorded: any history rewrite must
ship an old→new Zuordnung in the style of
shared/commit-zuordnung-2026-08-07.md(the pattern F-015 verified). Timing remains with the human / Session 2. - (game-operating mirror) — exists, per the human; the anonymous negative was withdrawn as inconclusive (Gitea hides existence behind an auth prompt — see F-007 addendum). Not ThreadNet-related beyond planned monitoring inclusion.
- (Dormant components) — intentional and staged: base feature set first, then monitoring and security build-out; deliberately not getting lost in polish. Recorded in the F-009 addendum; no repo document states it yet.
- (M5 ADR) — drafted as
analysis/drafts/0010-haertung-eigener-meilenstein.md; placed on localmainasdecisions/0010-haertung-eigener-meilenstein.md(banner stripped) at session close. Push ofmainpending; the draft stays in the analysis record as the field-test paper trail.
Non-goals — what this analysis deliberately did not examine
- No design doc in the target repo. Deliberate deviation from
WORKFLOW.mdsize-L Gates 1–5: the migration design belongs to Session 2. Analysis precedes adoption. - Gate 0 suspended.
PROJECT.mdis absent from the management repo, which underAGENTS.md:57-63would be the init trigger. Suspended by the session mandate; recorded as an observation, not a task. - Component code read structurally only — trees, manifests, CI files, entry points. No depth reading; no finding here required it.
- Upstream fork history not analysed as project drift.
threadnet-callandThreadNet-Webcarry thousands of Element/Matrix commits and 538 of the 543 TODO/FIXME/HACK markers found. Those are inherited, not steering artifacts. The management repo itself contains 0 markers — checked, no drift found. - Issue descriptions and comments were not exported.
gitlab_issues.jsonholds metadata only, by design. Claims made inside issue bodies are therefore unverified — including the migration footnotesCLAUDE.md:52says are authoritative for shifted gitops numbers. - Out-of-scope repos —
game-operating,gameserver, thevendorandArchivsubgroups — analysed only where a management-repo claim referred to them. Their contents were not examined. - The
homelabgroup (docs,wiki,wiki-bookstack) and axionwiki.lab were not examined; cross-references to them are recorded aspoints-outside-scopeinlinks.tsv. - CI behaviour was not exercised, only configuration presence (e.g.
canonize_rotationverified to exist at.gitlab-ci.yml:51in gitops; not observed running). - The human's own working copy could not be inspected. The human confirmed at the Phase-0 STOP that it points at git.lab.
- Nothing was fixed. No file outside
analysis/was modified;inv_repo.pyaborts the run if any was, and the guard was tested by deliberately dirtyingREADME.md.