Thanks to visit codestin.com
Credit goes to github.com

Skip to content

docs: re-init CLAUDE.md and align all four harness prompts - #2

Merged
OriNachum merged 3 commits into
mainfrom
docs/init-harness-prompts
Sep 12, 2026
Merged

docs: re-init CLAUDE.md and align all four harness prompts#2
OriNachum merged 3 commits into
mainfrom
docs/init-harness-prompts

Conversation

@OriNachum

Copy link
Copy Markdown
Contributor

What

/init replaced the scaffold seed CLAUDE.md with a runtime prompt grounded in
this repo, and the other three harness prompt files were brought in line with it —
each written for its own harness rather than restating the same text.

File Written for
CLAUDE.md a Claude Code session working on the repo (fullest write-up)
QWEN.md a Qwen Code coding session (same machinery, self-contained)
AGENTS.override.md Pi's non-coding associate lane — context only, identity stays in .pi/SYSTEM.md
AGENTS.colleague.md colleague as the /ask-colleague second mind

README.md drops the clone-and-rename-the-template instructions (this repo is
the clone) in favour of its own Status / CLI / Development sections.

Why

The scaffold left every doc describing culture-agent-template, not
substack-cli. Four concrete drifts are fixed:

  1. A domain surface that does not exist. The docs promised posts, comments,
    statistics and subscribers; no such noun groups are registered in
    _commands/. Every file now states the scaffold status explicitly, and
    AGENTS.override.md tells Pi's read-only lane to report that gap rather
    than infer an implementation from the project description.
  2. A quickstart that does not run. uv run substack-cli whoami — but
    [project.scripts] installs the binary as substack. Quickstart corrected;
    the binary-vs-prog-name mismatch is documented in all four harness files.
    Left as a doc note deliberately — picking a canonical name is a code
    change, not a docs one (see Follow-ups).
  3. Skill count 11 → 19.
  4. Three files called CLAUDE.md "the fullest write-up of the repo's
    conventions"
    and pointed at a "Cloning this template" section it did not
    contain — while CLAUDE.md was still the /init seed placeholder.

What's in CLAUDE.md now

Beyond commands: the cross-file CLI wiring that is not discoverable from any
single file — the _CliArgumentParser.error() override that keeps argparse
failures inside the error:/hint: contract, the _json_hint argv peek, the
parser_class propagation trap for nested nouns, CliError and the exit-code
policy, the strict stdout/stderr split, and the fact that tests/test_cli.py
walks known_paths() so an uncatalogued verb fails the suite. Plus a five-place
checklist for adding a Substack noun, and the _PROMPT_FILE (recognition) vs
_RESIDENT_PROMPT (health) distinction that tests/test_doctor_resident_prompt.py
pins shut.

Verification

  • uv run pytest -n auto — 117 passed, 1 skipped (the known report-only
    cross-repo gap in test_harness_registries.py)
  • uv run teken cli doctor . --strict — PASS
  • uv run python scripts/harness-smoke.py --stage config --require config — 6/6 PASS
  • python3 scripts/scan-secrets.py — clean; markdownlint-cli2 — 0 errors
  • devex pr lint — no violations; devex pr delta run (alignment-file rule):
    no sibling follow-up needed, this PR touches no vendored skill.

Behavioural check. Both interactive harnesses were asked "Who are you, and
what can you do?"
in this tree and answered from their new files — Qwen Code
named the repo by its real domain and framed the Substack verbs as work to add;
Pi answered with associate's non-coding bounds from .pi/SYSTEM.md plus the
scaffold status from AGENTS.override.md, volunteering that the Substack
surface "doesn't exist on disk yet".

ask-colleague explore was also run — but it works from a throwaway worktree at
HEAD, so it read the pre-change docs. Independently, from a cold read, it
flagged the same four drifts this PR fixes. A review of the committed diff is
running and findings will be folded in before merge.

Follow-ups (not in this PR)

  • substack vs substack-cli: decide which is canonical and align
    [project.scripts] with the argparse prog, the explain catalog, learn,
    and the tests. Documented here, not papered over.

  • whoami.py's hand-rolled culture.yaml parser stops at the first agent block
    with no warning (raised by colleague). Harmless today — this repo declares one
    agent — but worth a look before a multi-agent clone hits it.

  • substack-cli (Claude)

`/init` replaced the scaffold seed `CLAUDE.md` with a runtime prompt grounded
in this repo, and the other three harness files were brought in line with it —
each written for its own harness rather than restating the same text.

- CLAUDE.md: command block (tests, single test, every lint/rubric/smoke gate),
  the cross-file CLI wiring (`_CliArgumentParser.error()` override, the
  `_json_hint` argv peek, the `parser_class` propagation trap, `CliError`, the
  stdout/stderr split, the catalog walked by `tests/test_cli.py`), a five-place
  checklist for adding a Substack noun, and `_PROMPT_FILE` vs
  `_RESIDENT_PROMPT`.
- QWEN.md: the coding-session machinery for a Qwen Code session.
- AGENTS.override.md: context only (identity stays in `.pi/SYSTEM.md`), and
  tells Pi's non-coding lane to report the scaffold gap rather than infer an
  implementation from the project description.
- AGENTS.colleague.md: rewritten around colleague as the `/ask-colleague`
  second mind — per-verb expectations, the contracts a diff must respect, and
  the colleague#494 empty-skills caveat.
- README.md: template-clone instructions replaced by this repo's own Status /
  CLI / Development sections.

Fixes four drifts the docs carried: a Substack surface (posts, comments,
statistics, subscribers) that does not exist on disk; a quickstart using
`uv run substack-cli …` when `[project.scripts]` installs the binary as
`substack`; a skill count of 11 against 19 on disk; and three files calling
`CLAUDE.md` "the fullest write-up" while it was still the `/init` seed.

Verified: 117 tests pass, `teken cli doctor . --strict` PASS,
`harness-smoke --stage config` 6/6 PASS, scan-secrets clean, markdownlint
clean, `devex pr lint` no violations. Qwen and Pi were asked "Who are you,
and what can you do?" in this tree and both answered from their new files.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01VaCYnmwSaYL2DLxDtd1fTs
@OriNachum

Copy link
Copy Markdown
Contributor Author

/agentic_review

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Align harness prompts with substack-cli scaffold reality

📝 Documentation 🐞 Bug fix 🕐 20-40 Minutes

Grey Divider

AI Description

• Replaces scaffold seed with repository-specific Claude Code guidance and CLI contracts.
• Aligns Pi, Qwen, and colleague prompts while preserving harness-specific roles.
• Corrects scaffold status, executable name, skill count, and development documentation.
Diagram

graph TD
  ClaudeHarness["Claude / Mesh"] -->|reads| ClaudeDoc["CLAUDE.md"]
  QwenHarness["Qwen Code"] -->|reads| QwenDoc["QWEN.md"]
  PiHarness["Pi Associate"] -->|reads| PiDoc["AGENTS.override.md"]
  ColleagueHarness["Colleague"] -->|reads| ColleagueDoc["AGENTS.colleague.md"]
  QwenDoc -.->|aligned| PiDoc -.->|aligned| ColleagueDoc -.->|aligned| ClaudeDoc
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Generate prompts from shared contract data
  • ➕ Reduces manual drift in repeated CLI and harness facts
  • ➕ Allows automated validation of executable names, commands, and skill counts
  • ➖ Adds generation tooling and contributor workflow complexity
  • ➖ Makes harness-specific narrative harder to author and review
  • ➖ Generated prompts may obscure the exact runtime inputs committed to the repository
2. Use a shared AGENTS.md base
  • ➕ Centralizes common repository conventions
  • ➕ Reduces duplicated prose across harness files
  • ➖ Conflicts with Pi's override requirement
  • ➖ Not all harnesses share compatible prompt-cascade semantics
  • ➖ Risks leaking coding authority and identity instructions into non-coding lanes

Recommendation: Keep the PR's dedicated, self-contained prompt files. Their audiences, authority levels, and loader behavior differ enough that a shared base would be unsafe; existing smoke and registry checks provide reasonable drift protection. Consider generation only if repeated factual drift continues despite those checks.

Files changed (8) +629 / -208

Bug fix (1) +63 / -50
README.mdReplace template onboarding with project status and usage +63/-50

Replace template onboarding with project status and usage

• Adds explicit scaffold status, corrected quickstart commands, current CLI verbs, and expanded development checks. Removes clone-and-rename instructions and corrects the vendored skill count from 11 to 19.

README.md

Documentation (5) +532 / -124
AGENTS.colleague.mdReframe colleague as an independent second-opinion harness +109/-23

Reframe colleague as an independent second-opinion harness

• Defines expectations for review, exploration, writing, and lifecycle verbs. Documents scaffold status, CLI contracts, disposable worktrees, shared skills, and the upstream colleague skill-loading limitation.

AGENTS.colleague.md

AGENTS.override.mdGround Pi context in the repository's actual scaffold state +63/-30

Ground Pi context in the repository's actual scaffold state

• Clarifies that this file provides context rather than identity for Pi's non-coding lane. Adds the current repository layout, installed command name, output and error contracts, shared skill wiring, and guidance against inventing unimplemented Substack functionality.

AGENTS.override.md

CHANGELOG.mdDocument the 0.9.1 harness prompt refresh +15/-0

Document the 0.9.1 harness prompt refresh

• Records the prompt rewrites, README restructuring, corrected scaffold claims, executable-name fix, and updated skill count under the 0.9.1 release.

CHANGELOG.md

CLAUDE.mdReplace the bootstrap seed with full Claude Code guidance +232/-19

Replace the bootstrap seed with full Claude Code guidance

• Expands the placeholder into repository-specific guidance covering commands, CLI architecture, domain-extension steps, harness boundaries, skills, conventions, worktrees, and memory practices. Explicitly distinguishes the planned Substack surface from the checked-in scaffold.

CLAUDE.md

QWEN.mdAlign Qwen coding guidance with repository contracts +113/-52

Align Qwen coding guidance with repository contracts

• Replaces template-cloning instructions with self-contained Qwen commands, CLI architecture, extension requirements, harness registries, and current scaffold status. Documents the executable-name mismatch and shared skill-tree wiring.

QWEN.md

Other (2) +34 / -34
pyproject.tomlBump the project version to 0.9.1 +1/-1

Bump the project version to 0.9.1

• Advances the package version for the documentation release in accordance with the repository's every-PR version policy.

pyproject.toml

uv.lockSynchronize locked project metadata for version 0.9.1 +33/-33

Synchronize locked project metadata for version 0.9.1

• Updates the editable root package entry to version 0.9.1 and relocates the regenerated package block without changing dependency requirements.

uv.lock

@qodo-code-review

qodo-code-review Bot commented Sep 12, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Remediation recommended

1. Fresh setups cannot run markdown lint ✓ Resolved 🐞 Bug ≡ Correctness
Description
CLAUDE.md lists markdownlint-cli2 alongside commands available after uv sync, but that
executable is not declared in the project dependencies. On a clean checkout the documented
validation sequence stops there, while CI succeeds only because its workflow installs the npm
package separately.
Code

CLAUDE.md[45]

+markdownlint-cli2 "**/*.md" "#node_modules" "#.local" "#.claude/skills" "#.teken"
Evidence
The Python development dependencies do not include the Markdown linter, while CI explicitly installs
it globally through npm before running the same command.

pyproject.toml[32-43]
.github/workflows/tests.yml[72-75]
QWEN.md[80-87]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The documented validation commands invoke `markdownlint-cli2`, but `uv sync` does not install that npm executable.

## Fix Focus Areas
- CLAUDE.md[29-49]
- QWEN.md[68-88]

## Recommended Fix
Add the required npm installation command or explicitly identify `markdownlint-cli2` as an external prerequisite before the lint command in both prompt files.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Read-only runs still write local artifacts ✓ Resolved 🐞 Bug ≡ Correctness
Description
AGENTS.colleague.md says nothing from a read-only worktree reaches the asker’s tree, but
run_readonly copies the generated task record and optional trace into the real checkout’s
.colleague directory. Review and exploration therefore leave gitignored bookkeeping files behind
even though they do not modify the tracked branch.
Code

AGENTS.colleague.md[R42-45]

+In the read-only verbs your worktree is disposable and detached; nothing you
+write there reaches the asker's tree or branch. What *does* reach them is your
+result summary on stdout — so put the substance there, not in files nobody will
+read. Per-step progress goes to stderr.
Evidence
The wrapper creates a detached worktree, then deliberately copies its task artifact and optional
trace into $REPO/.colleague before cleanup.

.claude/skills/ask-colleague/scripts/ask-colleague.sh[676-712]
.claude/skills/ask-colleague/scripts/ask-colleague.sh[724-742]
.gitignore[225-233]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Read-only colleague runs preserve bookkeeping artifacts in the caller's checkout despite the prompt claiming that nothing reaches that tree.

## Fix Focus Areas
- AGENTS.colleague.md[42-45]

## Recommended Fix
State that tracked source changes are discarded, but task JSON and optional trace artifacts are copied into the gitignored `.colleague/` directory for later grading.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Skill sync targets wrong supplier ✓ Resolved 🔗 Cross-repo conflict ⚙ Maintainability
Description
README.md, CLAUDE.md, and QWEN.md label all 19 local skill directories as the canonical
Guildmaster kit, but Guildmaster supplies 17 of them while recall and remember are separate
additions. When maintainers reconcile this inventory against Guildmaster, the prompts direct them to
a supplier that does not own those two skills.
Code

README.md[R28-29]

+- **The canonical guildmaster skill kit** (19 skills) under `.claude/skills/`,
  vendored cite-don't-import. See [`docs/skill-sources.md`](docs/skill-sources.md).
-- **A build + deploy baseline** — pytest, lint, the agent-first rubric gate, and
-  PyPI Trusted Publishing wired into GitHub Actions.
Evidence
The PR labels the entire 19-directory tree as Guildmaster's canonical kit, while the local tree
includes recall and remember. Guildmaster's ledger defines eight directly supplied skills, eight
Devague-origin rebroadcasts, and ask-colleague as the tracked Colleague-origin skill for
substack-cli, accounting for only 17 entries.

README.md[28-29]
.claude/skills/recall/SKILL.md[1-10]
.claude/skills/remember/SKILL.md[1-10]
External repo: agentculture/guildmaster, docs/skill-sources.md [34-51]
External repo: agentculture/guildmaster, docs/skill-sources.md [89-99]
External repo: agentculture/guildmaster, docs/skill-sources.md [205-207]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The documentation calls all 19 local skills the canonical Guildmaster kit, although Guildmaster's supplier ledger accounts for only 17 and does not supply `recall` or `remember`.

## Fix Focus Areas
- README.md[28-29]
- CLAUDE.md[143-153]
- QWEN.md[146-153]
- docs/skill-sources.md[24-53]

## Recommended Fix
Describe the inventory as 17 Guildmaster-supplied or rebroadcast skills plus the separately sourced `recall` and `remember` skills. Add their actual provenance and resynchronization source to `docs/skill-sources.md`, and use the same distinction in every harness prompt.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View medium (3)
4. Claude is told absent features exist ✓ Resolved 📘 Rule violation § Compliance
Description
The opening What this project is paragraph presents publishing, scheduling, comments, statistics,
and subscriber management as current capabilities even though the following status block says that
none exists. A Claude Code session encounters these unmarked aspirational capabilities before the
caveat, while additional forward-looking instructions under Adding the Substack surface also lack
the required (planned) marker.
Code

CLAUDE.md[R7-10]

+`substack-cli` is an **agent-first CLI to manage a Substack publication and
+account** — publish and schedule posts, read posts and comments, run audience
+and post statistics, and manage subscribers. Unofficial community tool, not
+affiliated with Substack.
Evidence
Compliance rule 3243665 requires forward-looking claims outside a Roadmap to carry an immediate
(planned) marker and forbids presenting absent features as implemented. The new opening lists the
domain capabilities in the present tense, while its own following paragraph confirms that the entire
domain surface is absent and future work.

Rule 3243665: Mark forward-looking claims in CLAUDE.md as planned or move them to Roadmap
CLAUDE.md[7-18]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`CLAUDE.md` describes an unimplemented Substack feature surface without placing it under a Roadmap or immediately marking it `(planned)`.

## Fix Focus Areas
- CLAUDE.md[7-18]
- CLAUDE.md[51-56]
- CLAUDE.md[96-105]

## Recommended Fix
Rewrite the opening so the feature name or forward-looking phrase is immediately followed by `(planned)`. Apply the same marker to the future name-alignment and Substack-surface claims, or move those claims beneath a `## Roadmap` heading.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Failure rules contradict current behavior ✓ Resolved 🐞 Bug ⚙ Maintainability
Description
AGENTS.colleague.md says every failure raises CliError, but parser failures raise SystemExit
after formatting a CliError and an unhealthy doctor result simply returns status 1. Applying this
stated contract to new work or tests would conflict with two established CLI failure paths.
Code

AGENTS.colleague.md[R100-102]

+- **Every failure raises `CliError(code, message, remediation)`** — never a bare
+  exception, never a traceback to stderr. Exit codes: `0` success, `1` user
+  error, `2` environment error, `3+` reserved.
Evidence
The custom parser emits a CliError representation and raises SystemExit, while cmd_doctor
emits its report and returns 1 when checks fail rather than raising an exception.

substack_cli/cli/init.py[49-56]
substack_cli/cli/_commands/doctor.py[171-185]
substack_cli/cli/init.py[98-119]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The prompts state that every failure raises `CliError`, but parser failures and unhealthy diagnostic results intentionally use different control flow.

## Fix Focus Areas
- AGENTS.colleague.md[100-102]
- CLAUDE.md[68-80]
- QWEN.md[110-122]

## Recommended Fix
Limit the `CliError` requirement to command-handler errors, then document that parser errors emit the same structured payload before raising `SystemExit` and diagnostic commands may return a nonzero health status.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. Colleague is shown as skill-enabled ✓ Resolved 🐞 Bug ≡ Correctness
Description
CLAUDE.md describes the shared symlinks as “one skill tree, four loaders,” even though colleague
currently loads none of those skills. This contradicts the colleague prompt and can make agents
assume skills are available when choosing or diagnosing that harness.
Code

CLAUDE.md[R127-130]

+`AGENTS.override.md` exists specifically so Pi does **not** inherit this file.
+`.qwen/skills`, `.colleague/skills` and `.pi/skills` are relative symlinks onto
+`.claude/skills` — one skill tree, four loaders. Forcing a harness is
+invocation-level only (flags to one process); never rewrite `culture.yaml` to
Evidence
The smoke checker explicitly documents that colleague does not load the skills and validates only
its symlink, while the colleague-specific prompt also says version 1.76.0 loads zero skills.

scripts/harness-smoke.py[212-224]
AGENTS.colleague.md[67-71]
QWEN.md[44-46]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The shared-tree documentation says all four harnesses load the skills, but colleague currently has only symlink wiring and cannot load the tree.

## Fix Focus Areas
- CLAUDE.md[127-130]
- QWEN.md[44-46]
- AGENTS.colleague.md[67-71]

## Recommended Fix
Describe the symlinks as shared wiring rather than four working loaders, and explicitly preserve the colleague upstream-loading exception everywhere the shared tree is discussed.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational

7. Worktree advice describes an old example ✓ Resolved 🐞 Bug ⚙ Maintainability
Description
CLAUDE.md says the vendored fan-out example uses a shared ../worktrees/ directory, but the
checked-in skill already computes the required repository-scoped .worktrees.<repo-name> root. The
warning consequently tells agents to override an already-compliant path and obscures that only the
branch naming convention differs.
Code

CLAUDE.md[R212-214]

+The vendored `assign-to-workforce` skill's fan-out example uses both the shared
+`../worktrees/` path and `agent/<task-id>` branches — override *both* when you
+follow it; the skill is cited verbatim and must not be edited.
Evidence
The vendored example constructs a sibling .worktrees.<repo-name> directory and explicitly forbids
bare ../worktrees/; its branch is the only part still using the agent/<task-id> convention.

.claude/skills/assign-to-workforce/SKILL.md[190-205]
CLAUDE.md[198-214]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The prompt attributes the obsolete shared worktree path to the current vendored skill even though that skill already uses the repository-scoped root.

## Fix Focus Areas
- CLAUDE.md[212-214]

## Recommended Fix
Remove the shared-path warning for the vendored skill and state only the remaining difference: its example uses an `agent/<task-id>` branch name.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
✅ Compliance rules (platform): 13 rules
✅ Cross-repo context — repo relationships
  Explored: repo: agentculture/culture (sha: d5b5715f)
  Explored: repo: agentculture/steward (sha: 7b6c16db)
  Explored: repo: agentculture/colleague (sha: 6081b8c8)
  Explored: repo: agentculture/guildmaster (sha: fedb965d)
Review mode: ⚖️ Balanced: The change is primarily documentation but spans four operational harness prompts, repository guidance, packaging metadata, and lockfile state, creating broad cross-file consistency and behavior risks that merit a complete review.

Grey Divider

Tip of the day
💡 Did you know, you can hide the parts of a finding you never read, like the evidence or the agent prompt

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread CLAUDE.md
Comment thread CLAUDE.md
Comment thread CLAUDE.md Outdated
Comment thread AGENTS.colleague.md Outdated
Comment thread AGENTS.colleague.md Outdated
Comment thread CLAUDE.md Outdated
Comment thread README.md Outdated
The Worktrees section claimed the vendored skill's fan-out example uses a
shared `../worktrees/` path that must be overridden. It does not: the current
`.claude/skills/assign-to-workforce/SKILL.md` mandates the same repo-named
`.worktrees.<repo-name>` root this file does, and explicitly says "Never use a
bare `../worktrees/`". The claim was inherited from culture-agent-template's
CLAUDE.md and describes an older revision of the vendored file.

Only the branch-name half of the override still applies (`agent/<task-id>`).

Found by `ask-colleague review` on this PR. Its other two findings: the
"eight skills originate in devague" phrasing is correct as written
(docs/skill-sources.md lists exactly eight devague-origin rows, all
re-broadcast via guildmaster — the direct-from-devague vendoring it recalled
is marked superseded in that ledger), and the code-side "clonable template"
strings are filed as #3 rather than folded into a doc-only PR.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01VaCYnmwSaYL2DLxDtd1fTs
@OriNachum

Copy link
Copy Markdown
Contributor Author

Ran ask-colleague review on the committed diff (the standing pre-PR reflex — a different backend/model, read-only in a throwaway worktree). Verdict: no blocking findings; it checked every factual claim in the four harness files and the README against disk and found no contradictions. Three findings, triaged:

1. FIX — my citation of the vendored assign-to-workforce skill was wrong. Pushed in e61b4dc. CLAUDE.md's Worktrees section claimed the skill's fan-out example uses a shared ../worktrees/ path needing an override. It does not — the current vendored SKILL.md mandates the same repo-named .worktrees.<repo-name> root and explicitly says "Never use a bare ../worktrees/". The claim was inherited verbatim from culture-agent-template's CLAUDE.md and describes an older revision. Only the branch-name half of the override still applies. Verified against SKILL.md §Fan-out before changing it.

2. Deferred to #3 — the code still self-describes as a template. substack learn and --help say "a clonable template for AgentCulture mesh agents", contradicting every prompt file this PR just rewrote. Colleague called it "the single most visible remaining drift" and I agree, but it is a code change with test assertions attached, so it does not belong in a doc-only PR. Filed as #3 with the eight locations, the teken cli doctor constraints on learn, and a related wrinkle colleague did not mention: overview.py's _ARTIFACTS names culture.yaml + AGENTS.colleague.md as the identity pair, which is wrong here — culture.yaml declares backend: claude.

3. PUSHBACK — "eight skills originate in devague" is correct as written. Colleague read it as seven-plus-one and suggested naming the two legs. docs/skill-sources.md lists exactly eight devague-origin rows (think, spec-to-plan, assign-to-workforce, scope, challenge, deviate, validate-delivery, summarize-delivery), all re-broadcast via guildmaster. The direct-from-devague vendoring it recalled is the 2026-07-15 decision that ledger marks superseded. No change.

Colleague was explicit about what it did not check: it did not run the suite or teken cli doctor (review by inspection), and spot-checked the ask-colleague verb list against the ledger rather than the 941-line script. Both are covered by CI here.

Remaining CI failure is repo setup, not this branch. test-publish fails with invalid-publisher from TestPyPI — no Trusted Publisher is registered for agentculture/substack-cli with environment testpypi. The build succeeded (0.9.1.dev3); only the upload is rejected. That is the prerequisite README.md and CLAUDE.md both state, it needs someone with the TestPyPI account, and it will block the real publish job on merge to main until it is configured. Everything else is green, SonarCloud gate passed with 0 issues and 0 hotspots.

…ecision

Six inline findings from the Qodo review on PR #2, each verified against disk
before acting:

- Mark the Substack surface `(planned)` at first mention in all four harness
  files and on the "Adding the Substack surface" heading, per this repo's own
  rule that anything ahead of disk carries the marker.
- Note that `markdownlint-cli2` is an npm prerequisite, not something `uv sync`
  installs — CI installs it separately, so a clean checkout following the
  documented sequence stopped there.
- Stop implying all four harnesses load the shared skill tree: the symlinks are
  shared wiring, but colleague 1.76.0 loads 0 of the 19 (colleague#494). The
  caveat was in AGENTS.colleague.md only; it is now in CLAUDE.md and QWEN.md
  where the "one tree, four loaders" claim was made.
- Qualify the CliError contract. "Every failure raises CliError" contradicted
  two deliberate paths: `_CliArgumentParser.error()` emits a CliError then
  raises SystemExit, and `doctor` returns 1 for an unhealthy report rather than
  raising. Both are now named so neither gets "fixed" by a future change.
- AGENTS.colleague.md claimed nothing from a read-only run reaches the asker's
  checkout. Tracked files, correct — but the run artifact is copied into the
  gitignored `.colleague/` dir for grading. Stated.
- docs/skill-sources.md listed 17 rows while `.claude/skills/` holds 19:
  `recall` and `remember` were vendored without ledger entries. Added both
  (guildmaster, scope literal adapted), plus a header line accounting for all
  19. Qodo read the gap as "guildmaster does not supply these two" — it does
  ship both; the defect was the missing rows, not the supplier.

Also corrected the kit description in CLAUDE.md, QWEN.md and README.md: 19
skills is 17 guildmaster + ask-colleague direct from colleague, not a single
"canonical guildmaster kit".

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01VaCYnmwSaYL2DLxDtd1fTs
@OriNachum

Copy link
Copy Markdown
Contributor Author

FIX — dd96960. Fair reading of this repo's own rule (anything ahead of disk carries (planned) or lives under ## Roadmap), and the caveat did sit one paragraph below the claim. The domain sentence now reads **agent-first CLI to manage a Substack publication and account** *(planned — see Status below)* at first mention in all four harness files, and the section heading is now ## Adding the Substack surface (planned). I kept the capability list itself intact rather than deleting it — an agent reading the file needs to know what the repo is for, and the marker plus the Status block is what makes that honest.

  • substack-cli (Claude)

@OriNachum

Copy link
Copy Markdown
Contributor Author

FIX — dd96960. Correct and worth catching: markdownlint-cli2 is an npm package, uv sync cannot install it, and CI only succeeds because tests.yml runs npm install -g [email protected] in the lint job. Following the documented sequence on a clean checkout stopped at that line. Both CLAUDE.md and QWEN.md now carry the install command inline above it.

  • substack-cli (Claude)

@OriNachum

Copy link
Copy Markdown
Contributor Author

FIX — dd96960. The caveat existed in AGENTS.colleague.md but not where the "one skill tree, four loaders" claim was actually made. Verified against docs/harness-verification.md: Pi 19, Qwen 19, colleague 0 of 19 (upstream, colleague#494). CLAUDE.md and QWEN.md now say the symlinks are shared wiring and name the colleague exception with the issue link.

  • substack-cli (Claude)

@OriNachum

Copy link
Copy Markdown
Contributor Author

FIX — dd96960. Verified both paths in source: _CliArgumentParser.error() builds a CliError, calls emit_error, then raise SystemExit(err.code) (cli/__init__.py:57-64), and cmd_doctor ends return 0 if report["healthy"] else 1 without raising (_commands/doctor.py). The blanket phrasing would have led a future change to "fix" either one. All three files now scope the rule to command handlers and name the two downstream exceptions explicitly — including the reason doctor differs: an unhealthy agent is a result, not a CLI failure.

  • substack-cli (Claude)

@OriNachum

Copy link
Copy Markdown
Contributor Author

FIX — dd96960. Confirmed empirically, not just by reading run_readonly: the ask-colleague runs I did on this PR each printed artifact: /home/spark/git/substack-cli/.colleague/<id>.json in the real checkout. The text now distinguishes the two — no tracked file from the throwaway worktree reaches the asker's tree or branch, but the run artifact is copied into the gitignored .colleague/ directory so the run can be graded later (ask-colleague feedback <id> --rating N depends on it being there).

  • substack-cli (Claude)

@OriNachum

Copy link
Copy Markdown
Contributor Author

FIX on the defect, PUSHBACK on the diagnosis — dd96960.

The gap is real: docs/skill-sources.md had 17 rows while .claude/skills/ holds 19, so recall and remember were vendored without ledger entries. Added both, plus a header line accounting for all 19 (17 guildmaster + ask-colleague direct from colleague), and corrected the "canonical guildmaster kit" phrasing in README.md, CLAUDE.md and QWEN.md.

But guildmaster does supply them — ls ../guildmaster/.claude/skills/ lists both, and the local copies differ from upstream only in the consumer-scope literal (--scope guildmaster--scope substack-cli), the same adaptation cicd and communicate already document. So the fix is the missing rows, not a different supplier.

One thing the ledger now records that neither of us started from: remember/scripts/remember.sh carries an explicit policy override making a plain /remember --visibility public (landing in the committed <repo>/.eidetic/memory), while the vendored SKILL.md frontmatter still describes eidetic's upstream private/$HOME default. The script wins; the prompt files are correct as written.

  • substack-cli (Claude)

@sonarqubecloud

Copy link
Copy Markdown

@OriNachum
OriNachum merged commit d002997 into main Sep 12, 2026
11 of 12 checks passed
@OriNachum
OriNachum deleted the docs/init-harness-prompts branch September 12, 2026 18:09
OriNachum added a commit that referenced this pull request Sep 13, 2026
…lass (v0.10.0) (#5)

* docs: re-init CLAUDE.md and align all four harness prompts

`/init` replaced the scaffold seed `CLAUDE.md` with a runtime prompt grounded
in this repo, and the other three harness files were brought in line with it —
each written for its own harness rather than restating the same text.

- CLAUDE.md: command block (tests, single test, every lint/rubric/smoke gate),
  the cross-file CLI wiring (`_CliArgumentParser.error()` override, the
  `_json_hint` argv peek, the `parser_class` propagation trap, `CliError`, the
  stdout/stderr split, the catalog walked by `tests/test_cli.py`), a five-place
  checklist for adding a Substack noun, and `_PROMPT_FILE` vs
  `_RESIDENT_PROMPT`.
- QWEN.md: the coding-session machinery for a Qwen Code session.
- AGENTS.override.md: context only (identity stays in `.pi/SYSTEM.md`), and
  tells Pi's non-coding lane to report the scaffold gap rather than infer an
  implementation from the project description.
- AGENTS.colleague.md: rewritten around colleague as the `/ask-colleague`
  second mind — per-verb expectations, the contracts a diff must respect, and
  the colleague#494 empty-skills caveat.
- README.md: template-clone instructions replaced by this repo's own Status /
  CLI / Development sections.

Fixes four drifts the docs carried: a Substack surface (posts, comments,
statistics, subscribers) that does not exist on disk; a quickstart using
`uv run substack-cli …` when `[project.scripts]` installs the binary as
`substack`; a skill count of 11 against 19 on disk; and three files calling
`CLAUDE.md` "the fullest write-up" while it was still the `/init` seed.

Verified: 117 tests pass, `teken cli doctor . --strict` PASS,
`harness-smoke --stage config` 6/6 PASS, scan-secrets clean, markdownlint
clean, `devex pr lint` no violations. Qwen and Pi were asked "Who are you,
and what can you do?" in this tree and both answered from their new files.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01VaCYnmwSaYL2DLxDtd1fTs

* docs: correct the assign-to-workforce worktree citation in CLAUDE.md

The Worktrees section claimed the vendored skill's fan-out example uses a
shared `../worktrees/` path that must be overridden. It does not: the current
`.claude/skills/assign-to-workforce/SKILL.md` mandates the same repo-named
`.worktrees.<repo-name>` root this file does, and explicitly says "Never use a
bare `../worktrees/`". The claim was inherited from culture-agent-template's
CLAUDE.md and describes an older revision of the vendored file.

Only the branch-name half of the override still applies (`agent/<task-id>`).

Found by `ask-colleague review` on this PR. Its other two findings: the
"eight skills originate in devague" phrasing is correct as written
(docs/skill-sources.md lists exactly eight devague-origin rows, all
re-broadcast via guildmaster — the direct-from-devague vendoring it recalled
is marked superseded in that ledger), and the code-side "clonable template"
strings are filed as #3 rather than folded into a doc-only PR.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01VaCYnmwSaYL2DLxDtd1fTs

* docs: address Qodo review — planned markers, lint prereq, contract precision

Six inline findings from the Qodo review on PR #2, each verified against disk
before acting:

- Mark the Substack surface `(planned)` at first mention in all four harness
  files and on the "Adding the Substack surface" heading, per this repo's own
  rule that anything ahead of disk carries the marker.
- Note that `markdownlint-cli2` is an npm prerequisite, not something `uv sync`
  installs — CI installs it separately, so a clean checkout following the
  documented sequence stopped there.
- Stop implying all four harnesses load the shared skill tree: the symlinks are
  shared wiring, but colleague 1.76.0 loads 0 of the 19 (colleague#494). The
  caveat was in AGENTS.colleague.md only; it is now in CLAUDE.md and QWEN.md
  where the "one tree, four loaders" claim was made.
- Qualify the CliError contract. "Every failure raises CliError" contradicted
  two deliberate paths: `_CliArgumentParser.error()` emits a CliError then
  raises SystemExit, and `doctor` returns 1 for an unhealthy report rather than
  raising. Both are now named so neither gets "fixed" by a future change.
- AGENTS.colleague.md claimed nothing from a read-only run reaches the asker's
  checkout. Tracked files, correct — but the run artifact is copied into the
  gitignored `.colleague/` dir for grading. Stated.
- docs/skill-sources.md listed 17 rows while `.claude/skills/` holds 19:
  `recall` and `remember` were vendored without ledger entries. Added both
  (guildmaster, scope literal adapted), plus a header line accounting for all
  19. Qodo read the gap as "guildmaster does not supply these two" — it does
  ship both; the defect was the missing rows, not the supplier.

Also corrected the kit description in CLAUDE.md, QWEN.md and README.md: 19
skills is 17 guildmaster + ask-colleague direct from colleague, not a single
"canonical guildmaster kit".

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01VaCYnmwSaYL2DLxDtd1fTs

* spec: substack-domain-surface (devague /scope + /think)

Converged frame for the Substack control surface: post/feed/comment/
reaction/account nouns, webglass-cli as the runtime browser plane,
public read verbs first, owner verbs gated on webglass authenticated
sessions (agentculture/webglass-cli#17).

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01CH5jAgaWUmCiXBJ3nKWdUV

* spec: challenge pass on substack-domain-surface (devague /challenge)

Rigorous pass (hard-to-reverse publish + security-sensitive session):
webglass has no network lens (capture via Chrome-MCP now, lens asked in
webglass-cli#17), two API hosts, markdown->ProseMirror is real work, no
auto-retry on writes, partial-state reporting, three-state auth probe,
untrusted third-party text, containment twins for every write verb,
draft-first publish with --no-email for live proofs. One self-reported
lapse (l1) confirmed.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01CH5jAgaWUmCiXBJ3nKWdUV

* plan: substack-domain-surface (devague /spec-to-plan)

17 tasks in 7 waves covering all 56 spec targets: baseline, HTTP
transport, webglass adapter, untrusted-text helper, Chrome capture;
five nouns; post write side + markdown body; parser/learn/catalog
wiring; docs, version bump, CI gates; public and owner live proofs.
Owner proof (t18) is a follow-up risk on webglass-cli#17.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01CH5jAgaWUmCiXBJ3nKWdUV

* plan: implementation split (gate 2 approved)

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01CH5jAgaWUmCiXBJ3nKWdUV

* t1: record pre-feature learn baseline

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01CH5jAgaWUmCiXBJ3nKWdUV

* t4: untrusted third-party text renderer

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01CH5jAgaWUmCiXBJ3nKWdUV

* t3: webglass subprocess adapter

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01CH5jAgaWUmCiXBJ3nKWdUV

* t2: stdlib HTTP transport with host validation and GET-only backoff

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01CH5jAgaWUmCiXBJ3nKWdUV

* t6: post noun read side (list, get, overview)

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01CH5jAgaWUmCiXBJ3nKWdUV

* t5: account noun (whoami auth probe, overview)

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01CH5jAgaWUmCiXBJ3nKWdUV

* t12: observed Substack API endpoints for the v1 verbs

Captured 2026-09-13 in the owner's logged-in browser on
jetsonailab.substack.com: drafts create/update/publish/schedule/
unschedule/unpublish/delete, comments create/reply/delete, post and
comment reactions add/remove, public archive/post/comments reads, the
subscription endpoint as the whoami source, and the substack.com reader
feed. Unobserved paths are marked as such.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01CH5jAgaWUmCiXBJ3nKWdUV

* t12: reword a query-string example the secrets gate flagged

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01CH5jAgaWUmCiXBJ3nKWdUV

* t5: whoami reads user_id from /api/v1/subscription

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01CH5jAgaWUmCiXBJ3nKWdUV

* t9: feed noun (read, overview)

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01CH5jAgaWUmCiXBJ3nKWdUV

* t7: comment noun (list, reply, delete, overview)

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01CH5jAgaWUmCiXBJ3nKWdUV

* t8: reaction noun (list, add, remove, overview)

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01CH5jAgaWUmCiXBJ3nKWdUV

* t10: post write side (publish, schedule, unpublish, delete) and markdown body builder

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01CH5jAgaWUmCiXBJ3nKWdUV

* t13: wire the five Substack nouns into the parser, learn and explain

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01CH5jAgaWUmCiXBJ3nKWdUV

* t15: bump version to 0.10.0

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01CH5jAgaWUmCiXBJ3nKWdUV

* http: descriptive User-Agent and fail-fast on non-retryable 4xx

The live public-read proof returned 403: Substack rejects urllib's
default Python-urllib agent (a descriptive substack-cli/<version> agent
is accepted; verified with curl). The GET loop also retried every
HTTPError; it now retries only 429, 5xx and transport errors, per
spec claim c38. Two tests that asserted four attempts on a 404 now
assert one.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01CH5jAgaWUmCiXBJ3nKWdUV

* t16: CI gates — socket-blocking fixture, repo invariants, coverage floor

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01CH5jAgaWUmCiXBJ3nKWdUV

* t14: document the Substack surface across README and the four harness prompts

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01CH5jAgaWUmCiXBJ3nKWdUV

* t17: public-half live proof against two publication hosts

Evidence stored as a text record with a header line (JSON body):
scripts/scan-secrets.py fails any JSON-parsable file whose url keys
point off localhost, and the t2 invariant forbids tracked *.json files
naming substack.com.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01CH5jAgaWUmCiXBJ3nKWdUV

* delivery: summarize the substack-domain-surface workforce run

Partial run: 16 of 17 plan tasks delivered, t18 (owner-half live proof)
blocked on agentculture/webglass-cli#17. Deviations d1-d4, lapses
l1-l15, validation ledger o1-o23/e1-e22/b1-b4 all adjudicated.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01CH5jAgaWUmCiXBJ3nKWdUV

* fix: address Qodo review on PR #5 (comments 3998832718, 3998832722, 3998832725, 3998832730, 3998832732, 3998832734, 3998832736, 3998832739)

- 3998832718: `comment list` now sends the observed query
  (all_comments=true&sort=best_first, urlencoded) and flattens nested
  `children` replies depth-first, parents before replies, keeping
  parent_id/ancestor_path on each item.
- 3998832722: reaction add/remove build their URL from
  http.publication_base(), so SUBSTACK_API_BASE reaches writes as it does reads.
- 3998832725: `feed read` builds limit/cursor with urllib.parse.urlencode, so a
  cursor containing &, #, + or % can no longer forge or truncate the query.
- 3998832730: run_webglass passes a finite timeout (120s, SUBSTACK_WEBGLASS_TIMEOUT;
  invalid -> CliError(1)) and maps TimeoutExpired to CliError(2) naming the variable.
- 3998832732: http passes a finite timeout to opener.open (30s,
  SUBSTACK_HTTP_TIMEOUT; invalid -> CliError(1)); timeouts retry on GET and
  raise a single CliError(2) on writes.
- 3998832734: UnicodeDecodeError/JSONDecodeError around response decoding on
  both the GET and write paths -> CliError(2) naming the URL, never retried.
- 3998832736: an argparse usage/unknown-verb answer from webglass now maps to
  CliError(2) saying webglass-cli has no authenticated request verb yet, citing
  agentculture/webglass-cli#17. The verbs stay registered.
- 3998832739: --body-json must decode to {"type": "doc", "content": [...]};
  anything else is CliError(1) with the ProseMirror remediation.
- 3998832738 (--send): behaviour unchanged by design; the help text and
  docstring now say the send:true path is unverified against the live API.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01CH5jAgaWUmCiXBJ3nKWdUV

* refactor: address SonarCloud smells on the Substack surface (S1192, S8513, S3358, S5799, S9073, S9100)

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01CH5jAgaWUmCiXBJ3nKWdUV

* refactor: drop redundant HTTPError from except tuples (S5713); split a composite assert (S9073)

HTTPError derives from URLError, so catching both is redundant; the
behaviour is unchanged.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01CH5jAgaWUmCiXBJ3nKWdUV

* refactor: single-return account handlers (S3516), split map_failure's HTTP branch (S3776), merge a literal (S5799)

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01CH5jAgaWUmCiXBJ3nKWdUV

---------

Co-authored-by: Claude Opus 5 (1M context) <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant