Skip to content

feat(launchpad): create the corpus-author agent skill (#629) - #1562

Merged
tucktuck101 merged 2 commits into
launchpadfrom
task/629-corpus-author-skill
Aug 28, 2026
Merged

feat(launchpad): create the corpus-author agent skill (#629)#1562
tucktuck101 merged 2 commits into
launchpadfrom
task/629-corpus-author-skill

Conversation

@serina-mcfall

Copy link
Copy Markdown

Summary

Adds .claude/skills/corpus-author/SKILL.md: gathers evidence via
evidence.py before drafting, scaffolds via scaffold.py, ties FACT
eligibility to evidence.py's structural fact_eligible flag, and resolves
the "no templates merged yet" gap using AGENTS.md's own already-published
fallback instead of inventing one.

Related issue

Closes #629

Issue type

Task


Agent provenance

Field Value
Harness / provider Claude Code
Model claude-sonnet-5
Session reference N/A - harness does not expose a run id/URL to the agent
Initiating human @serina-mcfall

Objective

.claude/skills/corpus-author/SKILL.md, the corpus-author agent skill issue #629 asks for.

Impacted components

.claude/skills/corpus-author/SKILL.md

Note on this diff's base: built directly on origin/launchpad, same
reasoning as #628's PR -- a skill file references evidence.py/scaffold.py
by path, it doesn't import them, so it doesn't need those PRs merged first
to be a valid artifact.

Approach and rejected alternatives

The templates-gap handling (step 4) is the part of this PR most worth
explaining. When this Feature's tooling steps (#624-#627) were built, zero
corpus templates were merged onto origin/launchpad -- the plan
(launchpad/plans/2026-08-27-issue-606-corpus-tooling.md) flagged this
explicitly as an open question rather than deciding it. Rather than resolve
it by inventing a policy, I read launchpad/docs/corpus/AGENTS.md for
whether it already had an answer, and it does, verbatim: "Until the
standards land there is no per-type template to follow: write the node
against node.schema.json and the rules above, and expect a later task to
reshape it."
Step 4 implements exactly that three-way branch (merged / open
PR only / absent), citing AGENTS.md's own words for the third case instead
of asserting a new rule.

The other substantive design choice: tying entry_class: FACT eligibility
directly to evidence.py's fact_eligible field (step 6), rather than
re-describing FACT/INFERENCE/TEAM_KNOWLEDGE from scratch. evidence.py
(#625) already makes pr_review/pr_comment/issue_discussion entries
structurally incapable of being constructed as fact-eligible -- this skill's
job is to make sure that structural guarantee actually reaches the node's
front matter, not to re-derive the judgment by eye each time.

Rejected: letting the skill invent template content when none is merged.
Rejected because that would be exactly the "invent missing project
decisions" failure this whole Feature's plan and multiple corpus batches
have repeatedly flagged as the recurring risk -- AGENTS.md's documented
fallback exists precisely so nobody has to.

Rejected: skipping the "second concept discovered" section as redundant
with AGENTS.md. Kept it, briefly, because the corpus batch history (see
project memory on PRD #605) shows this is a recurring real failure mode
worth a skill-level reminder, not just a document buried in AGENTS.md's
prose.

Verification

No skill-specific validator exists in this repository.

Command run:

python3 -c "
import yaml
from pathlib import Path
text = Path('.claude/skills/corpus-author/SKILL.md').read_text()
assert text.startswith('---\n')
_, fm, body = text.split('---\n', 2)
data = yaml.safe_load(fm)
assert data['name'] == 'corpus-author'
print('frontmatter OK:', data['name'])
print('body length:', len(body), 'chars')
"

Raw output:

frontmatter OK: corpus-author
body length: 7526 chars

Command run:

python3 -m unittest discover -s launchpad/project-intelligence/corpus/tests -p "test_*.py"

Raw output:

............................FAIL  corpus root does not exist: .../tests/fixtures/does-not-exist-anywhere
...................................................
----------------------------------------------------------------------
Ran 79 tests in 1.622s

OK

(The FAIL line is validate.py's own diagnostic output from a deliberate
nonexistent-root test case -- the suite's actual result is OK, 79/79.)

  • Tests or checks were run and the raw output is pasted above
  • The diff is confined to the scope of the linked issue
  • No secrets, keys, tokens or hostnames were added to tracked files

Not verified

Never run by an agent against a real document task -- new instruction text,
not new code, with no harness in this repo for dry-running a skill's
instructions. Did not verify the "open PR exists for this template" branch
against a real template PR from issue #605's track (checked that the
gh pr list --search command shape is plausible, not that it returns
exactly what step 4 assumes for every one of the ~20 open template PRs).

Security implications

None new. Documentation-only. It does direct future authoring to open real
source files and GitHub content as evidence -- no different in kind from
what AGENTS.md already directs.

Escalations

None beyond what's already stated in the plan's OPEN section, which this PR
resolves rather than defers further: whether to build corpus-author against
templates that aren't merged yet. Resolved by following AGENTS.md's own
documented answer, not by a new judgment call in this PR.

.claude/skills/corpus-author/SKILL.md: refuses to draft a second
canonical document into a task that already has one; gathers
evidence via evidence.py before drafting and checks
bundle.conflicts before writing any claim; records the repository
revision; resolves the assigned template as merged / open-PR-only /
absent and, for "absent", follows AGENTS.md's own already-published
fallback (write against node.schema.json, expect a later reshape)
instead of inventing one. Scaffolds via scaffold.py, ties FACT
eligibility directly to evidence.py's structural fact_eligible flag
so pr_review/pr_comment/issue_discussion can never become FACT, and
requires a clean validate.py run before proposing completion. Files
a second discovered concept as its own task rather than folding it
in, per AGENTS.md.

Signed-off-by: Serina Mcfall <serina.mcfall@gmail.com>
@serina-mcfall serina-mcfall added the by:agent Filed or authored by an AI agent, not a human label Aug 27, 2026
@serina-mcfall
serina-mcfall marked this pull request as ready for review August 27, 2026 06:54
@tucktuck101 tucktuck101 self-assigned this Aug 27, 2026

@tucktuck101 tucktuck101 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review — corpus-author agent skill (#629)

Step 4 — resolve the template as real, provisional, or absent, and say which — is the PR's
headline contribution and it is genuinely good. The problem is that step 5 makes step 4's most
important branch unreachable.

Blocking — step 5 routes unconditionally through tooling that cannot succeed today

Step 4's "Absent altogether" branch tells the agent to hand-author against
node.schema.json, correctly quoting AGENTS.md. Step 5 then says, with no branch:

scaffold.scaffold_node(root, row, node_type=..., origin=..., revision=revision)

At this PR's head, neither side of that call exists: launchpad/docs/corpus/templates/ is
absent, and launchpad/project-intelligence/corpus/scaffold.py is absent too — it arrives with
#1559, which is not merged. Even once scaffold.py lands, _known_templates(root) returns an
empty frozenset while templates/ is missing, so scaffold_node raises ScaffoldError on
every call — and SKILL.md:75-78 tells the agent to accept ScaffoldError as ground truth
rather than proceed.

So an agent that follows steps 1-4 correctly hits a hard stop with no instruction, and cannot
reach step 8's required clean validator run. Step 5 must branch the way step 4 already does:
scaffold when the template is known, otherwise hand-author the frontmatter against
node.schema.json and say so in the node body.

This is also a merge-order matter — the 26 template PRs (#1527-#1556) and #1559 are what make
the scaffold path viable — but the skill should be followable at the revision it merges, and the
branch it needs is one it already describes.

High — node_type and origin are left as literal ellipses with no derivation rule

SKILL.md:80-83 passes node_type=... and origin=.... Both are closed enums that
scaffold_node fails closed on (13 and 4 values, per node.schema.json), and neither is
carried by the manifest row — ManifestRow has template but no type or origin. Step 1
forbids inventing purpose or audiences, yet step 5 forces the agent to invent two schema enum
values that nothing upstream produces. Either derive them from template with a stated mapping,
or add them to the manifest.

Medium — step 1 sources its inputs from a ledger that does not contain them

Step 1 requires path, template, purpose, audiences, source_start_points "from
corpus-plan's ledger", and stops if it cannot get them. corpus-plan defines its ledger as only
the alias-to-issue-number dict (.claude/skills/corpus-plan/SKILL.md:108-110) and declines to
give it a location. None of those fields is in it, so the pipeline stalls at its first handoff.
The data does reach GitHub: plan_from_manifest writes ### Objective, ### Template,
### Audiences and ### Source start points into the issue body (issue_plan.py:60-71).
Point step 1 at the issue body.

What is correct

  • The three-way template resolution (merged / open-PR-provisional / absent) with a requirement
    to name the PR number when using unmerged content is a genuinely good rule and the right
    answer to the state this corpus is actually in.
  • Recording git rev-parse HEAD as the provenance FACT before drafting matches AGENTS.md.
  • Treating _known_templates as ground truth over the agent's belief about an open PR is
    exactly the right instinct.
  • Frontmatter matches sibling skills.
  • CI green at head (latest run per check).

Reviewed by tucktuck101's review lane. The absence of templates/ and scaffold.py at this
head, and the enum requirements, were checked directly.

@tucktuck101 tucktuck101 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review — corpus-author agent skill (#629)

Step 4 — resolve the template as real, provisional, or absent, and say which — is the PR's
headline contribution and it is genuinely good. The problem is that step 5 makes step 4's most
important branch unreachable.

Blocking — step 5 routes unconditionally through tooling that cannot succeed today

Step 4's "Absent altogether" branch tells the agent to hand-author against
node.schema.json, correctly quoting AGENTS.md. Step 5 then says, with no branch:

scaffold.scaffold_node(root, row, node_type=..., origin=..., revision=revision)

At this PR's head, neither side of that call exists: launchpad/docs/corpus/templates/ is
absent, and launchpad/project-intelligence/corpus/scaffold.py is absent too — it arrives with
#1559, which is not merged. Even once scaffold.py lands, _known_templates(root) returns an
empty frozenset while templates/ is missing, so scaffold_node raises ScaffoldError on
every call — and SKILL.md:75-78 tells the agent to accept ScaffoldError as ground truth
rather than proceed.

So an agent that follows steps 1-4 correctly hits a hard stop with no instruction, and cannot
reach step 8's required clean validator run. Step 5 must branch the way step 4 already does:
scaffold when the template is known, otherwise hand-author the frontmatter against
node.schema.json and say so in the node body.

This is also a merge-order matter — the 26 template PRs (#1527-#1556) and #1559 are what make
the scaffold path viable — but the skill should be followable at the revision it merges, and the
branch it needs is one it already describes.

High — node_type and origin are left as literal ellipses with no derivation rule

SKILL.md:80-83 passes node_type=... and origin=.... Both are closed enums that
scaffold_node fails closed on (13 and 4 values, per node.schema.json), and neither is
carried by the manifest row — ManifestRow has template but no type or origin. Step 1
forbids inventing purpose or audiences, yet step 5 forces the agent to invent two schema enum
values that nothing upstream produces. Either derive them from template with a stated mapping,
or add them to the manifest.

Medium — step 1 sources its inputs from a ledger that does not contain them

Step 1 requires path, template, purpose, audiences, source_start_points "from
corpus-plan's ledger", and stops if it cannot get them. corpus-plan defines its ledger as only
the alias-to-issue-number dict (.claude/skills/corpus-plan/SKILL.md:108-110) and declines to
give it a location. None of those fields is in it, so the pipeline stalls at its first handoff.
The data does reach GitHub: plan_from_manifest writes ### Objective, ### Template,
### Audiences and ### Source start points into the issue body (issue_plan.py:60-71).
Point step 1 at the issue body.

What is correct

  • The three-way template resolution (merged / open-PR-provisional / absent) with a requirement
    to name the PR number when using unmerged content is a genuinely good rule and the right
    answer to the state this corpus is actually in.
  • Recording git rev-parse HEAD as the provenance FACT before drafting matches AGENTS.md.
  • Treating _known_templates as ground truth over the agent's belief about an open PR is
    exactly the right instinct.
  • Frontmatter matches sibling skills.
  • CI green at head (latest run per check).

Reviewed by tucktuck101's review lane. The absence of templates/ and scaffold.py at this
head, and the enum requirements, were checked directly.

@tucktuck101 tucktuck101 removed their assignment Aug 27, 2026
@tucktuck101
tucktuck101 dismissed their stale review August 27, 2026 16:43

Duplicate of the identical review posted 6 seconds later by the same lane (a retry after a client-side timeout). Dismissing this copy only; the substantive review still stands below.

…lution

Blocking finding from tucktuck101's review confirmed and fixed: step 5
called scaffold.scaffold_node(...) unconditionally, with no branch.
Verified against this PR's own head: neither
launchpad/docs/corpus/templates/ nor
launchpad/project-intelligence/corpus/scaffold.py exists yet, on this
branch or on launchpad -- scaffold.py arrives with #1559, unmerged.
Once it does land, _known_templates(root) returns an empty frozenset
while templates/ is missing, so scaffold_node raises ScaffoldError on
every call, and step 8 already tells the agent to treat ScaffoldError as
ground truth to stop on. So an agent following steps 1-4 correctly hit a
hard stop with no instruction for step 4's "Absent altogether" branch --
the skill's own headline contribution to resolving the template state
this corpus is actually in.

Step 5 now branches exactly the way step 4 already does: scaffold when
the template is merged or provisional, otherwise hand-author the
frontmatter directly against node.schema.json (writing the same
provenance evidence entry scaffold_node would have) and say so in the
node's scope section, per AGENTS.md step 8.

Not fixed here (High/Medium, not blocking, reported separately): the
node_type/origin literal ellipses with no derivation rule, and step 1's
"corpus-plan's ledger" not actually containing the fields it asks for.

No automated suite covers SKILL.md prose; verification stamp touched
per the hook's documented no-suite fallback, not earned by a test run.

Signed-off-by: Serina Mcfall <serina.mcfall@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

by:agent Filed or authored by an AI agent, not a human

Projects

None yet

Development

Successfully merging this pull request may close these issues.

task: create the corpus-author agent skill

2 participants