Skip to content

Commit 38ad9c3

Browse files
authored
Merge pull request #7 from Doppp/agent/course-library-case-studies
Add local course library and model-learning tracks
2 parents 401522f + d1b9040 commit 38ad9c3

33 files changed

Lines changed: 1351 additions & 175 deletions

README.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ pnpm course
3131
```
3232

3333
Open the printed `http://127.0.0.1:4173` URL in the Codex built-in browser, a
34-
normal browser, or Claude Code Desktop Preview. In either coding host, ask:
34+
normal browser, or Claude Code Desktop Preview. The local library shows the
35+
foundation, shared research-skills course, and planned model specializations.
36+
Select an available course, then ask either coding host:
3537

3638
> Start the course.
3739
@@ -60,6 +62,11 @@ pnpm course:build
6062
pnpm test:browser
6163
```
6264

65+
`explorables start <path>` automatically recognizes either a standalone course
66+
containing `COURSE.md` or a local collection containing
67+
`explorables.library.json`. Run `pnpm course:foundation` to bypass the library
68+
and open the reference course directly.
69+
6370
## Author a course
6471

6572
```bash

apps/dev-preview/index.html

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@
77
<title>explorables course</title>
88
</head>
99
<body>
10-
<a class="skip-link" href="#lesson">Skip to lesson</a>
11-
<div id="root"></div>
10+
<nav aria-label="Skip links">
11+
<a class="skip-link" href="#root">Skip to content</a>
12+
</nav>
13+
<div id="root" tabindex="-1"></div>
1214
<script type="module" src="/src/main.tsx"></script>
1315
</body>
1416
</html>

apps/dev-preview/src/styles.css

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,140 @@ textarea {
8484
text-decoration: none;
8585
letter-spacing: -0.04em;
8686
}
87+
.brand-button {
88+
padding: 0;
89+
border: 0;
90+
background: transparent;
91+
cursor: pointer;
92+
}
93+
.course-library {
94+
width: min(100% - 2rem, 76rem);
95+
margin: 0 auto;
96+
padding: clamp(2rem, 6vw, 5rem) 0 6rem;
97+
}
98+
.library-hero {
99+
max-width: 58rem;
100+
margin-bottom: 4rem;
101+
}
102+
.library-eyebrow {
103+
margin: 3rem 0 0.5rem;
104+
}
105+
.library-title {
106+
margin: 0;
107+
}
108+
.library-hero > p:not(.eyebrow) {
109+
max-width: 48rem;
110+
font-size: 1.1rem;
111+
}
112+
.local-note {
113+
padding: 1rem 1.2rem;
114+
border-left: 4px solid var(--accent);
115+
background: var(--panel);
116+
color: var(--muted);
117+
}
118+
.library-track {
119+
margin-top: 4rem;
120+
}
121+
.track-heading {
122+
display: grid;
123+
grid-template-columns: 2.5rem minmax(0, 1fr);
124+
gap: 1rem;
125+
align-items: start;
126+
max-width: 52rem;
127+
}
128+
.track-heading > span {
129+
display: grid;
130+
width: 2.5rem;
131+
height: 2.5rem;
132+
place-items: center;
133+
border-radius: 50%;
134+
background: var(--accent);
135+
color: var(--bg);
136+
font-weight: 800;
137+
}
138+
.track-title,
139+
.track-summary {
140+
margin: 0;
141+
}
142+
.track-summary {
143+
color: var(--muted);
144+
}
145+
.course-grid {
146+
display: grid;
147+
grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
148+
gap: 1rem;
149+
margin-top: 1.5rem;
150+
}
151+
.course-card {
152+
display: flex;
153+
min-width: 0;
154+
flex-direction: column;
155+
padding: 1.25rem;
156+
border: 1px solid var(--border);
157+
border-radius: 0.8rem;
158+
background: var(--panel);
159+
}
160+
.featured-course {
161+
border-color: var(--accent);
162+
}
163+
.course-card-heading {
164+
display: flex;
165+
align-items: baseline;
166+
justify-content: space-between;
167+
gap: 1rem;
168+
}
169+
.course-status {
170+
margin: 0;
171+
color: var(--accent);
172+
font-size: 0.76rem;
173+
font-weight: 800;
174+
letter-spacing: 0.08em;
175+
text-transform: uppercase;
176+
}
177+
.course-card h3 {
178+
margin: 0.55rem 0 0;
179+
font-size: 1.35rem;
180+
line-height: 1.15;
181+
}
182+
.course-card > p:not(.course-status) {
183+
color: var(--muted);
184+
}
185+
.course-meta {
186+
font-size: 0.85rem;
187+
}
188+
.course-tags {
189+
display: flex;
190+
flex-wrap: wrap;
191+
gap: 0.4rem;
192+
margin: auto 0 1.2rem;
193+
padding: 0;
194+
list-style: none;
195+
}
196+
.course-tags li {
197+
padding: 0.18rem 0.5rem;
198+
border: 1px solid var(--border);
199+
border-radius: 999px;
200+
color: var(--muted);
201+
font-size: 0.75rem;
202+
}
203+
.course-action,
204+
.planned-label {
205+
display: inline-block;
206+
width: fit-content;
207+
margin-top: auto;
208+
padding: 0.6rem 0.8rem;
209+
border-radius: 0.4rem;
210+
font-weight: 750;
211+
}
212+
.course-action {
213+
background: var(--accent);
214+
color: var(--bg);
215+
text-decoration: none;
216+
}
217+
.planned-label {
218+
border: 1px dashed var(--border);
219+
color: var(--muted);
220+
}
87221
.course-title {
88222
margin: 1.5rem 0 0.75rem;
89223
color: var(--muted);

docs/PRD.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,24 @@ However, a `explorables` course is still a normal web project. The same course c
194194

195195
The course format must not require private Codex or Claude APIs.
196196

197+
## 3.8 Optional local course collections
198+
199+
A repository may contain `explorables.library.json` to present an ordered local
200+
learning path across multiple self-contained course packages. The manifest is
201+
an explicit allowlist of relative course roots; it is not a hosted catalogue,
202+
filesystem scan, marketplace, or remote installer.
203+
204+
The collection interface may also show clearly labelled planned courses so the
205+
curriculum path is visible. Planned entries cannot be opened. Every available
206+
course remains independently valid and runnable with its own `COURSE.md`, Agent
207+
Plugin manifest, portable skill, host adapters, exercises, and version.
208+
209+
The model-learning collection is structured as a vendor-neutral foundation, a
210+
shared frontier-research course, and separately versioned model-family case
211+
studies. Foundation lessons may include brief real-model connections in
212+
ordinary Markdown; release-specific reconstruction belongs in the appropriate
213+
case-study course.
214+
197215
---
198216

199217
# 4. Goals and non-goals
@@ -2548,6 +2566,9 @@ See how it works. Build it yourself.
25482566
- [ ] Explorable failures do not crash the whole course.
25492567
- [ ] Exercise links open the correct repository directory.
25502568
- [ ] Development errors include source file and line information.
2569+
- [ ] A local collection can list and open explicitly configured course roots.
2570+
- [ ] Planned collection entries are visibly unavailable and cannot be opened.
2571+
- [ ] Standalone course start and build behavior remains supported.
25512572

25522573
## Agent hosts
25532574

docs/architecture.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,35 @@ it directly or activate the portable skill. Claude Code Desktop retains a thin
115115
configuration. Both open localhost, read the same files, and run the same
116116
tests. No runtime package calls private host APIs.
117117

118+
## Local course collections
119+
120+
A standalone course remains the unit of distribution and Agent Plugin
121+
discovery. A repository may additionally contain `explorables.library.json` to
122+
present an explicit local learning path across several course packages.
123+
124+
```text
125+
explorables.library.json
126+
│ validate relative paths and course IDs
127+
128+
local library index
129+
│ select an available course
130+
131+
/courses/:courseId/course.json
132+
/courses/:courseId/course-files/*
133+
134+
135+
the same course runtime and iframe sandbox
136+
```
137+
138+
The manifest is an allowlist, not a directory scan. Available entries derive
139+
metadata from their contained `COURSE.md`; planned entries are
140+
presentation-only and cannot be opened. Collection routing never grants a
141+
course access outside its own root. The standalone `/course.json` and
142+
`/course-files/*` contract is preserved.
143+
144+
See [ADR 0005](decisions/0005-local-course-library.md) for the curriculum and
145+
distribution boundary.
146+
118147
## Deployment
119148

120149
The local course runtime is never deployed. Only `apps/site/dist` is uploaded

docs/course-authoring.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,3 +257,51 @@ Before publishing, test keyboard use and narrow layout, inspect the text-only
257257
fallback on GitHub, run from a clean checkout, declare licences for prose/code
258258
and third-party assets, then tag an immutable release. External compatible
259259
courses are unreviewed unless explicitly accepted by a catalogue review.
260+
261+
## 9. Assemble a local course collection
262+
263+
A repository containing several independent course packages may add
264+
`explorables.library.json` at its root. The manifest orders learning tracks and
265+
explicitly allowlists available course directories:
266+
267+
```json
268+
{
269+
"schemaVersion": 1,
270+
"title": "Systems learning path",
271+
"summary": "Start with foundations, then choose a specialization.",
272+
"tracks": [
273+
{
274+
"id": "foundations",
275+
"title": "Foundations",
276+
"summary": "Build the common baseline.",
277+
"courses": [
278+
{ "status": "available", "path": "courses/foundations" },
279+
{
280+
"status": "planned",
281+
"id": "advanced-systems",
282+
"title": "Advanced Systems",
283+
"summary": "A future specialization."
284+
}
285+
]
286+
}
287+
]
288+
}
289+
```
290+
291+
Available paths must be relative, remain inside the collection root, and point
292+
to independently valid courses. Their title, summary, version, lesson count,
293+
duration, and tags come from `COURSE.md`. Planned entries are visibly disabled
294+
and need enough metadata to explain the future course without implying it is
295+
installed.
296+
297+
The normal commands recognize either kind of root:
298+
299+
```bash
300+
pnpm exec explorables validate path/to/collection
301+
pnpm exec explorables start path/to/collection
302+
pnpm exec explorables build path/to/collection
303+
```
304+
305+
Collections do not scan the filesystem, clone repositories, install
306+
dependencies, or replace the plugin manifest and tutoring policy inside each
307+
course.
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# ADR 0005: Local course library and model-learning tracks
2+
3+
Status: accepted
4+
Date: 12 August 2026
5+
6+
## Context
7+
8+
The runtime originally accepted exactly one course root. That remains the right
9+
distribution boundary for an independently installable Agent Plugin, but the
10+
main repository now defines a family of prerequisite and model-specialization
11+
courses. Learners need to see that path and select locally available courses
12+
without a hosted LMS, account, database, remote catalogue, or filesystem scan.
13+
14+
The product also needs real frontier models to ground the foundation without
15+
making a durable introductory course track individual releases in depth.
16+
17+
## Decision
18+
19+
Add an optional `explorables.library.json` at a collection root. It explicitly
20+
orders tracks and contains two entry types:
21+
22+
- `available` entries point to a relative, contained course root and derive
23+
learner-facing metadata from that course's `COURSE.md`;
24+
- `planned` entries provide enough metadata to show the intended path while
25+
remaining visibly unavailable.
26+
27+
`explorables start <path>` and `explorables build <path>` detect either a
28+
standalone `COURSE.md` or a collection manifest. Collection mode serves a
29+
library index and namespaces course data and assets by validated course ID.
30+
Standalone commands, course schemas, plugin manifests, skills, and tutoring
31+
policies remain unchanged.
32+
33+
The model-learning curriculum has three layers:
34+
35+
1. `AI from First Principles` remains vendor-neutral and adds short real-model
36+
connections in ordinary Markdown.
37+
2. `Open Frontier Models: Shared Techniques` owns artifact reading, accounting,
38+
controlled comparison, provenance, and claim labels.
39+
3. Each model family remains a separate versioned course with pinned primary
40+
sources and controlled reconstructions.
41+
42+
The library displays prerequisites as an ordered path but does not lock
43+
courses. Planned cards are not install buttons, and the runtime does not clone
44+
repositories or install dependencies.
45+
46+
## Consequences
47+
48+
- A collection remains fully local and statically buildable.
49+
- Course packages can be extracted into independent repositories without
50+
changing their format.
51+
- Browser progress remains isolated by course ID and version.
52+
- Collection validation must reject duplicate IDs, absolute paths, traversal,
53+
symlink escapes, and invalid contained courses.
54+
- A bad or missing course route must fail independently.
55+
- Adding a public catalogue or remote installer remains a separate,
56+
trust-sensitive feature.

docs/implementation-plan.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,3 +144,22 @@ Deliverables:
144144

145145
Exit check: both example courses and a newly scaffolded course validate as
146146
Agent Plugins v1 packages, then pass the full repository check and build.
147+
148+
## Milestone 8 — local course library and case-study path
149+
150+
Deliverables:
151+
152+
- Optional validated `explorables.library.json` with ordered tracks, contained
153+
available-course paths, and honest planned-course metadata.
154+
- Local and static collection routes with course-scoped data/assets, safe deep
155+
links, standalone-course compatibility, and isolated guided progress.
156+
- Accessible normal/narrow library UI for the foundation, shared research core,
157+
and model-family specializations.
158+
- Real-model connection sections across all thirteen foundation lessons while
159+
keeping release-specific reconstruction in separate planned courses.
160+
- Updated PRD, architecture, roadmap, source register, status, and ADR.
161+
162+
Exit check: collection and standalone validation/build pass; browser tests
163+
cover selection, planned states, deep links, guidance, sandboxing, narrow
164+
layout, and axe; the full repository check and build pass under Node 24 and
165+
pnpm 11.

0 commit comments

Comments
 (0)