Repository source: docs/plans/agent_api_docs/agent_api_docs_step4_implementation_summary.md
Debug mode: enabled
Branch: feat/agent-api-docs, from origin/main at c6fe21b4 (which adds the onboarding checklist, pushed at the user's request). Planning commit: 6d404f4b.
Stage 1 - Route catalog and /api/ index
Changes:
New
ApiRouteCatalog: every routed/api/path with method, access (public,anonymous,signed,hint,session,member,operator,testing,retired), format and purpose. Access and format were checked by probing each route on a local app./api/now renders the catalog with an access legend and a pointer to/llms.txt. The private-messaging prose is unchanged.The index now also lists routes it used to omit:
prepare_*/create_prepared_*, profile name, approval, invitation, retraction, Forte fragments,read_model_status.agent_expansion_statusandprivate_messages/conversationlines now show their full query parameters.create_thread,create_replyandcreate_quoteare markedanonymous("Anonymous ... only").
Verification:
php tests/run.php ApiRouteCatalogTest: 3 passed. Mutation check: removingread_model_statusfrom the catalog makes the parity test fail.Old index route lines compared with the new index: none lost (two lines gained query parameters). Private-messaging prose is byte-identical.
php tests/run.php ApiRouteCatalogTest LocalAppSmokeTest PrivateMessageFeatureFlagTest: 148 passed, 2 failed. Both failures (testBuildStaticCommandReportsProgressAndArtifactSummary,testSharedStaticRefreshCommandKeepsDetailArtifactsWithoutRebuildingTheReadModel) reproduce on the base commit without this change.
Notes:
apply_thread_tag/apply_post_tagare markedhint: they act on the unsigned identity hint cookie. This is related to the Cycle A attribution finding; flagged for Cycle A, not changed here.The parity test reads the
/api/literals inApplication.php, the only file that routes them.
Stage 2 - Generated /llms.txt
Changes:
New
LlmsTxtRenderer, replacing the hard-coded "Local test slice" text. It renders the agent policy, four instance facts (text mode with emoji detail, members-only posting, images, username changes), the six-step signed flow, retry guidance, the agent routes fromApiRouteCatalog, and links to/api/,/api/version, the reference and/docs/.The members-only gate now lets
GET /llms.txtandGET /api/through (Application::membersOnlyRequestAllowed). Content routes such aslist_indexstay gated. See Enhancement Requests.The
LocalAppSmokeTest/llms.txtassertions are updated for the new content.
Verification:
php tests/run.php LlmsTxtRendererTest: 5 passed. Covers each flag on and off, emoji only under Unicode, policy and links, routes drawn from the catalog, and members-only access.Mutation check: disabling the gate change makes the members-only test fail.
php tests/run.php LlmsTxtRendererTest ApiRouteCatalogTest LocalAppSmokeTest: 147 passed, 2 failed (the same baseline static-build failures as Stage 1).WebServerRoutingTest UserAccessTest: passed.Flow claims checked against code:
prepareIdentityBootstrap/createIdentityBootstrapfield names, theopenpgp:<fingerprint>identity ID, username normalization inOpenPgpKeyInspector, the 600-second prepare token lifetime, JSON request bodies inRouteServices::requestData, and no approval check on signed prepare when members-only is off.Cache risk (Step 3):
/llms.txtis not prebuilt or cached; it renders per request.
Notes:
I removed a draft line telling agents to "post at a human pace": it was unapproved policy, and Step 1 excludes rate-limit statements. A test guards against "rate limit" text appearing.
The reference link resolves after Stage 3.
Stage 3 - Protocol reference
Changes:
New
docs/reference/agent_api.md, covering policy, request encodings and response formats, identities and usernames, signing, the flow, text rules, approval and members-only access, unsigned routes, retries, main errors, and "Current limitations" (the statements Cycles A-C will change).New
PlatformDocsCatalogentry, "Agent API Reference" (Extending the Platform).
Verification:
php tests/run.php LlmsTxtRendererTest PlatformDocsCatalogTest PlatformDocsPageTest PlatformDocsStaticTest: 19 passed. The new test checks that every route the reference names is inApiRouteCatalog, and that the reference renders at/docs/reference/agent_api.md.Each error message and field name was checked against
LocalWriteService,AuthApiController,OpenPgpKeyInspectorandRouteServices. The rendered checklist link resolves to/docs/plans/agent_api_onboarding_checklist.md.
Notes:
The worked-example script is not linked from the reference:
/docsonly serves Markdown. Stage 4 decides where the example's sample responses go.
Stage 4 - Tested worked example
Changes:
New
docs/examples/agent_api_worked_example.sh(gpg, curl, and python3 for JSON). It makes an Ed25519 key whose user ID is the username, creates the identity, prepares, signs and publishes a thread, then confirms it withget_post.New
AgentApiWorkedExampleTest. It boots a fresh instance (LocalRepositoryBootstrap) behindFrontendTestServer, runs the script with an isolated GNUPGHOME, and checks the transcript and the new profile (Username: example-agent,Posts: 1).Reference: added a "Sample session" taken from a real run.
Verification:
php tests/run.php AgentApiWorkedExampleTest: passed. On its first run, the test found thatcreate_prepared_postalso requiresrecord_path,post_idandauthor_identity_idechoed back unchanged (Prepared post record_path mismatch.). That was missing from/llms.txtstep 5 and the reference. Both now say it, and the reference error table has a<field> mismatchrow.php tests/run.php AgentApiWorkedExampleTest LlmsTxtRendererTest ApiRouteCatalogTest PlatformDocsCatalogTest PlatformDocsPageTest LocalAppSmokeTest: 162 passed, 2 failed (the same baseline static-build failures).
Notes:
Deviation from Step 3: the plan said to skip when gpg is missing, but
tests/run.phphas no skip mechanism and many existing tests already require gpg. The test fails with a message naming the missing tool, so it never passes silently.The script needs python3 to read JSON. No jq is installed here, and python3 is more common in agent sandboxes.
Step 1 called gpg's default key "Ed25519". gpg 2.2 defaults to RSA, so the script names
ed25519explicitly and the reference no longer calls it the default.
Stage 5 - Invisible discovery
Changes:
<link rel="alternate" type="text/plain" href="/llms.txt" title="Agent guide">in the head oftemplates/layout.php, outside the members-only manifest block, and oftemplates/standalone_layout.php.No visible copy, navigation or icon changes.
docs/plans/ui_copy_audit_checklist.mdandtheme-nav-icons.cssare unaffected.
Verification:
php tests/run.php LlmsTxtRendererTest: 7 passed. The new test checks that/,/account/key/and/forte/users/(standalone layout) have the link in<head>and nowhere else, and that the members-only lobby page has it too.Full suite,
php tests/run.php: 1394 run, 1389 passed, 5 failed. All 5 are long-standing per the runner's history (failing since 2026-10-16 to 2026-10-19, before this branch):ApprovalSeedCommandTest::testApprovalIsEffectiveForExistingAuthenticatedMemberOnNextRequest,AgentIdentityServiceTest::testReplyAgentBootstrapCreatesApprovedIdentityAndPrivateKeyOutsidePublicArtifacts, twoLocalAppSmokeTeststatic-build tests, andReadModelBuilderTimingTest::testProgressSeparatesParsingDerivationAndWritingWithBoundedCounts.
Notes:
None.
Completion Contract status
Normal entry (
/llms.txt, from/api/or the page head): passed, by tests, including members-only instances.End-to-end outcome (gpg+curl script publishes a signed thread using only documented routes): passed,
AgentApiWorkedExampleTest.Recovery (documented errors with next actions; retry guidance): passed; error text checked against the code.
Deployment check on zenmemes (
/llms.txtand/api/facts match its flags): pending. The branch is not merged or deployed.Release condition (new tests pass; full suite has no new failures): passed.
Enhancement Requests
Request: commit the onboarding checklist to
mainand push it, so the user can work on other cycles elsewhere. / Disposition: separate work, done outside this branch (c6fe21b4onorigin/main); this branch is based on it. / Approval: requested by the user. / Outcome: pushed.Request: let
/llms.txtand/api/through the members-only gate. I found during Stage 2 that both returned the lobby page, so agents on members-only instances could not read them. / Disposition: in-scope refinement, needed for the Completion Contract's normal entry; it is an access-policy change, so I asked first. / Approval: the user chose "Allow both". / Outcome: implemented in Stage 2 with a test.