learn-cli 0.5.0__tar.gz → 0.5.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (238) hide show
  1. {learn_cli-0.5.0 → learn_cli-0.5.2}/.gitignore +3 -0
  2. {learn_cli-0.5.0 → learn_cli-0.5.2}/CHANGELOG.md +24 -0
  3. {learn_cli-0.5.0 → learn_cli-0.5.2}/PKG-INFO +1 -1
  4. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/profile/_ledger.py +26 -3
  5. {learn_cli-0.5.0 → learn_cli-0.5.2}/pyproject.toml +1 -1
  6. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/test_profile_store.py +17 -0
  7. {learn_cli-0.5.0 → learn_cli-0.5.2}/uv.lock +1 -1
  8. {learn_cli-0.5.0 → learn_cli-0.5.2}/workers/learn-api/README.md +46 -10
  9. {learn_cli-0.5.0 → learn_cli-0.5.2}/workers/learn-api/src/index.js +8 -2
  10. {learn_cli-0.5.0 → learn_cli-0.5.2}/workers/learn-api/test/worker.test.js +44 -0
  11. learn_cli-0.5.2/workers/learn-api/wrangler.signedout.toml +42 -0
  12. {learn_cli-0.5.0 → learn_cli-0.5.2}/workers/learn-api/wrangler.toml +22 -15
  13. {learn_cli-0.5.0 → learn_cli-0.5.2}/.claude/skills/agent-config/SKILL.md +0 -0
  14. {learn_cli-0.5.0 → learn_cli-0.5.2}/.claude/skills/agent-config/data/backend-fingerprints.yaml +0 -0
  15. {learn_cli-0.5.0 → learn_cli-0.5.2}/.claude/skills/agent-config/scripts/show.sh +0 -0
  16. {learn_cli-0.5.0 → learn_cli-0.5.2}/.claude/skills/ask-colleague/SKILL.md +0 -0
  17. {learn_cli-0.5.0 → learn_cli-0.5.2}/.claude/skills/ask-colleague/prompts/explore.md +0 -0
  18. {learn_cli-0.5.0 → learn_cli-0.5.2}/.claude/skills/ask-colleague/prompts/review.md +0 -0
  19. {learn_cli-0.5.0 → learn_cli-0.5.2}/.claude/skills/ask-colleague/prompts/write.md +0 -0
  20. {learn_cli-0.5.0 → learn_cli-0.5.2}/.claude/skills/ask-colleague/scripts/ask-colleague.sh +0 -0
  21. {learn_cli-0.5.0 → learn_cli-0.5.2}/.claude/skills/assign-to-workforce/SKILL.md +0 -0
  22. {learn_cli-0.5.0 → learn_cli-0.5.2}/.claude/skills/assign-to-workforce/scripts/assign-to-workforce.sh +0 -0
  23. {learn_cli-0.5.0 → learn_cli-0.5.2}/.claude/skills/cicd/SKILL.md +0 -0
  24. {learn_cli-0.5.0 → learn_cli-0.5.2}/.claude/skills/cicd/scripts/_resolve-nick.sh +0 -0
  25. {learn_cli-0.5.0 → learn_cli-0.5.2}/.claude/skills/cicd/scripts/portability-lint.sh +0 -0
  26. {learn_cli-0.5.0 → learn_cli-0.5.2}/.claude/skills/cicd/scripts/pr-reply.sh +0 -0
  27. {learn_cli-0.5.0 → learn_cli-0.5.2}/.claude/skills/cicd/scripts/pr-status.sh +0 -0
  28. {learn_cli-0.5.0 → learn_cli-0.5.2}/.claude/skills/cicd/scripts/workflow.sh +0 -0
  29. {learn_cli-0.5.0 → learn_cli-0.5.2}/.claude/skills/communicate/SKILL.md +0 -0
  30. {learn_cli-0.5.0 → learn_cli-0.5.2}/.claude/skills/communicate/scripts/fetch-issues.sh +0 -0
  31. {learn_cli-0.5.0 → learn_cli-0.5.2}/.claude/skills/communicate/scripts/mesh-message.sh +0 -0
  32. {learn_cli-0.5.0 → learn_cli-0.5.2}/.claude/skills/communicate/scripts/post-comment.sh +0 -0
  33. {learn_cli-0.5.0 → learn_cli-0.5.2}/.claude/skills/communicate/scripts/post-issue.sh +0 -0
  34. {learn_cli-0.5.0 → learn_cli-0.5.2}/.claude/skills/communicate/scripts/templates/skill-new-brief.md +0 -0
  35. {learn_cli-0.5.0 → learn_cli-0.5.2}/.claude/skills/communicate/scripts/templates/skill-update-brief.md +0 -0
  36. {learn_cli-0.5.0 → learn_cli-0.5.2}/.claude/skills/doc-test-alignment/SKILL.md +0 -0
  37. {learn_cli-0.5.0 → learn_cli-0.5.2}/.claude/skills/doc-test-alignment/scripts/check.sh +0 -0
  38. {learn_cli-0.5.0 → learn_cli-0.5.2}/.claude/skills/pypi-maintainer/SKILL.md +0 -0
  39. {learn_cli-0.5.0 → learn_cli-0.5.2}/.claude/skills/pypi-maintainer/scripts/switch-source.sh +0 -0
  40. {learn_cli-0.5.0 → learn_cli-0.5.2}/.claude/skills/recall/SKILL.md +0 -0
  41. {learn_cli-0.5.0 → learn_cli-0.5.2}/.claude/skills/recall/scripts/recall.sh +0 -0
  42. {learn_cli-0.5.0 → learn_cli-0.5.2}/.claude/skills/remember/SKILL.md +0 -0
  43. {learn_cli-0.5.0 → learn_cli-0.5.2}/.claude/skills/remember/scripts/remember.sh +0 -0
  44. {learn_cli-0.5.0 → learn_cli-0.5.2}/.claude/skills/run-tests/SKILL.md +0 -0
  45. {learn_cli-0.5.0 → learn_cli-0.5.2}/.claude/skills/run-tests/scripts/test.sh +0 -0
  46. {learn_cli-0.5.0 → learn_cli-0.5.2}/.claude/skills/sonarclaude/SKILL.md +0 -0
  47. {learn_cli-0.5.0 → learn_cli-0.5.2}/.claude/skills/sonarclaude/scripts/sonar.sh +0 -0
  48. {learn_cli-0.5.0 → learn_cli-0.5.2}/.claude/skills/spec-to-plan/SKILL.md +0 -0
  49. {learn_cli-0.5.0 → learn_cli-0.5.2}/.claude/skills/spec-to-plan/scripts/spec-to-plan.sh +0 -0
  50. {learn_cli-0.5.0 → learn_cli-0.5.2}/.claude/skills/think/SKILL.md +0 -0
  51. {learn_cli-0.5.0 → learn_cli-0.5.2}/.claude/skills/think/scripts/think.sh +0 -0
  52. {learn_cli-0.5.0 → learn_cli-0.5.2}/.claude/skills/version-bump/SKILL.md +0 -0
  53. {learn_cli-0.5.0 → learn_cli-0.5.2}/.claude/skills/version-bump/scripts/bump.py +0 -0
  54. {learn_cli-0.5.0 → learn_cli-0.5.2}/.claude/skills.local.yaml.example +0 -0
  55. {learn_cli-0.5.0 → learn_cli-0.5.2}/.devague/current +0 -0
  56. {learn_cli-0.5.0 → learn_cli-0.5.2}/.devague/current_plan +0 -0
  57. {learn_cli-0.5.0 → learn_cli-0.5.2}/.devague/frames/agentculture-org-learn-is-live-one-learning-hub-in.json +0 -0
  58. {learn_cli-0.5.0 → learn_cli-0.5.2}/.devague/plans/agentculture-org-learn-is-live-one-learning-hub-in.json +0 -0
  59. {learn_cli-0.5.0 → learn_cli-0.5.2}/.flake8 +0 -0
  60. {learn_cli-0.5.0 → learn_cli-0.5.2}/.github/workflows/deploy-site.yml +0 -0
  61. {learn_cli-0.5.0 → learn_cli-0.5.2}/.github/workflows/publish.yml +0 -0
  62. {learn_cli-0.5.0 → learn_cli-0.5.2}/.github/workflows/tests.yml +0 -0
  63. {learn_cli-0.5.0 → learn_cli-0.5.2}/.markdownlint-cli2.yaml +0 -0
  64. {learn_cli-0.5.0 → learn_cli-0.5.2}/AGENTS.colleague.md +0 -0
  65. {learn_cli-0.5.0 → learn_cli-0.5.2}/CLAUDE.md +0 -0
  66. {learn_cli-0.5.0 → learn_cli-0.5.2}/LICENSE +0 -0
  67. {learn_cli-0.5.0 → learn_cli-0.5.2}/README.md +0 -0
  68. {learn_cli-0.5.0 → learn_cli-0.5.2}/culture.yaml +0 -0
  69. {learn_cli-0.5.0 → learn_cli-0.5.2}/docs/hosting.md +0 -0
  70. {learn_cli-0.5.0 → learn_cli-0.5.2}/docs/plans/.markdownlint-cli2.yaml +0 -0
  71. {learn_cli-0.5.0 → learn_cli-0.5.2}/docs/plans/2026-07-10-agentculture-org-learn-is-live-one-learning-hub-in.md +0 -0
  72. {learn_cli-0.5.0 → learn_cli-0.5.2}/docs/skill-sources.md +0 -0
  73. {learn_cli-0.5.0 → learn_cli-0.5.2}/docs/specs/.markdownlint-cli2.yaml +0 -0
  74. {learn_cli-0.5.0 → learn_cli-0.5.2}/docs/specs/2026-07-10-agentculture-org-learn-is-live-one-learning-hub-in.md +0 -0
  75. {learn_cli-0.5.0 → learn_cli-0.5.2}/docs/specs/subject-plugin-contract.md +0 -0
  76. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/__init__.py +0 -0
  77. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/__main__.py +0 -0
  78. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/cli/__init__.py +0 -0
  79. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/cli/_commands/__init__.py +0 -0
  80. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/cli/_commands/auth.py +0 -0
  81. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/cli/_commands/cli.py +0 -0
  82. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/cli/_commands/doctor.py +0 -0
  83. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/cli/_commands/explain.py +0 -0
  84. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/cli/_commands/learn.py +0 -0
  85. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/cli/_commands/mcp.py +0 -0
  86. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/cli/_commands/next_cmd.py +0 -0
  87. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/cli/_commands/overview.py +0 -0
  88. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/cli/_commands/progress.py +0 -0
  89. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/cli/_commands/record.py +0 -0
  90. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/cli/_commands/site.py +0 -0
  91. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/cli/_commands/subject.py +0 -0
  92. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/cli/_commands/subjects.py +0 -0
  93. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/cli/_commands/whoami.py +0 -0
  94. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/cli/_errors.py +0 -0
  95. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/cli/_output.py +0 -0
  96. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/contract/__init__.py +0 -0
  97. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/contract/_validate.py +0 -0
  98. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/contract/schemas/advice.json +0 -0
  99. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/contract/schemas/doctor.json +0 -0
  100. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/contract/schemas/error.json +0 -0
  101. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/contract/schemas/lesson.json +0 -0
  102. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/contract/schemas/overview.json +0 -0
  103. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/contract/schemas/practice.json +0 -0
  104. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/contract/schemas/progress.json +0 -0
  105. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/contract/schemas/record.json +0 -0
  106. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/contract/schemas/story.json +0 -0
  107. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/contract/schemas/story_list.json +0 -0
  108. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/contract/schemas/story_read.json +0 -0
  109. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/explain/__init__.py +0 -0
  110. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/explain/catalog.py +0 -0
  111. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/front/__init__.py +0 -0
  112. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/front/_docs.py +0 -0
  113. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/front/_driver.py +0 -0
  114. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/front/_export.py +0 -0
  115. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/motivation/__init__.py +0 -0
  116. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/motivation/_constants.py +0 -0
  117. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/motivation/_decay.py +0 -0
  118. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/motivation/_models.py +0 -0
  119. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/motivation/_review.py +0 -0
  120. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/motivation/_scoring.py +0 -0
  121. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/motivation/_state.py +0 -0
  122. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/motivation/_streaks.py +0 -0
  123. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/motivation/_whatnext.py +0 -0
  124. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/profile/__init__.py +0 -0
  125. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/profile/_api.py +0 -0
  126. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/profile/_auth.py +0 -0
  127. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/profile/_paths.py +0 -0
  128. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/profile/_sync.py +0 -0
  129. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/profile/_syncstate.py +0 -0
  130. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/subjects/__init__.py +0 -0
  131. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/subjects/conformance.py +0 -0
  132. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/subjects/driver.py +0 -0
  133. {learn_cli-0.5.0 → learn_cli-0.5.2}/learn/subjects/registry.json +0 -0
  134. {learn_cli-0.5.0 → learn_cli-0.5.2}/site-astro/.gitignore +0 -0
  135. {learn_cli-0.5.0 → learn_cli-0.5.2}/site-astro/.nvmrc +0 -0
  136. {learn_cli-0.5.0 → learn_cli-0.5.2}/site-astro/README.md +0 -0
  137. {learn_cli-0.5.0 → learn_cli-0.5.2}/site-astro/astro.config.mjs +0 -0
  138. {learn_cli-0.5.0 → learn_cli-0.5.2}/site-astro/package-lock.json +0 -0
  139. {learn_cli-0.5.0 → learn_cli-0.5.2}/site-astro/package.json +0 -0
  140. {learn_cli-0.5.0 → learn_cli-0.5.2}/site-astro/public/apple-touch-icon.png +0 -0
  141. {learn_cli-0.5.0 → learn_cli-0.5.2}/site-astro/public/favicon.ico +0 -0
  142. {learn_cli-0.5.0 → learn_cli-0.5.2}/site-astro/public/favicon.svg +0 -0
  143. {learn_cli-0.5.0 → learn_cli-0.5.2}/site-astro/scripts/check-export-pages.mjs +0 -0
  144. {learn_cli-0.5.0 → learn_cli-0.5.2}/site-astro/scripts/check-static-auth.mjs +0 -0
  145. {learn_cli-0.5.0 → learn_cli-0.5.2}/site-astro/src/components/Footer.astro +0 -0
  146. {learn_cli-0.5.0 → learn_cli-0.5.2}/site-astro/src/components/Header.astro +0 -0
  147. {learn_cli-0.5.0 → learn_cli-0.5.2}/site-astro/src/components/LearnerPanelOverview.astro +0 -0
  148. {learn_cli-0.5.0 → learn_cli-0.5.2}/site-astro/src/components/LearnerPanelSubject.astro +0 -0
  149. {learn_cli-0.5.0 → learn_cli-0.5.2}/site-astro/src/components/Mark.astro +0 -0
  150. {learn_cli-0.5.0 → learn_cli-0.5.2}/site-astro/src/components/PageHero.astro +0 -0
  151. {learn_cli-0.5.0 → learn_cli-0.5.2}/site-astro/src/content-export/docs/portal.md +0 -0
  152. {learn_cli-0.5.0 → learn_cli-0.5.2}/site-astro/src/content-export/docs/subject-plugin-contract.md +0 -0
  153. {learn_cli-0.5.0 → learn_cli-0.5.2}/site-astro/src/content-export/docs/subjects.md +0 -0
  154. {learn_cli-0.5.0 → learn_cli-0.5.2}/site-astro/src/content-export/meta.json +0 -0
  155. {learn_cli-0.5.0 → learn_cli-0.5.2}/site-astro/src/content-export/stories-culture-guide.json +0 -0
  156. {learn_cli-0.5.0 → learn_cli-0.5.2}/site-astro/src/content-export/stories-french.json +0 -0
  157. {learn_cli-0.5.0 → learn_cli-0.5.2}/site-astro/src/content-export/stories-spanish.json +0 -0
  158. {learn_cli-0.5.0 → learn_cli-0.5.2}/site-astro/src/content-export/subjects.json +0 -0
  159. {learn_cli-0.5.0 → learn_cli-0.5.2}/site-astro/src/data/site.ts +0 -0
  160. {learn_cli-0.5.0 → learn_cli-0.5.2}/site-astro/src/layouts/Layout.astro +0 -0
  161. {learn_cli-0.5.0 → learn_cli-0.5.2}/site-astro/src/lib/api.ts +0 -0
  162. {learn_cli-0.5.0 → learn_cli-0.5.2}/site-astro/src/lib/content.ts +0 -0
  163. {learn_cli-0.5.0 → learn_cli-0.5.2}/site-astro/src/pages/[subject]/index.astro +0 -0
  164. {learn_cli-0.5.0 → learn_cli-0.5.2}/site-astro/src/pages/[subject]/stories/[id]/index.astro +0 -0
  165. {learn_cli-0.5.0 → learn_cli-0.5.2}/site-astro/src/pages/index.astro +0 -0
  166. {learn_cli-0.5.0 → learn_cli-0.5.2}/site-astro/src/scripts/learner.js +0 -0
  167. {learn_cli-0.5.0 → learn_cli-0.5.2}/site-astro/src/styles/global.css +0 -0
  168. {learn_cli-0.5.0 → learn_cli-0.5.2}/site-astro/tsconfig.json +0 -0
  169. {learn_cli-0.5.0 → learn_cli-0.5.2}/sonar-project.properties +0 -0
  170. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/__init__.py +0 -0
  171. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/conftest.py +0 -0
  172. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/e2e/__init__.py +0 -0
  173. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/e2e/conftest.py +0 -0
  174. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/e2e/test_cli_golden.py +0 -0
  175. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/e2e/test_mcp_harness.py +0 -0
  176. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/fixtures/motivation/completed_track_current.json +0 -0
  177. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/fixtures/motivation/completed_track_decayed.json +0 -0
  178. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/fixtures/motivation/cross_subject.json +0 -0
  179. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/fixtures/motivation/single_subject_progression.json +0 -0
  180. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/fixtures/payloads/advice.json +0 -0
  181. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/fixtures/payloads/doctor.json +0 -0
  182. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/fixtures/payloads/error.json +0 -0
  183. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/fixtures/payloads/lesson.json +0 -0
  184. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/fixtures/payloads/overview.json +0 -0
  185. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/fixtures/payloads/practice.json +0 -0
  186. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/fixtures/payloads/progress.json +0 -0
  187. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/fixtures/payloads/record.json +0 -0
  188. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/fixtures/payloads/story.json +0 -0
  189. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/fixtures/payloads/story_list.json +0 -0
  190. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/fixtures/payloads/story_read.json +0 -0
  191. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/fixtures/stories/culture-guide-scenario-overloaded-agent.json +0 -0
  192. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/fixtures/stories/french-beginner-le-marche.json +0 -0
  193. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/fixtures/stories/spanish-beginner-la-panaderia.json +0 -0
  194. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/fixtures/subjects/conformant_subject.py +0 -0
  195. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/fixtures/subjects/drifted_subject.py +0 -0
  196. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/test_auth_cli.py +0 -0
  197. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/test_cli.py +0 -0
  198. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/test_cli_faces.py +0 -0
  199. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/test_cli_introspection.py +0 -0
  200. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/test_contract_schemas.py +0 -0
  201. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/test_contract_validator.py +0 -0
  202. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/test_front_app.py +0 -0
  203. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/test_front_driver.py +0 -0
  204. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/test_motivation_decay_review.py +0 -0
  205. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/test_motivation_extras.py +0 -0
  206. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/test_motivation_golden.py +0 -0
  207. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/test_motivation_purity.py +0 -0
  208. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/test_motivation_scoring.py +0 -0
  209. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/test_motivation_streaks.py +0 -0
  210. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/test_motivation_whatnext.py +0 -0
  211. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/test_progress_next_record.py +0 -0
  212. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/test_site_export.py +0 -0
  213. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/test_story_fixtures.py +0 -0
  214. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/test_subject_doctor.py +0 -0
  215. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/test_subject_driver.py +0 -0
  216. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/test_subject_registry.py +0 -0
  217. {learn_cli-0.5.0 → learn_cli-0.5.2}/tests/test_surfaces_agree.py +0 -0
  218. {learn_cli-0.5.0 → learn_cli-0.5.2}/tools/launch-gate/.gitignore +0 -0
  219. {learn_cli-0.5.0 → learn_cli-0.5.2}/tools/launch-gate/README.md +0 -0
  220. {learn_cli-0.5.0 → learn_cli-0.5.2}/tools/launch-gate/api-server.mjs +0 -0
  221. {learn_cli-0.5.0 → learn_cli-0.5.2}/tools/launch-gate/launch_bar.py +0 -0
  222. {learn_cli-0.5.0 → learn_cli-0.5.2}/tools/launch-gate/package.json +0 -0
  223. {learn_cli-0.5.0 → learn_cli-0.5.2}/tools/launch-gate/report.py +0 -0
  224. {learn_cli-0.5.0 → learn_cli-0.5.2}/tools/launch-gate/run.sh +0 -0
  225. {learn_cli-0.5.0 → learn_cli-0.5.2}/tools/launch-gate/walk.mjs +0 -0
  226. {learn_cli-0.5.0 → learn_cli-0.5.2}/workers/learn-api/.gitignore +0 -0
  227. {learn_cli-0.5.0 → learn_cli-0.5.2}/workers/learn-api/package.json +0 -0
  228. {learn_cli-0.5.0 → learn_cli-0.5.2}/workers/learn-api/schema.sql +0 -0
  229. {learn_cli-0.5.0 → learn_cli-0.5.2}/workers/learn-api/src/auth.js +0 -0
  230. {learn_cli-0.5.0 → learn_cli-0.5.2}/workers/learn-api/src/db.js +0 -0
  231. {learn_cli-0.5.0 → learn_cli-0.5.2}/workers/learn-api/src/github.js +0 -0
  232. {learn_cli-0.5.0 → learn_cli-0.5.2}/workers/learn-api/src/progress.js +0 -0
  233. {learn_cli-0.5.0 → learn_cli-0.5.2}/workers/learn-api/src/session.js +0 -0
  234. {learn_cli-0.5.0 → learn_cli-0.5.2}/workers/learn-api/src/util.js +0 -0
  235. {learn_cli-0.5.0 → learn_cli-0.5.2}/workers/learn-api/src/validate.js +0 -0
  236. {learn_cli-0.5.0 → learn_cli-0.5.2}/workers/learn-api/test/helpers.js +0 -0
  237. {learn_cli-0.5.0 → learn_cli-0.5.2}/workers/learn-api/test/session.test.js +0 -0
  238. {learn_cli-0.5.0 → learn_cli-0.5.2}/workers/learn-api/test/validate.test.js +0 -0
@@ -232,3 +232,6 @@ skills.local.yaml
232
232
  # devague working state (not committed by default)
233
233
  .devague/reviews/
234
234
  .claude/settings.json
235
+
236
+ # wrangler local state (created by `wrangler pages deploy` at repo root)
237
+ .wrangler/
@@ -5,6 +5,30 @@ All notable changes to this project will be documented in this file.
5
5
  Format follows [Keep a Changelog](https://keepachangelog.com/). This project
6
6
  adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.5.2] - 2026-07-11
9
+
10
+ ### Added
11
+
12
+ - Phase-1 (signed-out) production deploy of agentculture.org/learn: Cloudflare Pages project agentculture-learn + proxy Worker owning the agentculture.org/learn/* zone route. Signed-out tour, all subject/story pages, and the 401 resource-gate are live; verified 38/38 by the LIVE_ORIGIN launch gate.
13
+ - workers/learn-api/wrangler.signedout.toml — the committed Phase-1 config (proxy-only: route + PAGES_ORIGIN, no KV/D1/secrets).
14
+
15
+ ### Changed
16
+
17
+ - workers/learn-api/README.md: document the two-phase go-live (signed-out live vs signed-in pending) and the exact token permissions each phase needs (Pages+Workers Scripts for Phase 1; +KV+D1 for Phase 2).
18
+
19
+ ### Fixed
20
+
21
+ - wrangler.toml: moved the routes array above the [vars] table. Under [vars], TOML scoped it as vars.routes and wrangler silently bound no route (No targets deployed).
22
+
23
+ ## [0.5.1] - 2026-07-11
24
+
25
+ ### Fixed
26
+
27
+ - API worker: the /learn zone-mount proxy strips Cookie/Authorization before forwarding to the Pages origin (review finding: session leak)
28
+ - API worker: withCors appends to an existing Vary header instead of overwriting it
29
+ - Profile ledger: created 0600 like auth.json (learner data is private)
30
+ - Profile ledger: a malformed ledger line is skipped instead of crashing progress/next/sync
31
+
8
32
  ## [0.5.0] - 2026-07-11
9
33
 
10
34
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: learn-cli
3
- Version: 0.5.0
3
+ Version: 0.5.2
4
4
  Summary: A CLI, MCP server, and web front for learning — a hosted site where humans and agents learn a subject step by step. Fronts the french-cli and spanish-cli language tutors, and generalizes to other learnable domains such as leading teams of agents. The learn command is the local operator surface and how agents drive it.
5
5
  Project-URL: Homepage, https://github.com/agentculture/learn-cli
6
6
  Project-URL: Issues, https://github.com/agentculture/learn-cli/issues
@@ -8,26 +8,44 @@ written to by ``learn record`` (never by a subject CLI directly) and read by
8
8
  every motivation computation. Append-only by design — nothing here ever
9
9
  rewrites or deletes a row, so the sync cursor (:mod:`learn.profile._syncstate`)
10
10
  can track "pushed so far" as a simple row count.
11
+
12
+ The ledger is learner data: the file is created ``0600`` (like ``auth.json``),
13
+ and a malformed line — a crash mid-append, a manual edit — is skipped rather
14
+ than crashing every ``progress``/``next``/sync flow. Because the ledger is
15
+ append-only and a malformed line never becomes valid, skipping is stable, so
16
+ the sync cursor's count-of-valid-rows arithmetic stays consistent across runs.
11
17
  """
12
18
 
13
19
  from __future__ import annotations
14
20
 
15
21
  import json
22
+ import os
16
23
  from typing import Any
17
24
 
18
25
  from learn.profile._paths import ensure_store_dir, ledger_path
19
26
 
27
+ #: Learner data is private to the local user, like ``auth.json``.
28
+ _LEDGER_MODE = 0o600
29
+
20
30
 
21
31
  def append_ledger(row: dict[str, Any]) -> None:
22
32
  """Append one row to the local ledger, creating the store dir if needed."""
23
33
  ensure_store_dir()
24
- with ledger_path().open("a", encoding="utf-8") as handle:
34
+ path = ledger_path()
35
+ created = not path.exists()
36
+ with path.open("a", encoding="utf-8") as handle:
25
37
  handle.write(json.dumps(row, ensure_ascii=False))
26
38
  handle.write("\n")
39
+ if created:
40
+ os.chmod(path, _LEDGER_MODE)
27
41
 
28
42
 
29
43
  def read_ledger() -> list[dict[str, Any]]:
30
- """Read every row, in append order. Empty list when the ledger doesn't exist yet."""
44
+ """Read every valid row, in append order. Empty list when no ledger exists yet.
45
+
46
+ A line that fails to parse (or parses to a non-object) is skipped — one
47
+ corrupt row must not take down ``progress``/``next``/sync.
48
+ """
31
49
  path = ledger_path()
32
50
  if not path.is_file():
33
51
  return []
@@ -37,7 +55,12 @@ def read_ledger() -> list[dict[str, Any]]:
37
55
  stripped = line.strip()
38
56
  if not stripped:
39
57
  continue
40
- rows.append(json.loads(stripped))
58
+ try:
59
+ parsed = json.loads(stripped)
60
+ except json.JSONDecodeError:
61
+ continue
62
+ if isinstance(parsed, dict):
63
+ rows.append(parsed)
41
64
  return rows
42
65
 
43
66
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "learn-cli"
3
- version = "0.5.0"
3
+ version = "0.5.2"
4
4
  description = "A CLI, MCP server, and web front for learning — a hosted site where humans and agents learn a subject step by step. Fronts the french-cli and spanish-cli language tutors, and generalizes to other learnable domains such as leading teams of agents. The learn command is the local operator surface and how agents drive it."
5
5
  readme = "README.md"
6
6
  license = "Apache-2.0"
@@ -72,6 +72,23 @@ def test_read_ledger_skips_blank_lines(profile_home) -> None:
72
72
  assert len(p.read_ledger()) == 1
73
73
 
74
74
 
75
+ def test_ledger_file_is_created_private(profile_home) -> None:
76
+ p.append_ledger({"subject": "french", "item_id": "fr.x", "result": "pass"})
77
+ mode = p.ledger_path().stat().st_mode & 0o777
78
+ assert mode == 0o600
79
+
80
+
81
+ def test_read_ledger_skips_malformed_lines(profile_home) -> None:
82
+ p.append_ledger({"subject": "french", "item_id": "fr.a", "result": "pass"})
83
+ with p.ledger_path().open("a", encoding="utf-8") as handle:
84
+ handle.write("{not json\n")
85
+ handle.write("[1, 2, 3]\n")
86
+ p.append_ledger({"subject": "french", "item_id": "fr.b", "result": "partial"})
87
+ rows = p.read_ledger()
88
+ assert [r["item_id"] for r in rows] == ["fr.a", "fr.b"]
89
+ assert p.ledger_count() == 2
90
+
91
+
75
92
  # --- auth state ------------------------------------------------------------
76
93
 
77
94
 
@@ -474,7 +474,7 @@ wheels = [
474
474
 
475
475
  [[package]]
476
476
  name = "learn-cli"
477
- version = "0.5.0"
477
+ version = "0.5.2"
478
478
  source = { editable = "." }
479
479
  dependencies = [
480
480
  { name = "agentfront", extra = ["mcp"] },
@@ -64,18 +64,43 @@ wrangler dev # serves http://localhost:8787
64
64
  For `wrangler dev`, put non-secret vars in `wrangler.toml` and provide dev
65
65
  secrets in a git-ignored `.dev.vars` file (see below).
66
66
 
67
- ## Provisioning (operator steps still owed)
67
+ ## Deploy status: two phases
68
68
 
69
- These steps are done once, by the operator, before the first deploy. Nothing
70
- here is committed.
69
+ The go-live is staged. **Phase 1 (signed-out) is LIVE** at
70
+ <https://agentculture.org/learn/> (deployed 2026-07-11); **Phase 2 (signed-in)
71
+ is pending** two operator-held credentials.
72
+
73
+ | | Phase 1 — signed-out (LIVE) | Phase 2 — signed-in (pending) |
74
+ | --- | --- | --- |
75
+ | Config | [`wrangler.signedout.toml`](wrangler.signedout.toml) | [`wrangler.toml`](wrangler.toml) |
76
+ | Serves | Static `/learn/*` proxied to Pages; `/api/*` returns 401 | + sessions, ledger, tutoring |
77
+ | KV / D1 | none | KV `SESSIONS` + D1 `learn-ledger` |
78
+ | Secrets | none | `SESSION_SECRET`, `GITHUB_CLIENT_SECRET`, `INFERENCE_TOKEN` |
79
+ | Token perms | Cloudflare Pages: Edit **+** Workers Scripts: Edit | **+** Workers KV Storage: Edit **+** D1: Edit |
80
+ | Deploy | `wrangler deploy -c wrangler.signedout.toml` | `wrangler deploy` |
81
+
82
+ The signed-out tier touches no storage and spends no inference — `/api/me` and
83
+ `POST /api/tutor` return `401` *before* any KV/D1 access (proven live by the
84
+ launch gate's "signed-out fires ONLY GET /api/me" walk). That is why Phase 1
85
+ deploys with a Pages+Workers token and nothing else.
86
+
87
+ **Phase 1 was deployed with the repo's `.env` token, which carries Pages: Edit
88
+ and Workers Scripts: Edit but NOT KV/D1.** To do Phase 2 self-serve, that token
89
+ needs **Workers KV Storage: Edit** and **D1: Edit** added (or swap in a token
90
+ that has them).
91
+
92
+ ## Provisioning Phase 2 (signed-in)
93
+
94
+ These steps are done once, by the operator, before the signed-in deploy.
95
+ Nothing here is committed.
71
96
 
72
97
  ### 1. Create the GitHub OAuth app
73
98
 
74
99
  Create an OAuth app at
75
100
  `https://github.com/settings/developers` (or in the AgentCulture org):
76
101
 
77
- - **Authorization callback URL:** `https://<worker-host>/api/auth/callback`
78
- (e.g. the route mounted under `agentculture.org/learn`).
102
+ - **Authorization callback URL:**
103
+ `https://agentculture.org/learn/api/auth/callback` (the live zone route).
79
104
  - **Enable Device Flow** — required for the CLI/MCP device sign-in (t12).
80
105
  - Requested scope is `read:user` only. Do **not** request `user:email`; the API
81
106
  never reads or stores email.
@@ -93,7 +118,16 @@ wrangler d1 execute learn-ledger --file schema.sql
93
118
 
94
119
  Copy the returned ids into `wrangler.toml` (replace the `REPLACE_ME_*`
95
120
  placeholders for `id`, `preview_id`, and `database_id`), and set
96
- `GITHUB_CLIENT_ID` there too (it is public).
121
+ `GITHUB_CLIENT_ID` there too (it is public). The route + `PUBLIC_URL` /
122
+ `APP_URL` / `CORS_ORIGIN` / `PAGES_ORIGIN` vars are already filled in
123
+ `wrangler.toml` from the live Phase-1 deploy.
124
+
125
+ Apply the schema to the **remote** D1 (the `--local` form only touches the
126
+ `wrangler dev` SQLite):
127
+
128
+ ```bash
129
+ wrangler d1 execute learn-ledger --remote --file schema.sql
130
+ ```
97
131
 
98
132
  ### 3. Set secrets
99
133
 
@@ -128,12 +162,14 @@ INFERENCE_TOKEN = "..."
128
162
  ### 4. Deploy
129
163
 
130
164
  ```bash
131
- wrangler deploy
165
+ wrangler deploy # uses wrangler.toml — full stack, same /learn/* route
132
166
  ```
133
167
 
134
- Then mount the Worker under the `agentculture.org/learn` zone via the
135
- operator-owned Cloudflare routing (coordinated with the `org` / cultureflare
136
- path — the same route that fronts the Pages site).
168
+ The `agentculture.org/learn/*` zone route is already live (Phase 1) and is
169
+ declared in `wrangler.toml`, so this deploy upgrades the *same* worker in place
170
+ — the route does not move. Confirm the signed-in path end-to-end afterward
171
+ (`GET /learn/api/me` with a real session cookie should `200`), then merge org's
172
+ Learn-nav link to open public discovery.
137
173
 
138
174
  ## Endpoint shapes for downstream waves
139
175
 
@@ -102,7 +102,13 @@ async function proxyToPages(request, env, url) {
102
102
  requireConfig(env, "PAGES_ORIGIN");
103
103
  const origin = env.PAGES_ORIGIN.replace(/\/+$/, "");
104
104
  const upstream = origin + url.pathname + url.search;
105
- return fetch(new Request(upstream, { method: request.method, headers: request.headers }));
105
+ // Never forward credentials to the static origin: the session cookie (and
106
+ // any Authorization header) is for this API only — the Pages origin serves
107
+ // public files and must not see learner sessions.
108
+ const headers = new Headers(request.headers);
109
+ headers.delete("Cookie");
110
+ headers.delete("Authorization");
111
+ return fetch(new Request(upstream, { method: request.method, headers }));
106
112
  }
107
113
 
108
114
  // --- public routes ---------------------------------------------------------
@@ -325,6 +331,6 @@ function withCors(env, request, response) {
325
331
  headers.set("Access-Control-Allow-Credentials", "true");
326
332
  headers.set("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
327
333
  headers.set("Access-Control-Allow-Headers", "Content-Type, Authorization");
328
- headers.set("Vary", "Origin");
334
+ headers.append("Vary", "Origin");
329
335
  return new Response(response.body, { status: response.status, headers });
330
336
  }
@@ -429,3 +429,47 @@ test("POST under the /learn site mount is rejected (read-only proxy)", async ()
429
429
  const res = await call(env, new Request(`${BASE}/learn/french/`, { method: "POST" }));
430
430
  assert.equal(res.status, 405);
431
431
  });
432
+
433
+ test("proxy to PAGES_ORIGIN strips Cookie and Authorization headers", async () => {
434
+ let seenHeaders = null;
435
+ const realFetch = globalThis.fetch;
436
+ globalThis.fetch = async (req) => {
437
+ seenHeaders = req.headers;
438
+ return new Response("ok", { status: 200 });
439
+ };
440
+ try {
441
+ const env = makeEnv({ PAGES_ORIGIN: "https://agentculture-learn.pages.dev" });
442
+ const req = new Request(`${BASE}/learn/french/`, {
443
+ headers: { Cookie: "session=supersecret", Authorization: "Bearer tok", Accept: "text/html" },
444
+ });
445
+ const res = await call(env, req);
446
+ assert.equal(res.status, 200);
447
+ assert.equal(seenHeaders.get("Cookie"), null);
448
+ assert.equal(seenHeaders.get("Authorization"), null);
449
+ assert.equal(seenHeaders.get("Accept"), "text/html");
450
+ } finally {
451
+ globalThis.fetch = realFetch;
452
+ }
453
+ });
454
+
455
+ test("withCors appends to an existing Vary header instead of overwriting", async () => {
456
+ let called = 0;
457
+ const realFetch = globalThis.fetch;
458
+ globalThis.fetch = async () => {
459
+ called += 1;
460
+ return new Response("ok", { status: 200, headers: { Vary: "Accept-Encoding" } });
461
+ };
462
+ try {
463
+ const env = makeEnv({
464
+ PAGES_ORIGIN: "https://agentculture-learn.pages.dev",
465
+ CORS_ORIGIN: "https://agentculture.org",
466
+ });
467
+ const res = await call(env, new Request(`${BASE}/learn/french/`, { headers: { Origin: "https://agentculture.org" } }));
468
+ assert.equal(called, 1);
469
+ const vary = res.headers.get("Vary");
470
+ assert.ok(vary.includes("Accept-Encoding"), `Vary lost upstream value: ${vary}`);
471
+ assert.ok(vary.includes("Origin"), `Vary missing Origin: ${vary}`);
472
+ } finally {
473
+ globalThis.fetch = realFetch;
474
+ }
475
+ });
@@ -0,0 +1,42 @@
1
+ # wrangler config — PHASE 1 (signed-out) deploy of the learn API Worker.
2
+ #
3
+ # This is the config that is LIVE in production today (deployed 2026-07-11).
4
+ # It stands up the whole SIGNED-OUT experience at agentculture.org/learn:
5
+ # the worker owns the /learn/* zone route and reverse-proxies every non-API
6
+ # path to the Cloudflare Pages origin (PAGES_ORIGIN). The signed-out tour is
7
+ # fully static; the resource-gated API routes (/api/me, /api/tutor, …) return
8
+ # 401 WITHOUT ever touching storage, so this deploy needs NO KV, NO D1, and
9
+ # NO secrets. It requires only two token permissions: Cloudflare Pages: Edit
10
+ # (for the Pages project) and Workers Scripts: Edit (for this worker + route).
11
+ #
12
+ # Deploy with:
13
+ # wrangler deploy -c wrangler.signedout.toml
14
+ #
15
+ # PHASE 2 (signed-in) uses the full ./wrangler.toml instead — it adds the KV
16
+ # namespace, the D1 ledger, the GitHub OAuth client id, and the secrets. That
17
+ # deploy additionally needs Workers KV Storage: Edit + D1: Edit on the token,
18
+ # and the GitHub OAuth app must exist first. See README.md "Provisioning".
19
+
20
+ name = "learn-api"
21
+ main = "src/index.js"
22
+ compatibility_date = "2024-11-01"
23
+ workers_dev = false
24
+
25
+ # Top-level key — MUST precede [vars] (see the gotcha note in wrangler.toml).
26
+ routes = [
27
+ { pattern = "agentculture.org/learn/*", zone_name = "agentculture.org" },
28
+ { pattern = "agentculture.org/learn", zone_name = "agentculture.org" },
29
+ ]
30
+
31
+ [vars]
32
+ # Placeholder client id: harmless in phase 1. The sign-in button is only
33
+ # reachable by direct navigation (org's Learn nav link is held until phase 2),
34
+ # so a non-functional OAuth start has no public surface yet.
35
+ GITHUB_CLIENT_ID = "REPLACE_ME_github_oauth_client_id"
36
+ PUBLIC_URL = "https://agentculture.org"
37
+ APP_URL = "https://agentculture.org/learn/"
38
+ CORS_ORIGIN = "https://agentculture.org"
39
+ PAGES_ORIGIN = "https://agentculture-learn.pages.dev"
40
+
41
+ [observability]
42
+ enabled = true
@@ -15,27 +15,34 @@ compatibility_date = "2024-11-01"
15
15
  # Node-compat is not required — the Worker uses only Web-standard APIs
16
16
  # (fetch, Request/Response, crypto.subtle, btoa/atob). Keep the bundle lean.
17
17
 
18
+ # --- Zone route (the same-origin /learn mount) -------------------------------
19
+ # Cloudflare Pages cannot be mounted at a path, so this ONE worker owns
20
+ # agentculture.org/learn/*: /learn/api/* is handled here, everything else
21
+ # proxies to PAGES_ORIGIN (which serves the site under /learn/ too).
22
+ #
23
+ # GOTCHA: `routes` is a TOP-LEVEL key and MUST appear ABOVE the [vars] table.
24
+ # Placed after [vars], TOML scopes it as `vars.routes` and wrangler silently
25
+ # ignores it ("No targets deployed") — the worker uploads but binds no route.
26
+ # This block is live in production (deployed 2026-07-11); the signed-out mount
27
+ # is served by exactly these two patterns.
28
+ routes = [
29
+ { pattern = "agentculture.org/learn/*", zone_name = "agentculture.org" },
30
+ { pattern = "agentculture.org/learn", zone_name = "agentculture.org" },
31
+ ]
32
+
18
33
  # --- Non-secret vars -------------------------------------------------------
19
34
  # INFERENCE_URL points at the cloudai-cli / ec2bedrock-cli SERVED endpoint
20
35
  # (an OpenAI-shaped HTTP API), NEVER a bespoke provider SDK. The broker only
21
36
  # ever POSTs JSON to this URL. Leave it unset to disable tutoring (broker 503s).
22
37
  [vars]
38
+ # GITHUB_CLIENT_ID is public; still REPLACE_ME until the GitHub OAuth app exists
39
+ # (needed only for the signed-in tier — see README "Phase 2").
23
40
  GITHUB_CLIENT_ID = "REPLACE_ME_github_oauth_client_id"
24
- # PUBLIC_URL = "https://agentculture.org" # origin used to build the OAuth callback
25
- # APP_URL = "https://agentculture.org/learn/" # where the web callback redirects post-login
26
- # CORS_ORIGIN = "https://agentculture.org" # allow the /learn site to call the API with creds
27
- # INFERENCE_URL = "https://<cloudai-or-ec2bedrock-served-endpoint>/v1/messages"
28
- # PAGES_ORIGIN = "https://agentculture-learn.pages.dev" # static-site origin the /learn zone mount proxies to
29
-
30
- # --- Zone route (the same-origin /learn mount) -------------------------------
31
- # Cloudflare Pages cannot be mounted at a path, so this ONE worker owns
32
- # agentculture.org/learn/*: /learn/api/* is handled here, everything else
33
- # proxies to PAGES_ORIGIN (which serves the site under /learn/ too).
34
- # Uncomment once the zone is reachable from this account's token:
35
- # routes = [
36
- # { pattern = "agentculture.org/learn/*", zone_name = "agentculture.org" },
37
- # { pattern = "agentculture.org/learn", zone_name = "agentculture.org" },
38
- # ]
41
+ PUBLIC_URL = "https://agentculture.org" # origin used to build the OAuth callback
42
+ APP_URL = "https://agentculture.org/learn/" # where the web callback redirects post-login
43
+ CORS_ORIGIN = "https://agentculture.org" # allow the /learn site to call the API with creds
44
+ PAGES_ORIGIN = "https://agentculture-learn.pages.dev" # static-site origin the /learn zone mount proxies to
45
+ # INFERENCE_URL = "https://<cloudai-or-ec2bedrock-served-endpoint>/v1/messages" # unset tutoring 503s
39
46
 
40
47
  # --- Secrets (NEVER committed) ---------------------------------------------
41
48
  # Set with: wrangler secret put <NAME>
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes