Implementation Plan

Publish HTML plans to GitHub Pages

completed
2026-06-07 agentics feature

Ship a GitHub Actions pipeline that publishes the entire docs/ tree to GitHub Pages, so every developer can browse all 32 HTML plans from one public URL — landing straight on the filterable plans gallery — instead of cloning the repo and opening files by hand.

Implement Read and implement all steps in the plan at docs/plans/publish-plans-to-github-pages.html — Publish all HTML plans to GitHub Pages for one-click browsing
File publish-plans-to-github-pages.html
Path docs/plans/publish-plans-to-github-pages.html
Acceptance criteria 0 / 8 done

Context

The repo already generates rich, self-contained HTML plans into docs/plans/ (32 of them today), and a PostToolUse hook (rebuild-plans-index.py) keeps docs/plans/index.html — a filterable gallery — current after every plan write. The one missing piece is reach: those files only exist on disk, so a developer has to clone the repo and open them in a local browser to read them.

GitHub Pages closes that gap. The repo (shawn-sandy/agentics) already runs GitHub Actions, so the cleanest fit is a dedicated Pages deploy workflow using the official actions/upload-pages-artifact + actions/deploy-pages pair, publishing the whole docs/ directory on every push to main. Two known footguns shape the approach: GitHub Pages runs Jekyll by default (which can mangle hand-built HTML and ignores _-prefixed paths) — neutralised with a .nojekyll marker; and a project Pages site is served under a base path (/agentics/), so the landing page must use a relative redirect. The gallery's own links are already relative, so they survive the base path unchanged.

Per the decisions taken while drafting: deploy via a GitHub Actions workflow (not branch/folder), and make the existing plans gallery the site's landing page via a root redirect, keeping docs/plans/index.html as the single hook-maintained source of truth.

Files to Modify

agentics/
  • .github/workflows/
    • deploy-pages.yml new Actions workflow that deploys docs/ to Pages
  • docs/
    • .nojekyll new disable Jekyll processing of hand-built HTML
    • index.html new root redirect to the plans gallery
  • README.md modified add a link/badge to the published site

Diagram

Publish pipeline
Trigger
push to main (docs/**)
also workflow_dispatch for manual runs
Build job
upload-pages-artifact (path: docs)
packs docs/ into a Pages artifact; .nojekyll skips Jekyll
Deploy job
deploy-pages
environment: github-pages · permissions: pages write, id-token write
Live site
shawn-sandy.github.io/agentics/
root redirects to plans/index.html gallery

Steps

1
done Add the docs/.nojekyll marker file
GitHub Pages runs the Jekyll static-site processor by default, which strips files and folders whose names start with an underscore and can rewrite hand-authored HTML. The plans are fully self-contained HTML — an empty .nojekyll file at the published root tells Pages to serve every byte verbatim.
Verify
test -f docs/.nojekyll && echo present prints present. The file is empty (zero bytes is fine).
2
done Create docs/index.html as a relative redirect to the plans gallery
Publishing all of docs/ means the site root resolves to docs/index.html, which does not yet exist — visitors would hit a 404. A tiny redirect page forwards the root to plans/index.html so visitors land directly on the filterable gallery (the chosen landing page), while docs/plans/index.html stays the single hook-maintained source of truth. Use a relative target (plans/index.html, not a leading slash) so it works under the /agentics/ Pages base path, plus a <meta http-equiv="refresh">, a canonical <link>, and a visible fallback anchor for no-JS/no-refresh clients.
Verify
Open docs/index.html in a browser from a local server — it immediately navigates to the plans gallery. grep -q 'plans/index.html' docs/index.html succeeds, and the href does not start with / (no absolute path that would break the base-path).
3
done Add the .github/workflows/deploy-pages.yml deploy workflow
This is the engine. The workflow triggers on push to main filtered to paths: ['docs/**', '.github/workflows/deploy-pages.yml'] (plus workflow_dispatch for manual re-runs), so changes to the workflow itself also trigger a redeploy. It declares the required permissions (pages: write, id-token: write, contents: read) and a concurrency group of pages with cancel-in-progress: false. A build job checks out, asserts docs/.nojekyll exists (fail fast if accidentally deleted), runs actions/configure-pages, and uploads docs via actions/upload-pages-artifact; a deploy job with environment: github-pages runs actions/deploy-pages. Pin every action to a commit SHA with a version comment, matching the convention in auto-version-bump.yml. Look up current SHAs from each action's releases page or the existing pinned versions in auto-version-bump.yml.
Verify
The file parses as YAML (e.g. python3 -c "import yaml,sys; yaml.safe_load(open('.github/workflows/deploy-pages.yml'))"). It declares both pages: write and id-token: write, a build and a deploy job, uploads artifact path docs, every uses: is pinned to a 40-char SHA, the path filter includes both docs/** and .github/workflows/deploy-pages.yml, and the build job asserts docs/.nojekyll exists before uploading the artifact.
4
done Enable GitHub Pages with source set to "GitHub Actions"
A deploy workflow cannot publish until Pages is enabled on the repo with the build type set to workflow (Pages is currently disabled — the API returns 404). This is a one-time repo setting that must be completed before the PR is merged, since the workflow will fail on first trigger if Pages is not enabled. Enable it with gh api -X POST repos/shawn-sandy/agentics/pages -f build_type=workflow, or via Settings → Pages → "Build and deployment" → Source: GitHub Actions. Requires admin on the repo. If admin access is unavailable, coordinate with a repo admin to complete this step before merging.
Verify
gh api repos/shawn-sandy/agentics/pages --jq .build_type returns workflow (no longer 404), and the response html_url shows https://shawn-sandy.github.io/agentics/.
5
done Add a "Browse the plans" link to README.md
The published site is only useful if people can find it. Add a short link (or shields.io badge) near the top of README.md pointing at https://shawn-sandy.github.io/agentics/ so the gallery is discoverable from the repo's front door. Keep it one line — this is a pointer, not a section.
Verify
grep -q 'shawn-sandy.github.io/agentics' README.md succeeds, and the link renders correctly in the GitHub README preview.
6
done Create test files in tests/pages/
The Tests section specifies three test scripts (test-pages-smoke.sh, test-root-redirect.sh, test-workflow-config.sh) but no earlier step creates them. Create mkdir -p tests/pages and write all three scripts with the assertions described in the Tests section. The unit and integration tests should be runnable locally as pre-merge validation; the smoke test runs post-deploy against the live URL with a retry loop (up to 5 attempts, 15s apart) to handle Pages propagation delay.
Verify
ls tests/pages/test-*.sh | wc -l returns 3. Each script is executable (chmod +x) and exits 0 when run against the expected inputs (local files for unit/integration, live URL for smoke).
7
done Merge to main, then confirm the first deploy serves the live gallery
The pipeline only proves itself end-to-end once it has actually run. After the change merges to main, the docs/** path filter fires the workflow; watch the run complete, then load the public URL and confirm the gallery and a sample plan render. This is the real acceptance gate — a green Actions run plus a reachable site.
Verify
gh run list --workflow=deploy-pages.yml --limit 1 shows a completed/success run. curl -sI https://shawn-sandy.github.io/agentics/ returns 200, and curl -s https://shawn-sandy.github.io/agentics/plans/ contains the gallery title Plans Library. A sample plan such as .../plans/add-tests-section-to-plans.html also returns 200.

Tests

Tier 1 — Code-touching plan
Objective Published Pages site serves the plans gallery and every plan

File: tests/pages/test-pages-smoke.sh

Type: smoke test (run post-deploy, e.g. a final step of deploy-pages.yml or manually against the live URL)

Asserts: the objective is actually met — GET https://shawn-sandy.github.io/agentics/ returns 200 and redirects to the gallery; /agentics/plans/ contains Plans Library; and a loop over every docs/plans/*.html filename confirms each returns 200 at /agentics/plans/<name> (all plans browsable — count derived dynamically from find docs/plans -name '*.html', not hardcoded). Includes a retry loop (up to 5 attempts, 15s apart) per URL to handle GitHub Pages propagation delay.

Run: bash tests/pages/test-pages-smoke.sh https://shawn-sandy.github.io/agentics

Unit Root redirect points at the gallery with a base-path-safe relative href

File: tests/pages/test-root-redirect.sh

Targets: docs/index.html

Key cases: file exists; contains a refresh/redirect to plans/index.html; the redirect target is relative (does not begin with / or http); a visible fallback anchor to the gallery is present for no-refresh clients.

Integration Deploy workflow is valid and correctly wired for Pages

File: tests/pages/test-workflow-config.sh

Targets: .github/workflows/deploy-pages.yml + docs/.nojekyll

Key cases: YAML parses; triggers on push to main with paths: docs/**; declares pages: write and id-token: write; has a build job uploading artifact path docs and a deploy job using actions/deploy-pages with environment: github-pages; all uses: pinned to SHAs; docs/.nojekyll exists so the artifact disables Jekyll.

Acceptance Criteria

Verification

End-to-end: after the change merges to main, confirm the deploy-pages.yml run completes successfully (gh run list --workflow=deploy-pages.yml shows success). Then load https://shawn-sandy.github.io/agentics/ in a browser — it should redirect to and display the plans gallery with all plan cards and working filter chips. Click into at least two plans (e.g. a normal plan and one ending in -review.html) and confirm they render with full styling, working checkboxes, and the sidebar table of contents. Spot-check that deep links work directly (paste a .../plans/<name>.html URL fresh). Finally, run the smoke test (bash tests/pages/test-pages-smoke.sh https://shawn-sandy.github.io/agentics) and confirm it passes for the root, the gallery, and all plan files; and verify the README link resolves to the live site.

Troubleshooting: If the first deploy fails, check: (1) GitHub Pages is enabled with build_type=workflow (Step 4), (2) the workflow has correct permissions (pages: write, id-token: write), (3) the artifact path is docs, not ./docs. If the site returns 404 after a green deploy, wait 60–90 seconds for Pages propagation. If the smoke test times out, verify the URL base path (/agentics/) matches the repo name.

Completion Checklist

Required

Completion Report

No items to report — all requirements met.

Next Steps

Build a top-level docs hub linking plans, media, and guides

Paste this prompt into Claude to execute this follow-up:

Create a docs/index.html landing hub for the agentics GitHub Pages site that links to the three existing galleries/sections: the plans gallery (docs/plans/index.html), the social media gallery (docs/media/social/index.html), and the guides directory (docs/guides/). Match the visual style of docs/plans/index.html (same CSS tokens, light theme). Replace the current root redirect with this hub. Keep all links relative so they work under the /agentics/ Pages base path. Do not change the deploy workflow.
Render the markdown guides as HTML for the published site

Paste this prompt into Claude to execute this follow-up:

The docs/guides/ directory contains 62 markdown files that will not render as formatted pages on GitHub Pages without Jekyll (which we disabled via .nojekyll). Add a build step to .github/workflows/deploy-pages.yml that converts docs/guides/*.md to self-contained HTML (reuse the plan-interview markdown-to-html skill's approach or a small pandoc/markdown step) and generates a guides index, all before the upload-pages-artifact step, so the guides are browsable on the published site. Keep the conversion output out of git (generated only in CI).
Wish List
Serve the site from a custom domain with full-text plan search Wish List

Speculative / blue-sky idea — not on the critical path. Paste into Claude when ready to explore:

Explore upgrading the agentics GitHub Pages site into a polished plan-browsing portal: (1) configure a custom domain (CNAME) instead of the github.io base path, (2) add a client-side full-text search across all plan HTML (build a JSON index of plan titles, objectives, and statuses at deploy time and wire a search box into the gallery), and (3) add per-plan-type and per-status landing pages. Recommend an approach that keeps everything static (no server) and works within GitHub Pages constraints, and outline the tradeoffs of a custom domain vs the project base path for relative links.
Team Review (2026-06-07 16:09:00 UTC) — 5 core reviewers

Executive Summary

The plan is approved with revisions. All 5 reviewers found the design architecturally sound, well-aligned with project conventions, and appropriately scoped. Three cross-reviewer concerns dominate: (1) the test files described in the Tests section had no corresponding creation step, (2) the Pages enablement ordering was implicit rather than enforced, and (3) there was no pre-deploy CI validation. Additionally, the plan hardcoded “32 plans” in acceptance criteria and used underscore-separated test filenames against the project’s kebab-case convention. All issues have been addressed with inline edits.

Role-by-Role Findings

Architecture Review

Fit: Architecturally sound — a thin static-site deployment layer that correctly avoids touching the existing hook-driven content pipeline.

  • Path filter gap (medium): workflow changes to deploy-pages.yml itself wouldn’t trigger a redeploy. Fixed: path filter now includes the workflow file.
  • No .nojekyll guard (low): accidental deletion would silently re-enable Jekyll. Fixed: build job now asserts .nojekyll exists.
  • Post-deploy-only smoke test (low): no pre-upload local validation of artifact completeness. Mitigated: new step 6 creates test files runnable pre-merge.

Completeness Review

Completeness: Well-structured with good specificity, but had two notable gaps.

  • Missing test file creation step (high): tests were specified but no step created them. Fixed: new Step 6 added.
  • Pages enablement ordering implicit (medium): no note that Step 4 must precede merge. Fixed: Step 4 now states “must be completed before the PR is merged.”
  • Hardcoded SHA lookups (medium): no guidance on where to find SHAs. Fixed: Step 3 now references action release pages and existing workflow.
  • Hardcoded “32” in AC6 (low): stale if plans are added/removed. Fixed: AC6 now says “all plan files present at deploy time.”

Testability Review

Test coverage: Present but thin — tests existed on paper but not as executable files, and there was no pre-merge CI gate.

  • No pre-deploy CI validation (high): only post-deploy smoke test. Mitigated: Step 6 creates tests; step 3 adds .nojekyll assertion. Unit/integration tests runnable locally pre-merge.
  • Hardcoded plan count in smoke test (low): Fixed: now derived dynamically via find.
  • No Jekyll-suppression test (medium): no test verifies .nojekyll is active. Partially addressed: build job .nojekyll assertion catches the most common failure mode.

Risk Review

Risk level: Medium overall.

  • Pages enablement prerequisite (high): workflow fails silently if Pages not enabled. Fixed: Step 4 strengthened with ordering requirement and admin access note.
  • Stale gallery index (medium): hook-maintained index could be stale if plan committed without hook. Noted: recommend CI-side index regeneration as a follow-up.
  • Public content is irreversible once indexed (medium): plans become public immediately. Noted: recommend a content audit before enabling Pages.
  • Smoke test propagation delay (low): no retry. Fixed: smoke test now specifies retry loop.

Conventions Review

Fit: Good alignment with project patterns overall.

  • Test file naming (medium): used underscores (test_*) instead of project-standard kebab-case. Fixed: all test files renamed to test-*.
  • Missing tests/pages/ directory creation (low): no step to mkdir. Fixed: included in new Step 6.

Agreements & Conflicts

Confirmed concerns (flagged by 2+ reviewers):

  • Missing test file creation step (Completeness + Testability)
  • Pages enablement ordering (Completeness + Risk)
  • No pre-deploy CI validation (Architecture + Testability)
  • Hardcoded plan count (Completeness + Testability)
  • Workflow path filter gap (Architecture + Risk)

No conflicts between reviewers.

Highest-Risk Issues (Priority Order)

  1. Pages must be enabled before merge — Risk reviewer (high). Fixed in Step 4.
  2. Test files must be created, not just described — Completeness reviewer (high). Fixed with new Step 6.
  3. No pre-deploy CI gate — Testability reviewer (high). Mitigated with .nojekyll assertion and local-runnable tests.
  4. Public content exposure — Risk reviewer (medium). Recommend content audit before enabling.
  5. Gallery index staleness in CI — Risk reviewer (medium). Recommend CI-side regeneration as follow-up.

Edits Applied

TargetActionChange
AC6 labeleditReplaced “All 32 plan files” with “All plan files present in docs/plans/ at deploy time”
Step 3 whyeditAdded workflow self-trigger path, .nojekyll assertion, SHA lookup guidance
Step 3 verifyeditAdded path-filter and .nojekyll assertion checks
Step 4 whyeditAdded “must be completed before PR is merged” and admin access note
After Step 5insertNew Step 6: Create test files in tests/pages/
Old Step 6editRenumbered to Step 7
All test filenameseditRenamed from underscore to kebab-case (test_* → test-*)
Objective testeditDynamic plan count + retry loop for propagation delay
VerificationeditRemoved hardcoded “32”; added troubleshooting paragraph
AC1 labeleditAdded workflow self-trigger and .nojekyll assertion mentions
Criteria listappendNew AC8: test scripts exist and pass locally
Progress labeleditUpdated from 0/7 to 0/8