Files
TSYSGroupAIOS/PATTERNS.md
T
mrcharles f5292183f4 refactor: remove Makefile, restructure as knowledge-first framework
The primary value is the knowledge layer (markdown files that any agent
reads — Crush, OpenWebUI, Hermes, Conduit on iPhone). CLI tooling
(scripts, git hooks) is optional, for projects that use git/docker.

Changes:
- Remove Makefile entirely. All commands are now direct script invocations
  (bash scripts/check-rules.sh, bash scripts/setup-hooks.sh, etc.)
- Add scripts/test.sh stub (replaces make test)
- check-rules.sh: test-suite check now calls scripts/test.sh, not make test
- Rewrite README as three-layer architecture: knowledge → git hooks → docker
- Update all docs (AGENTS.md, BASELINE-PROMPT.md, ADOPTING.md, PATTERNS.md,
  STATUS.md) to remove every make reference

The framework now works for:
- CLI/harness users (git hooks + scripts + AGENTS.md)
- Non-CLI users (BASELINE-PROMPT.md loaded into any agent's system prompt)

💘 Generated with Crush

Assisted-by: Crush via Crush <crush@charm.land>
2026-08-07 12:14:30 -05:00

16 KiB
Raw Blame History

Cross-Project Pattern Extraction

Scope: 18 projects surveyed across two machines:

  • Local (ultix-streaming): 12 infra/stack projects — dotfiles, EngineeringWorkstation, EngStack, football, hermes-rceo-streaming, KNEL-AIMiddleware, KNELIAC, netbird, PFVCluster, TSYSDevStack-SupportStack-Cloudron, WorkstationStack, TSYSDevStack-SupportStack-LocalWorkstation.
  • Remote (ultix-offstage): 6 personal/business projects — CharlesNWybleResume, rceo-automation-espanso-private, RCEO-PersonalAssistant, ReachableCEO-Profile-FullTimeEmployment, RevGen-TimeForMoney, ThreeYearPlan.

This document records the patterns that recur, the inconsistencies between them, and the decisions the repo makes to drive inconsistency to zero.


1. AGENTS.md — recurring structure

A canonical section set emerges from the 12 files that have one (8 local + 4 remote):

Section Prevalence
Git commit & push policy 12/12
Project overview / context 11/12
Key commands / build cheat sheet 10/12
Repository layout (ASCII tree) 9/12
Status / journal maintenance 9/12
Conventions & naming 8/12
DO / DON'T 7/12
Validation / testing 7/12
Key files reference 6/12
Quick start / onboarding 5/12

Decision: the template's AGENTS.md ships all ten sections in a fixed order, so every project has the same skeleton. Filler is bracketed for replacement.


2. Shared cross-project preferences (the house style)

These recur strongly and are baked into the template:

  1. Auto-commit + push is mandatory and non-negotiable. Stated with ALL-CAPS force in nearly every file. The template states the override-once and lets the hooks enforce it.
  2. Atomic commits — one logical change per commit. Universal.
  3. Conventional-commit format (feat:/fix:/docs:/…). Universal, but the 💘 Crush attribution footer is inconsistent: mandated only by football and KNELIAC; absent on the remote entirely. Decision: the template mandates the footer once, in the AGENTS.md commit block.
  4. Docker-only host hygiene. The single most consistent convention across both machines (KNEL-AIMiddleware, EngStack, LocalWorkstation, RCEO-PersonalAssistant, ThreeYearPlan, CharlesNWybleResume). Decision: the template's check-rules.sh enforces host hygiene via the Docker-only rule (no :latest tags, container naming) and scripts/docker-run.sh provides the canonical container wrapper. The Crush-specific enforce-bash.sh hook was removed for harness portability; the policy lives in AGENTS.md prose.
  5. Sub-agents encouraged. Explicit in football, ThreeYearPlan, RCEO-PersonalAssistant. Decision: standard section in the template.
  6. No secrets in git (infra genre). Inverted on the remote private repos (RCEO-PersonalAssistant deliberately commits credentials). Decision: the template keeps the infra stance (.env gitignored) as the default; private repos may opt out.

Inconsistencies the template resolves:

  • shellcheck is mandated by PFVCluster and football but unmentioned elsewhere → the template mandates it for all shell, via Docker.
  • "Keep the host clean" is phrased four different ways → one canonical phrasing.
  • Auto-commit override language varies in strength → stated once, authoritatively.

3. Git hooks — the biggest gap, now standardized

Finding: custom git hooks are essentially unused. Only 3 of 18 projects have any:

Project Hook Mechanism Installer
football pre-commit (4-check SDLC gate: shellcheck, unit tests, coverage, doc-sync) core.hooksPath githooks/ scripts/setup-githooks.sh
KNEL-AIMiddleware pre-push (block on dirty tree) core.hooksPath .githooks/ none (manual git config)
RCEO-PersonalAssistant pre-commit (fast audit) + pre-push (full Docker tests) copy into .git/hooks/ scripts/setup-hooks.sh

Three different install mechanisms; one project has no installer at all.

Decision: the template uses the copy approach (most portable: works on any clone, no config mutation, idempotent) with a single scripts/setup-hooks.sh, and combines both policy philosophies:

  • pre-commit = fast audit with a hot-path bypass for STATUS.md / JOURNAL.md / WORKING.md (so frequent status commits stay frictionless) — proven in RCEO.
  • pre-push = full audit (incl. scripts/test.sh) — proven in RCEO — plus the dirty-tree gate — proven in KNEL-AIMiddleware.

4. Crush hooks — an entirely untapped capability (except one project)

Finding: Crush hooks are used by exactly one projectRCEO-PersonalAssistant. Every other crush.json (and most projects have none) defines only lsp/mcp/options, never hooks. All process enforcement elsewhere is prose in AGENTS.md — manually enforced, violable.

RCEO's crush.json wires five PreToolUse hooks that form a behavioral guardrail layer complementing the git hooks:

Hook Matcher Effect
block-todos.sh ^todos$ bans the todos tool; WORKING.md is the only tracker
enforce-bash.sh ^bash$ blocks banned commands + host language toolchains
enforce-rules.sh ^(edit|write|multiedit)$ blocks banned file types; TDD reminder on source edits
audit-before-git.sh ^bash$ runs the fast audit before any git commit/git push
exit-protocol.sh .* blocks stopping while WORKING.md has unchecked tasks

Decision: the Crush hooks were studied as the proof-of-concept and their policies (ban todos, Docker-only, banned file types, audit before git, exit protocol) were ported into AGENTS.md prose and check-rules.sh mechanical checks. The harness-specific crush.json + hooks/ layer was deliberately removed for portability — the user is shifting away from Crush to OpenWebUI/Hermes, so all enforcement is git hooks + prose only.


5. The rules engine — check-rules.sh

RCO's check-rules.sh is the best reusable artifact found. Its core abstractions:

  • A check() accumulator classifying each rule as pass / warn / fail, with FAIL > 0 ⇒ exit 1 and WARN non-fatal.
  • A --fast mode (used by pre-commit) that silences per-check output and skips slow checks.
  • Self-checking categories: shellcheck, Docker image pinning (no :latest), required-files manifest, doc freshness (STATUS.md/JOURNAL.md touched today), git state, hooks-installed, WORKING.md completion, unresolved CNW: markers.

Decision: the template's check-rules.sh generalizes this — language-specific checks (Go test coverage, gofmt) are dropped or made opt-in via PROJECT_* env; universal checks (shellcheck, image pinning, required files, doc freshness, hygiene, WORKING.md, CNW markers, merge-conflict markers) are kept. The check() accumulator and --fast/--quiet flags move into scripts/lib/common.sh so any script can reuse them.


6. Scripts — driving the shebang/boilerplate chaos to zero

Findings:

  • Three incompatible shebang variants across projects: #!/usr/bin/env bash (best), #!/bin/bash, #!/usr/bin/bash (non-portable).
  • Four different set-flag policies: set -euo pipefail (best), set -e only, set -uo pipefail, none. KNEL-AIMiddleware uses set -e only — piped failures silently swallowed; BuildAll.sh's docker compose … | tail can report green on failure.
  • The ANSI color block is copy-pasted into ~10 scripts.
  • log_* helpers are redefined per project (and per-script in KNEL-AIMiddleware, where they aren't even functions).
  • Repo-root resolution is re-rolled in nearly every script.
  • No shared cross-project library exists. Only EngStack factors helpers (scripts/lib.sh build-time + lib/common.sh runtime).

Decision: scripts/lib/common.sh provides the deduplicated primitives once: ANSI colors, log_info/ok/warn/error/step, have(), die(), repo_root(), as_root(), docker_run(), and the init_counters/check/print_summary_and_exit audit helpers. All template scripts use #!/usr/bin/env bash + set -euo pipefail.


7. Task runners — five conventions, standardized to one

Findings: no Makefile/Taskfile/justfile exists anywhere. Five incompatible conventions for the same semantic verbs:

Project Convention
football ./run.sh <subcommand>
KNEL-AIMiddleware scripts/<Verb>.sh
EngStack scripts/<verb>-<noun>.sh
PFVCluster tests/<name>.sh
hermes-agent npm workspace scripts

The recurring semantic targets — build, test, lint, validate, status, clean, setup — map cleanly onto one target set that doesn't exist.

Decision: a single Makefile provides setup, validate, fast, lint, test, status, clean, help. It is pure dispatch to scripts/; projects override test/clean for their stack. CI, hooks, and humans now share one set of verbs.


8. CI — present in exactly one project

Only hermes-agent has CI (22 GitHub Actions workflows — an exemplar: change-detection orchestrator, reusable-workflow lanes, SHA-pinned actions, supply-chain/OSV scans, live PR-comment bot). The other 17 have none.

Decision: the template doesn't ship CI (it's stack-dependent), but scripts/check-rules.sh + scripts/garden.sh give any future workflow a uniform entry point. The hermes-agent ci.yml orchestrator is the documented growth path.


9. Crush configuration layers — documented but unused

Crush defines a priority chain ($HOME/.config/crush/crush.jsoncrush.json.crush.json). In practice:

  • The global config (dotfiles) is trivial (attribution style only) — no shared LSP/MCP baseline.
  • Only 2 projects have a project-local crush.json (KNEL-AIMiddleware: 4 LSP + 36 MCP via wrappers; RCEO-PersonalAssistant: hooks only).
  • The highest-priority .crush.json layer is unused anywhere.
  • No project sets model or provider in config.

Decision: no Crush config is shipped. The hooks layer was removed for harness portability. LSP/MCP remain project-local concerns.


10. Crush memory — a singleton, now a template

Only PFVCluster has operational memory (.crush/memory/operational.md). Its format — Identity → Tracking Systems (with READY/PARTIAL/BLOCKED status) → Tooling → Access chokepoints → Key commands → Mandatory rules → Credential TODOs — is strong and reusable.

Decision: the template ships .crush/memory/operational.md as a fill-in skeleton (optional, for projects using Crush).


11. KNEL-AIMiddleware wrapper ecosystem — a standardization opportunity (not in the template)

KNEL-AIMiddleware hand-maintains 38 near-identical wrapper scripts (mcp-*-wrapper.sh, lsp-*-wrapper.sh) for its MCP/LSP fleet. ~90% of each file is duplicated boilerplate (container-cleanup stanza, docker run -i --rm --name, env passthrough). Drift is already visible (default style, double-passed creds, one structurally-different LSP wrapper). There is no generator; they were hand-cloned by an agent over many sessions.

Recommendation (out of scope for the template): replace the 38 files with one parameterized launcher driven by a declarative servers.yaml manifest, plus a gen-wrappers.sh. The template's docker-run.sh + lib/common.sh show the direction; the same idea applies at fleet scale.


12. Workflow documents — WORKING.md / STATUS.md / JOURNAL.md

The remote personal genre contributes a discipline absent from infra: a task/state/document triad enforced by hooks:

  • WORKING.md — the only task tracker (todos tool banned); commits blocked while - [ ] remain; cleared before responding.
  • STATUS.md — agent-maintained dashboard humans read; staleness is a warning.
  • JOURNAL.md — append-only ADR/pattern log; no today-entry is a warning.
  • CNW: markers — flag unresolved questions for the human; empty markers are a warning.

Decision: all four are in the template, and check-rules.sh enforces their freshness/completion.


Standardization scorecard

Inconsistency Was Now
Shebangs 3 variants #!/usr/bin/env bash
set flags 4 policies set -euo pipefail
Color/log boilerplate copy-pasted ~10× lib/common.sh
Task runner 5 conventions one Makefile
Git hook install 3 mechanisms, 1 missing one setup-hooks.sh (copy)
Git hook coverage 3/18 projects every project, two hooks
Crush hooks 1/18 projects not used (harness-agnostic; git hooks only)
Rules engine 1 project (Go-specific) generalized, project-agnostic
Crush memory 1 project skeleton in template (optional, Crush-only)
AGENTS.md structure bespoke per project canonical 10-section skeleton
💘 commit footer 2/18 projects mandated in template (harness-agnostic)

13. Global baseline prompt integration

After the initial extraction, the owner shared a draft "global baseline prompt" (an Apple Note of operating observations gathered over weeks of working with agents). It encodes principles that cut across every project and that the template now reflects. The cleaned canonical version lives in BASELINE-PROMPT.md; the project-level specialization is in AGENTS.md. New artifacts and checks added:

New policy encoded

Principle (baseline §) How the template enforces it
Stop over-thinking; ask early (§1, §9) questions-v1.md skeleton + AGENTS.md "Questions" section; required-files check fails if absent
Token efficiency / farm to tooling (§2) scripts/check-rules.sh runs shellcheck in Docker; AGENTS.md "Working Style" forbids parsing huge code in context
Redmine = SoR for work; Discourse = SoR for docs (§3) AGENTS.md "Systems of Record" section; scripts/garden.sh flags oversized non-Discourse .md
Git .md = stubs to Discourse (§3) scripts/garden.sh reports oversized .md lacking a Discourse URL
tea CLI for PRs; off-workstation → PR (§4) AGENTS.md "Git Workflow" policy
Shift-left CI/CD, lockstep local + hosted (§5) AGENTS.md "CI/CD" section; scripts/check-rules.sh --fast runs at pre-commit
Docker/k8s for everything; container naming (§6) new container-naming rule in check-rules.sh (every compose service needs container_name); docker-compose.yml.example + scripts/up.sh / scripts/down.sh
STATUS.md = scratchpad, not SoR; has Inbox (§8) STATUS.md reframed; Inbox section for mid-task interruptions ("don't pivot")
Questions file (§9) questions-v1.md artifact + required-files check
Belt-and-suspenders enforcement (§10) already present (git hooks + Crush hooks) — now documented as policy
Gardening loop (§11) scripts/garden.sh
Sub-agents as subcontractors (§12) AGENTS.md "Working Style"
TDD + linters (§13) AGENTS.md "TDD & Linting"; enforce-rules.sh TDD reminder (opt-in via PROJECT_SOURCE_SUFFIXES)

New template artifacts

  • BASELINE-PROMPT.md — the cleaned canonical global prompt (lives in the meta root; projects inherit).
  • questions-v1.md — git-tracked question log skeleton.
  • docker-compose.yml.example — lifecycle template with project-prefix naming.
  • scripts/up.sh, scripts/down.sh — compose lifecycle wrappers.
  • scripts/garden.sh — doc-sprawl / Discourse-migration report.

New check-rules.sh checks

  • Container naming (§6): every service in a docker-compose*.y*ml must declare container_name:; failure otherwise.
  • Questions file required: questions-v1.md must exist (required-files manifest).

New Makefile targets

scripts/garden.sh, scripts/up.sh, scripts/down.sh — standard scripts across every project.

What stayed project-level (not globalized)

  • sectestbed- / preprod- VM testing semantics — IAC-workstream-specific; left as AGENTS.md prose, not a mechanical check.
  • Redmine Gantt / dependency modeling — workflow-specific.
  • Specific DNS/cloudron/SITER production details — out of scope.