@a-company/paradigm 6.1.0 → 6.2.1
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.
- package/dist/arch-5UVPSOG2.js +3 -0
- package/dist/arch-loader-T3TARMSO.js +2 -0
- package/dist/chunk-ARLB6YYW.js +3 -0
- package/dist/chunk-EMGJWT7D.js +111 -0
- package/dist/chunk-MA75GS7J.js +635 -0
- package/dist/chunk-SU5F5D4I.js +3 -0
- package/dist/index.js +6 -6
- package/dist/mcp.js +3 -52
- package/dist/reindex-PJVOMN57.js +2 -0
- package/dist/tools-BPEKRC2U.js +2 -0
- package/dist/university-content/notes/.purpose +14 -0
- package/dist/university-content/notes/N-para-701-arch-mcp-tools.md +149 -0
- package/dist/university-content/notes/N-para-701-arch-yaml-format.md +123 -0
- package/dist/university-content/notes/N-para-701-atlas-agent.md +83 -0
- package/dist/university-content/paths/.purpose +12 -0
- package/dist/university-content/paths/LP-para-701.yaml +15 -0
- package/dist/university-content/quizzes/.purpose +14 -0
- package/dist/university-content/quizzes/Q-para-701-arch-mcp-tools.yaml +66 -0
- package/dist/university-content/quizzes/Q-para-701-arch-yaml-format.yaml +66 -0
- package/dist/university-content/quizzes/Q-para-701-atlas-agent.yaml +66 -0
- package/dist/university-content/quizzes/Q-plsat-v3.yaml +126 -1
- package/dist/university-ui/assets/{index-CkgaxOXi.js → index-SNyIB61M.js} +2 -2
- package/dist/university-ui/assets/{index-CkgaxOXi.js.map → index-SNyIB61M.js.map} +1 -1
- package/dist/university-ui/index.html +1 -1
- package/package.json +1 -1
- package/dist/chunk-K7EQHFZP.js +0 -111
- package/dist/chunk-MOVDVBU7.js +0 -605
- package/dist/reindex-GSRV4MQO.js +0 -2
- package/dist/tools-VNDXOFXR.js +0 -2
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
id: Q-para-701-arch-mcp-tools
|
|
2
|
+
title: 'PARA 701: Agent Mastery — Lesson 13: The arch MCP Tools'
|
|
3
|
+
description: 'Quiz for lesson: Lesson 13: The arch MCP Tools'
|
|
4
|
+
author: paradigm
|
|
5
|
+
created: '2026-04-28'
|
|
6
|
+
updated: '2026-04-28'
|
|
7
|
+
tags:
|
|
8
|
+
- course
|
|
9
|
+
- para-701
|
|
10
|
+
symbols: []
|
|
11
|
+
difficulty: intermediate
|
|
12
|
+
passThreshold: 0.7
|
|
13
|
+
category: paradigm-core
|
|
14
|
+
origin: imported
|
|
15
|
+
source: courses/para-701.json
|
|
16
|
+
questions:
|
|
17
|
+
- id: q1
|
|
18
|
+
question: A developer wants to know which newly-added components are not yet assigned to any architectural tier. Which tool should they call, and which field in the response answers the question?
|
|
19
|
+
choices:
|
|
20
|
+
A: paradigm_arch_diagram — the diagram visually shows unassigned nodes
|
|
21
|
+
B: paradigm_arch_status — check drift.unassigned for component symbols that exist in the index but are not in any tier
|
|
22
|
+
C: paradigm_status — it includes drift information in the main status response
|
|
23
|
+
D: paradigm_arch_status — check drift.missing_purpose for components not in any tier
|
|
24
|
+
E: paradigm_search — search for components with type "unassigned"
|
|
25
|
+
correct: B
|
|
26
|
+
explanation: paradigm_arch_status returns a drift object with two arrays. drift.unassigned contains component symbols that are indexed (documented) but not listed in any tier's components array — these are the newly-added components with no tier assignment. drift.missing_purpose is the inverse: components declared in arch.yaml that do not appear in the index. paradigm_arch_diagram renders the declared tiers but does not show drift; paradigm_status does not include arch.yaml drift.
|
|
27
|
+
- id: q2
|
|
28
|
+
question: A project does not have a `.paradigm/arch.yaml` file. A developer calls `paradigm_arch_status`. What happens?
|
|
29
|
+
choices:
|
|
30
|
+
A: The tool throws an error and the MCP session crashes
|
|
31
|
+
B: The tool returns a JSON object with exists=false and a message explaining that arch.yaml was not found, with guidance on how to create it
|
|
32
|
+
C: The tool is not listed in the tool registry at all — it cannot be called on projects without arch.yaml
|
|
33
|
+
D: The tool returns an empty tier list with zero drift
|
|
34
|
+
E: The tool automatically creates a minimal arch.yaml and returns its contents
|
|
35
|
+
correct: B
|
|
36
|
+
explanation: "The tool handles the missing-file case gracefully: it returns {\"exists\": false, \"message\": \"No arch.yaml found. Create .paradigm/arch.yaml to start mapping your architecture.\"}. However, the tool detection note adds nuance: the arch module registers with a `detect` function that checks for arch.yaml. If the file doesn't exist, the tools are not included in the tool list. A developer who calls the tool directly (knowing its name) after the file was deleted would get the graceful JSON response. The session does not crash either way."
|
|
37
|
+
- id: q3
|
|
38
|
+
question: An engineer wants to generate a Mermaid diagram to paste into a pull request description. Which of the following is the correct approach?
|
|
39
|
+
choices:
|
|
40
|
+
A: Call paradigm_arch_status and extract the diagram field from the response
|
|
41
|
+
B: Call paradigm_arch_diagram — it returns a JSON object with a `diagram` field containing the Mermaid graph string, or use `paradigm arch diagram` from the CLI
|
|
42
|
+
C: Call paradigm_arch_status with format="mermaid" to get the diagram
|
|
43
|
+
D: Manually write the Mermaid diagram by reading arch.yaml — the tools do not generate diagrams
|
|
44
|
+
E: Call paradigm_arch_diagram with output="clipboard" to copy it automatically
|
|
45
|
+
correct: B
|
|
46
|
+
explanation: "paradigm_arch_diagram is the dedicated diagram tool. It returns {\"format\": \"mermaid\", \"diagram\": \"graph TD\\n ...\"} where the diagram field is the Mermaid string ready for copy-paste. The CLI equivalent is `paradigm arch diagram` — on macOS, piping to `pbcopy` copies it to the clipboard. paradigm_arch_status does not include a diagram field; it focuses on tier metadata and drift. There is no `format` parameter on paradigm_arch_status."
|
|
47
|
+
- id: q4
|
|
48
|
+
question: A project has `.paradigm/arch.yaml`. An agent calls `paradigm_arch_status` and receives `drift.clean: false` with `drift.unassigned` containing 5 symbols and `drift.missing_purpose` containing 2 symbols. What is the correct interpretation?
|
|
49
|
+
choices:
|
|
50
|
+
A: The build is blocked — drift.clean must be true before deployment
|
|
51
|
+
B: 5 components are in the index but not assigned to any tier; 2 components are declared in arch.yaml tiers but do not appear in the index. Neither condition blocks anything — this is advisory information.
|
|
52
|
+
C: 5 components have no .purpose files; 2 components have missing portal.yaml gate declarations
|
|
53
|
+
D: The arch.yaml file has 5 syntax errors and 2 missing required fields
|
|
54
|
+
E: drift.clean: false means the previous build introduced breaking changes
|
|
55
|
+
correct: B
|
|
56
|
+
explanation: "drift.clean: false means at least one drift category is non-empty. drift.unassigned (5 items) means 5 component symbols exist in the symbol index but have no tier assignment in arch.yaml — likely new components added after arch.yaml was last updated. drift.missing_purpose (2 items) means 2 component IDs in arch.yaml tiers cannot be found in the index — likely renamed or deleted components. Neither is a blocker. Atlas reports this information so the team can decide whether to update arch.yaml."
|
|
57
|
+
- id: q5
|
|
58
|
+
question: Why are the arch tools registered in the `feature` tier of the MCP registry rather than the `core` tier?
|
|
59
|
+
choices:
|
|
60
|
+
A: Feature-tier tools cost fewer tokens to list than core-tier tools
|
|
61
|
+
B: Feature-tier tools are auto-detected — the arch module uses a `detect` function that checks for arch.yaml. If the file doesn't exist, the tools are not listed, saving token budget for projects that don't use architectural mapping
|
|
62
|
+
C: Feature-tier tools require manual activation via paradigm_tool_activate before they can be called
|
|
63
|
+
D: Core-tier tools are reserved for Anthropic-approved tools only
|
|
64
|
+
E: The arch tools are in the feature tier because they were added after the core tier was finalized
|
|
65
|
+
correct: B
|
|
66
|
+
explanation: The feature tier supports auto-detection via a `detect` function. For arch tools, detect checks whether `.paradigm/arch.yaml` exists. If it does, both arch tools are included in the tool list. If not, they are omitted entirely. This keeps the tool list lean for projects that have not declared an architectural map. Advanced-tier tools require manual `paradigm_tool_activate` to load; feature-tier tools are automatic based on detection. Core-tier tools are always loaded regardless of project state.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
id: Q-para-701-arch-yaml-format
|
|
2
|
+
title: 'PARA 701: Agent Mastery — Lesson 11: The arch.yaml Format'
|
|
3
|
+
description: 'Quiz for lesson: Lesson 11: The arch.yaml Format'
|
|
4
|
+
author: paradigm
|
|
5
|
+
created: '2026-04-28'
|
|
6
|
+
updated: '2026-04-28'
|
|
7
|
+
tags:
|
|
8
|
+
- course
|
|
9
|
+
- para-701
|
|
10
|
+
symbols: []
|
|
11
|
+
difficulty: intermediate
|
|
12
|
+
passThreshold: 0.7
|
|
13
|
+
category: paradigm-core
|
|
14
|
+
origin: imported
|
|
15
|
+
source: courses/para-701.json
|
|
16
|
+
questions:
|
|
17
|
+
- id: q1
|
|
18
|
+
question: A team adds a new component `#notification-service` to the backend. Their `.paradigm/arch.yaml` was last updated six months ago and does not list this component in any tier. When Atlas runs, how will this component appear in the drift report?
|
|
19
|
+
choices:
|
|
20
|
+
A: As a "missing_purpose" entry — the component is listed in arch.yaml but not in the index
|
|
21
|
+
B: As an "unassigned" entry — the component exists in the symbol index but is not assigned to any tier
|
|
22
|
+
C: Atlas will not report it because arch.yaml does not need to be updated
|
|
23
|
+
D: Atlas will automatically add it to the backend tier
|
|
24
|
+
E: The drift report only includes gate symbols, not components
|
|
25
|
+
correct: B
|
|
26
|
+
explanation: "Unassigned drift means: component exists in the symbol index but is not listed in any tier's components array. The component was indexed (via .purpose coverage) but arch.yaml was not updated to include it. Missing_purpose is the inverse: declared in arch.yaml but not found in the index. Atlas never auto-assigns components — it reports drift as advisory findings for the team to resolve."
|
|
27
|
+
- id: q2
|
|
28
|
+
question: Which of the following arch.yaml configurations is valid?
|
|
29
|
+
choices:
|
|
30
|
+
A: A tier with no `id` field but a `label` field
|
|
31
|
+
B: A `links` array with an entry that has `from` and `to` pointing to tier IDs, and an optional `via` label
|
|
32
|
+
C: A `components` array containing `$checkout-flow` (a flow symbol)
|
|
33
|
+
D: Omitting the `links` key entirely from the file
|
|
34
|
+
E: Using camelCase for tier IDs (e.g., `id: frontEnd`)
|
|
35
|
+
correct: B
|
|
36
|
+
explanation: "Links require `from` and `to` (both referencing tier IDs) and accept an optional `via` label for edge labeling in Mermaid diagrams. Tier `id` is required — a label alone is not sufficient. The `components` array holds `#component` symbols only, not `$flows`. The `links` key is required (though it can be an empty array `[]`). Tier IDs should use kebab-case per Paradigm conventions."
|
|
37
|
+
- id: q3
|
|
38
|
+
question: A startup is three months into development. They have 40 components, 6 flows, and 12 gates indexed by Paradigm. Should they create `.paradigm/arch.yaml`?
|
|
39
|
+
choices:
|
|
40
|
+
A: Yes — arch.yaml is required for gate checking to work
|
|
41
|
+
B: Yes — without it, the symbol index will not build
|
|
42
|
+
C: No — arch.yaml is required only for projects with more than 100 components
|
|
43
|
+
D: It depends — arch.yaml is optional additive metadata. They should create it if they want tier-level architecture documentation, drift detection, or diagrams. It is not required for any core Paradigm feature.
|
|
44
|
+
E: No — arch.yaml is only for enterprise projects
|
|
45
|
+
correct: D
|
|
46
|
+
explanation: "arch.yaml is entirely optional. All core Paradigm features — orchestration, symbol indexing, gate checking, notebook learning, lore recording — work without it. The file is additive metadata that enables tier-level documentation, drift detection via Atlas, and Mermaid diagram rendering. A three-month project with 40 components may benefit from declaring their tier structure, but there is no requirement to do so."
|
|
47
|
+
- id: q4
|
|
48
|
+
question: A project's arch.yaml declares `#legacy-payment-gateway` in the backend tier. Six months later, the team deprecated and deleted that component. What drift will Atlas report?
|
|
49
|
+
choices:
|
|
50
|
+
A: Unassigned — the component was removed from the index
|
|
51
|
+
B: Missing Purpose — the component is listed in arch.yaml but no longer exists in the symbol index
|
|
52
|
+
C: No drift — deleted components are automatically removed from arch.yaml
|
|
53
|
+
D: Critical error — Atlas will block the build
|
|
54
|
+
E: Unassigned and Missing Purpose simultaneously
|
|
55
|
+
correct: B
|
|
56
|
+
explanation: "Missing Purpose drift means: a component is declared in a tier's components array in arch.yaml, but it cannot be found in the live symbol index. When a component is deleted (its .purpose entry removed and paradigm scan run), it disappears from the index. The arch.yaml entry remains until manually updated. Atlas reports this as missing_purpose so the team knows the map is stale. Atlas never blocks — it is advisory-only."
|
|
57
|
+
- id: q5
|
|
58
|
+
question: What does the `via` field on a link do?
|
|
59
|
+
choices:
|
|
60
|
+
A: It declares which gate must be satisfied when crossing from one tier to another
|
|
61
|
+
B: It specifies the network protocol (HTTP, gRPC, WebSocket) for rate-limiting purposes
|
|
62
|
+
C: It provides a human-readable edge label that appears in the Mermaid diagram output
|
|
63
|
+
D: It is required for all links — omitting it causes a parse error
|
|
64
|
+
E: It declares the intermediate tier a message passes through before reaching the destination
|
|
65
|
+
correct: C
|
|
66
|
+
explanation: "The `via` field is an optional human-readable label placed on the edge between two tiers in the generated Mermaid diagram. For example, `via: REST API` renders as `frontend -->|\"REST API\"| backend` in Mermaid syntax. It has no functional effect on orchestration, gate checking, or drift detection — it is purely for diagram readability. Omitting it is valid; the edge renders without a label."
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
id: Q-para-701-atlas-agent
|
|
2
|
+
title: 'PARA 701: Agent Mastery — Lesson 12: Atlas — The Cartographer Agent'
|
|
3
|
+
description: 'Quiz for lesson: Lesson 12: Atlas — The Cartographer Agent'
|
|
4
|
+
author: paradigm
|
|
5
|
+
created: '2026-04-28'
|
|
6
|
+
updated: '2026-04-28'
|
|
7
|
+
tags:
|
|
8
|
+
- course
|
|
9
|
+
- para-701
|
|
10
|
+
symbols: []
|
|
11
|
+
difficulty: intermediate
|
|
12
|
+
passThreshold: 0.7
|
|
13
|
+
category: paradigm-core
|
|
14
|
+
origin: imported
|
|
15
|
+
source: courses/para-701.json
|
|
16
|
+
questions:
|
|
17
|
+
- id: q1
|
|
18
|
+
question: A Builder agent has just completed implementing a new `#analytics-service` component. The project has a `.paradigm/arch.yaml` with three declared tiers. In the standard orchestration pipeline, when does Atlas run relative to the Documentor?
|
|
19
|
+
choices:
|
|
20
|
+
A: Atlas runs before the Builder, to predict what components will be created
|
|
21
|
+
B: Atlas and the Documentor run simultaneously in parallel
|
|
22
|
+
C: Atlas runs after the Builder stage and before (or alongside) the Documentor — he surfaces unassigned components from the new build before the Documentor writes .purpose updates
|
|
23
|
+
D: Atlas only runs when explicitly called by the user — he never fires automatically in orchestration
|
|
24
|
+
E: Atlas runs after the Documentor, so he can use the updated .purpose files as input
|
|
25
|
+
correct: C
|
|
26
|
+
explanation: Atlas fires after the Builder completes and before (or alongside) the Documentor in the post-build review pipeline. When arch.yaml exists, Atlas checks whether the newly built components have been assigned to tiers. The Documentor focuses on .purpose coverage. Both are post-Builder agents, but Atlas surfaces tier-level drift while the Documentor handles symbol-level gaps. Running Atlas before the Documentor ensures architectural drift is visible before .purpose work begins.
|
|
27
|
+
- id: q2
|
|
28
|
+
question: Why is Atlas a tier-1 (opus) agent rather than a tier-3 (haiku) agent?
|
|
29
|
+
choices:
|
|
30
|
+
A: Tier-1 means Atlas runs first in every orchestration, not that he uses a more capable model
|
|
31
|
+
B: Atlas is tier-1 because architectural reasoning — explaining what drift means and how to resolve it in context — requires deep understanding of symbol relationships, which benefits from a more capable model
|
|
32
|
+
C: All agents that deal with YAML files are tier-1 by convention
|
|
33
|
+
D: Atlas was assigned tier-1 because cartography is a premium feature
|
|
34
|
+
E: Atlas is tier-1 because he has write access to source files
|
|
35
|
+
correct: B
|
|
36
|
+
explanation: Tier assignment reflects the cognitive complexity of the agent's work. Tier-1 (opus) is for decision-makers and agents whose reasoning depth directly affects output quality. Atlas earns tier-1 because his value is not in parsing YAML (any model can do that), but in explaining what architectural drift means in the context of a specific project — why certain components ended up unassigned, what that implies for the team, and how to prioritize resolution. Shallow analysis here produces misleading or useless drift reports.
|
|
37
|
+
- id: q3
|
|
38
|
+
question: A project's arch.yaml has 5 tiers. Atlas reports 12 unassigned components after a large feature build. What should the team do?
|
|
39
|
+
choices:
|
|
40
|
+
A: Immediately fix the build — Atlas's report means the deployment pipeline is blocked
|
|
41
|
+
B: Ignore the report permanently — Atlas only reports cosmetic information
|
|
42
|
+
C: Evaluate the drift at their own pace — they can update arch.yaml to assign components to tiers, leave genuinely cross-cutting utilities unassigned, or declare a new tier if the build introduced a distinct new layer
|
|
43
|
+
D: Ask Atlas to automatically assign the components to the most likely tier
|
|
44
|
+
E: Delete arch.yaml to stop Atlas from running
|
|
45
|
+
correct: C
|
|
46
|
+
explanation: "Atlas is advisory-only — he never blocks. The team has three valid paths: (1) update arch.yaml to assign components to the correct tiers, (2) intentionally leave cross-cutting utilities unassigned if they genuinely don't belong to one tier, or (3) declare a new tier if the 12 new components represent a distinct architectural layer. The architect typically drives this decision. Atlas surfaces the information; humans make the call."
|
|
47
|
+
- id: q4
|
|
48
|
+
question: What is the key distinction between what Atlas reports and what the Documentor reports?
|
|
49
|
+
choices:
|
|
50
|
+
A: Atlas reports security drift; the Documentor reports performance drift
|
|
51
|
+
B: Atlas reports tier-level architectural drift (which components are unassigned to tiers or stale in the map), while the Documentor reports symbol-level coverage gaps (missing .purpose files, undocumented components)
|
|
52
|
+
C: Atlas and the Documentor report the same information from different perspectives
|
|
53
|
+
D: Atlas reports drift in portal.yaml; the Documentor reports drift in arch.yaml
|
|
54
|
+
E: Atlas reports on test coverage; the Documentor reports on code comments
|
|
55
|
+
correct: B
|
|
56
|
+
explanation: "Atlas and the Documentor operate at different granularities. Atlas works at tier granularity: given the architectural map, which components lack a tier assignment? Which declared components no longer exist? The Documentor works at symbol granularity: which directories lack a .purpose file? Which components have no description? They complement each other — the Documentor ensures symbols are documented, Atlas ensures documented symbols are architecturally located."
|
|
57
|
+
- id: q5
|
|
58
|
+
question: A developer asks Atlas to update `.paradigm/arch.yaml` to add the three new components he just built. What will Atlas do?
|
|
59
|
+
choices:
|
|
60
|
+
A: Atlas will update arch.yaml immediately — this is his primary function
|
|
61
|
+
B: Atlas will ask for confirmation before writing to arch.yaml
|
|
62
|
+
C: Atlas will decline — he is read-only on arch.yaml. He reports drift but never modifies the map. The developer or architect must update arch.yaml manually.
|
|
63
|
+
D: Atlas will delegate the update to the Documentor
|
|
64
|
+
E: Atlas will update arch.yaml only if the developer has the `^architect` gate
|
|
65
|
+
correct: C
|
|
66
|
+
explanation: Atlas never modifies arch.yaml. His agent profile restricts write access on all source files, .purpose files, portal.yaml, and arch.yaml itself. He is read-only. The design is intentional — an advisory agent that modifies files would create side effects that undermine trust. The developer or architect updates arch.yaml; Atlas reports on what he finds.
|
|
@@ -11,7 +11,7 @@ symbols: []
|
|
|
11
11
|
difficulty: advanced
|
|
12
12
|
passThreshold: 0.9
|
|
13
13
|
timeLimit: 5400
|
|
14
|
-
totalSlots:
|
|
14
|
+
totalSlots: 133
|
|
15
15
|
exam:
|
|
16
16
|
kind: proctored
|
|
17
17
|
category: paradigm-core
|
|
@@ -2907,3 +2907,128 @@ questions:
|
|
|
2907
2907
|
E: Score = 1.0 — all four dimensions fire because admin is security-related
|
|
2908
2908
|
correct: C
|
|
2909
2909
|
explanation: 'The scoring uses max() across four dimensions, not an average. symbolMatch: ''#admin-routes'' does not end with ''-auth'' or ''-middleware'' and does not start with ''^'', so 0. pathMatch: ''src/routes/admin.ts'' does not match ''auth/**'' or ''middleware/**'', so 0. conceptMatch: keywords [''new endpoint'', ''admin panel'', ''user management''] do not contain ''permission'', ''JWT'', ''RBAC'', ''XSS'', or ''injection'', so 0. signalMatch: the event type ''route-created'' matches the signal { type: ''route-created'' }, so 1.0. Final score: max(0, 0, 0, 1.0) = 1.0. The security agent self-nominates — new route creation is exactly the kind of event that warrants security review.'
|
|
2910
|
+
- id: plsat-129
|
|
2911
|
+
scenario: A project has `.paradigm/arch.yaml` with three tiers (frontend, backend, database). After a two-week sprint, Atlas reports drift.unassigned contains 7 symbols and drift.missing_purpose contains 3 symbols. The team asks what the correct resolution steps are.
|
|
2912
|
+
question: What should the team do to resolve both drift categories?
|
|
2913
|
+
choices:
|
|
2914
|
+
A: Delete arch.yaml and re-run paradigm scan to regenerate it automatically
|
|
2915
|
+
B: For unassigned (7 symbols in index but not in tiers), add them to the correct tier's components array in arch.yaml. For missing_purpose (3 symbols declared in arch.yaml but not in the index), either re-create the missing components or remove the stale entries from arch.yaml.
|
|
2916
|
+
C: Run paradigm_reindex — it will automatically assign unassigned components to the nearest tier
|
|
2917
|
+
D: Call paradigm_arch_status --fix to apply automatic drift resolution
|
|
2918
|
+
E: Unassigned drift can only be resolved by the architect agent running in the background
|
|
2919
|
+
correct: B
|
|
2920
|
+
explanation: Drift resolution is a manual, human-driven process. For drift.unassigned (7 components indexed but not in any tier), the team adds each component to the appropriate tier's components array in arch.yaml. For drift.missing_purpose (3 components declared in arch.yaml tiers but absent from the index), the team either creates the missing components (if they were planned but not built) or removes the stale entries from arch.yaml (if the components were renamed or deleted). There is no auto-fix flag — Atlas reports drift, humans resolve it.
|
|
2921
|
+
slot: slot-129
|
|
2922
|
+
section: para-701
|
|
2923
|
+
variants:
|
|
2924
|
+
- id: plsat-129b
|
|
2925
|
+
scenario: A team has 4 items in drift.missing_purpose after running paradigm_arch_status. They confirm that all 4 components were renamed as part of a refactor two months ago. The new names are indexed and assigned to tiers. What is the minimal correct resolution?
|
|
2926
|
+
question: How should the team resolve the 4 stale missing_purpose entries?
|
|
2927
|
+
choices:
|
|
2928
|
+
A: Run paradigm_reindex — it automatically removes stale arch.yaml entries
|
|
2929
|
+
B: Remove the 4 old component IDs from their tier's components array in arch.yaml and optionally add the new component IDs if they are not already assigned
|
|
2930
|
+
C: Create stub components with the old names to make them appear in the index again
|
|
2931
|
+
D: Delete and recreate arch.yaml from scratch
|
|
2932
|
+
E: The entries are harmless and can be left indefinitely without action
|
|
2933
|
+
correct: B
|
|
2934
|
+
explanation: The minimal resolution is to remove the 4 stale component IDs from the tier's components array in arch.yaml. This eliminates the missing_purpose drift. If the renamed components are already assigned to tiers (because someone added them after the rename), no further action is needed. If they are unassigned, adding them to the correct tier's components array in the same edit is efficient. Creating stub components would be the wrong approach — it papering over stale map entries rather than updating the map.
|
|
2935
|
+
- id: plsat-130
|
|
2936
|
+
scenario: A project uses `paradigm_orchestrate_inline` with mode="plan". The task is "review the current architectural layer structure and identify components that need tier reassignment." Atlas is on the project roster. At what point in the orchestration pipeline does Atlas fire?
|
|
2937
|
+
question: When does Atlas (cartographer) run in a standard post-build orchestration pipeline?
|
|
2938
|
+
choices:
|
|
2939
|
+
A: Atlas runs in stage 1, before the architect, to map the territory before planning begins
|
|
2940
|
+
B: Atlas runs in parallel with the builder during implementation
|
|
2941
|
+
C: Atlas runs after the Builder stage completes and before or alongside the Documentor — he checks whether newly built components have been assigned to architectural tiers
|
|
2942
|
+
D: Atlas always runs last, after the Documentor completes .purpose updates
|
|
2943
|
+
E: Atlas only fires when the user explicitly adds "cartographer" to the agent list in paradigm_orchestrate_inline
|
|
2944
|
+
correct: C
|
|
2945
|
+
explanation: In the standard orchestration pipeline, Atlas fires after the Builder stage. The Builder produces new components; Atlas checks whether those components are assigned to tiers in arch.yaml. The Documentor runs to update .purpose files. Atlas and the Documentor are both post-Builder agents — Atlas focuses on tier-level architectural drift while the Documentor handles symbol-level coverage. Atlas does not run before the architect (he has no planning role) and does not require explicit invocation when he is on the roster and arch.yaml exists.
|
|
2946
|
+
slot: slot-130
|
|
2947
|
+
section: para-701
|
|
2948
|
+
variants:
|
|
2949
|
+
- id: plsat-130b
|
|
2950
|
+
scenario: A developer is building a small utility library. There is no .paradigm/arch.yaml. They call paradigm_orchestrate_inline with mode="plan". Will Atlas appear in the orchestration plan?
|
|
2951
|
+
question: Does Atlas participate in orchestration when arch.yaml does not exist?
|
|
2952
|
+
choices:
|
|
2953
|
+
A: Yes — Atlas always participates because architectural oversight is always valuable
|
|
2954
|
+
B: Yes — Atlas participates and creates arch.yaml as its first action
|
|
2955
|
+
C: No — Atlas's attention patterns include .paradigm/arch.yaml as a path pattern. Without the file, his attention scoring for this task is near-zero and he will not be nominated
|
|
2956
|
+
D: No — Atlas is a tier-1 agent and tier-1 agents are excluded from small library projects
|
|
2957
|
+
E: Yes — Atlas participates but produces an empty drift report when arch.yaml is missing
|
|
2958
|
+
correct: C
|
|
2959
|
+
explanation: Atlas's attention configuration includes `.paradigm/arch.yaml` as a path pattern and architectural concepts as concept triggers. When arch.yaml does not exist, the path match contributes zero to his attention score. For a small utility library task with no architectural keywords in the task description, his conceptMatch is also likely below threshold. His attention threshold is 0.35 — low enough to catch architectural tasks, but the complete absence of arch.yaml means the task has no architectural mapping signals. He will not self-nominate and will not appear in the plan.
|
|
2960
|
+
- id: plsat-131
|
|
2961
|
+
scenario: A developer generates a Mermaid diagram using `paradigm_arch_diagram` and notices that some tier edges show no label, while others show labels like "REST API" and "message queue." They want to add labels to the unlabeled edges.
|
|
2962
|
+
question: How do Mermaid edge labels get added to arch.yaml links, and what field controls them?
|
|
2963
|
+
choices:
|
|
2964
|
+
A: Edge labels are automatically inferred from the framework names in each tier's tech field
|
|
2965
|
+
B: Edge labels require a separate `labels.yaml` file in .paradigm/
|
|
2966
|
+
C: The `via` field on each link in the links array provides the edge label. Links without a `via` field render without a label. To add a label, add `via: "label text"` to the link entry in arch.yaml.
|
|
2967
|
+
D: Edge labels can only be set via the paradigm_arch_diagram tool's input parameters
|
|
2968
|
+
E: Edge labels are set in the tier's `tech.libraries` array using the format "label:target-tier"
|
|
2969
|
+
correct: C
|
|
2970
|
+
explanation: "The `via` field on a link entry is the only mechanism for edge labels. When `via` is present, generateMermaid() renders the edge as `from -->|\"via text\"| to`. When `via` is absent, the edge renders as `from --> to` with no label. To add labels to currently unlabeled edges, the developer edits arch.yaml and adds `via: \"label text\"` to each link entry they want labeled. The tool's input has no label parameter — labels are part of the arch.yaml data, not the tool call."
|
|
2971
|
+
slot: slot-131
|
|
2972
|
+
section: para-701
|
|
2973
|
+
variants:
|
|
2974
|
+
- id: plsat-131b
|
|
2975
|
+
scenario: A team's arch.yaml has this link entry -- `from: api-gateway, to: user-service, via: gRPC`. The same team has another link -- `from: api-gateway, to: notification-service` with no via field. What will the generated Mermaid diagram show for each edge?
|
|
2976
|
+
question: What does the Mermaid output look like for these two links?
|
|
2977
|
+
choices:
|
|
2978
|
+
A: Both edges render with no label — via is ignored in diagram generation
|
|
2979
|
+
B: The first edge renders as `api-gateway -->|"gRPC"| user-service` and the second renders as `api-gateway --> notification-service` with no label
|
|
2980
|
+
C: The second edge renders as `api-gateway -->|"undefined"| notification-service`
|
|
2981
|
+
D: Both edges require via — the second link causes a parse error
|
|
2982
|
+
E: The first edge renders as `api-gateway -- gRPC --> user-service` using Mermaid's alternate edge syntax
|
|
2983
|
+
correct: B
|
|
2984
|
+
explanation: 'generateMermaid() branches on the presence of link.via. When via is set, it produces `from -->|"via text"| to`. When via is absent (undefined or not provided), it produces `from --> to` with no label. The first link produces `api-gateway -->|"gRPC"| user-service`. The second produces `api-gateway --> notification-service`. There is no "undefined" label for missing via — the code explicitly checks `if (link.via)` and omits the label syntax entirely when false.'
|
|
2985
|
+
- id: plsat-132
|
|
2986
|
+
scenario: An agent needs to get both the architectural summary data (tier names, component counts, drift) AND a Mermaid diagram string in one session. The developer asks whether they should call one tool or two.
|
|
2987
|
+
question: What is the correct tool call strategy to get both tier summary data and the Mermaid diagram?
|
|
2988
|
+
choices:
|
|
2989
|
+
A: Call paradigm_arch_status with format="mermaid" to get both in one response
|
|
2990
|
+
B: Call paradigm_arch_diagram — it includes the full tier summary along with the diagram
|
|
2991
|
+
C: Call both paradigm_arch_status (for tier metadata and drift) and paradigm_arch_diagram (for the diagram string) — they serve distinct purposes and neither includes the other's output
|
|
2992
|
+
D: Call paradigm_arch_status and extract the diagram from the `tiers` array
|
|
2993
|
+
E: There is a single paradigm_arch_full tool that returns both
|
|
2994
|
+
correct: C
|
|
2995
|
+
explanation: paradigm_arch_status and paradigm_arch_diagram are complementary tools with distinct outputs. paradigm_arch_status returns tier metadata (id, label, responsibility, framework, componentCount, components list) and the drift object (unassigned, missing_purpose, clean flag). It does not include a Mermaid diagram. paradigm_arch_diagram returns a JSON object with format and diagram fields — a Mermaid graph string. It does not include tier metadata or drift. To get both, call both tools. Combined token cost is approximately 350 tokens — well within typical budgets.
|
|
2996
|
+
slot: slot-132
|
|
2997
|
+
section: para-701
|
|
2998
|
+
variants:
|
|
2999
|
+
- id: plsat-132b
|
|
3000
|
+
scenario: A developer is writing a CI script that checks whether the architectural map is clean after each build. They want a JSON output they can parse. They are using the Paradigm CLI.
|
|
3001
|
+
question: Which CLI command produces JSON output suitable for programmatic parsing of drift status?
|
|
3002
|
+
choices:
|
|
3003
|
+
A: paradigm arch diagram --json
|
|
3004
|
+
B: paradigm arch status | jq .drift
|
|
3005
|
+
C: paradigm arch status --json
|
|
3006
|
+
D: paradigm status --arch
|
|
3007
|
+
E: paradigm arch --output json
|
|
3008
|
+
correct: C
|
|
3009
|
+
explanation: '`paradigm arch status --json` outputs the full arch.yaml summary as a JSON object, including the drift field with unassigned and missing_purpose arrays and the clean boolean. This is directly parseable by jq, Python json.loads(), or any JSON parser. `paradigm arch status` without --json outputs human-friendly formatted text with headers and key-value pairs — not JSON. The --json flag on the status subcommand is the explicit programmatic interface for CI integration.'
|
|
3010
|
+
- id: plsat-133
|
|
3011
|
+
scenario: A startup is three weeks into development. They have a monorepo with 2 services and a React frontend. They have 22 indexed components but no arch.yaml. A senior engineer asks when the team should create arch.yaml.
|
|
3012
|
+
question: At what point should a project create `.paradigm/arch.yaml`?
|
|
3013
|
+
choices:
|
|
3014
|
+
A: Immediately — arch.yaml must be created before running paradigm init
|
|
3015
|
+
B: Only when the project has more than 100 components — smaller projects do not benefit
|
|
3016
|
+
C: arch.yaml is optional and created when the team wants tier-level documentation, drift detection, or diagrams. A reasonable trigger is when cross-tier architectural decisions are being discussed or when onboarding new team members who need a system map.
|
|
3017
|
+
D: arch.yaml should be created only by the architect agent, never by a human
|
|
3018
|
+
E: arch.yaml is created automatically by `paradigm shift` and should not be edited manually
|
|
3019
|
+
correct: C
|
|
3020
|
+
explanation: arch.yaml is entirely optional — it is additive metadata, not required for any core Paradigm feature. The right time to create it is when it adds value that justifies the maintenance cost. Common triggers include (1) cross-tier architectural planning where tier structure needs to be explicit, (2) onboarding where new engineers need a visual map of the system, (3) architectural review where stakeholders want diagrams, or (4) large refactors where the target architecture should be declared before work begins so drift is detectable. A three-week project with 22 components and an active senior engineer discussing cross-tier work is a reasonable point to create it. The 100-component rule is a myth — value comes from clarity, not scale.
|
|
3021
|
+
slot: slot-133
|
|
3022
|
+
section: para-701
|
|
3023
|
+
variants:
|
|
3024
|
+
- id: plsat-133b
|
|
3025
|
+
scenario: A team created arch.yaml at project inception. Now, 8 months later, the file shows 15 unassigned components and 8 missing_purpose entries. They are debating whether to delete arch.yaml and start fresh or update it incrementally.
|
|
3026
|
+
question: What is the better approach for a heavily drifted arch.yaml?
|
|
3027
|
+
choices:
|
|
3028
|
+
A: Delete arch.yaml — a file with this much drift is actively misleading and should be removed
|
|
3029
|
+
B: Update it incrementally — assign the 15 unassigned components to their correct tiers, remove the 8 stale missing_purpose entries. The architectural context (tier labels, responsibilities, links) is still valuable even if component lists are stale.
|
|
3030
|
+
C: Archive arch.yaml and regenerate it from scratch using the symbol index
|
|
3031
|
+
D: Leave it as-is — drift is cosmetic and does not affect any Paradigm functionality
|
|
3032
|
+
E: Ask Atlas to auto-resolve the drift by analyzing component names
|
|
3033
|
+
correct: B
|
|
3034
|
+
explanation: Incremental update is almost always preferable to deletion or regeneration. The tier structure (ids, labels, responsibilities, tech stacks, links) likely still reflects the actual architecture — only the component lists have drifted. Updating the component lists (15 additions, 8 removals) is a focused edit that preserves architectural context. Deleting and regenerating loses tier metadata that was manually authored. Atlas never auto-resolves drift. Leaving heavy drift signals uncleaned creates confusion about which components belong where. The incremental update path gives the highest value-to-effort ratio.
|
|
@@ -83,5 +83,5 @@ Error generating stack: `+i.message+`
|
|
|
83
83
|
*/var Il=S,fm=cm;function dm(e,t){return e===t&&(e!==0||1/e===1/t)||e!==e&&t!==t}var pm=typeof Object.is=="function"?Object.is:dm,hm=fm.useSyncExternalStore,mm=Il.useRef,vm=Il.useEffect,gm=Il.useMemo,ym=Il.useDebugValue;hf.useSyncExternalStoreWithSelector=function(e,t,n,r,l){var i=mm(null);if(i.current===null){var o={hasValue:!1,value:null};i.current=o}else o=i.current;i=gm(function(){function u(x){if(!c){if(c=!0,h=x,x=r(x),l!==void 0&&o.hasValue){var y=o.value;if(l(y,x))return m=y}return m=x}if(y=m,pm(h,x))return y;var w=r(x);return l!==void 0&&l(y,w)?(h=x,y):(h=x,m=w)}var c=!1,h,m,v=n===void 0?null:n;return[function(){return u(t())},v===null?void 0:function(){return u(v())}]},[t,n,r,l]);var s=hm(e,i[0],i[1]);return vm(function(){o.hasValue=!0,o.value=s},[s]),ym(s),s};pf.exports=hf;var xm=pf.exports;const wm=Uu(xm),gf={},{useDebugValue:Sm}=vo,{useSyncExternalStoreWithSelector:km}=wm;let Iu=!1;const Cm=e=>e;function Em(e,t=Cm,n){(gf?"production":void 0)!=="production"&&n&&!Iu&&(console.warn("[DEPRECATED] Use `createWithEqualityFn` instead of `create` or use `useStoreWithEqualityFn` instead of `useStore`. They can be imported from 'zustand/traditional'. https://github.com/pmndrs/zustand/discussions/1937"),Iu=!0);const r=km(e.subscribe,e.getState,e.getServerState||e.getInitialState,t,n);return Sm(r),r}const Ou=e=>{(gf?"production":void 0)!=="production"&&typeof e!="function"&&console.warn("[DEPRECATED] Passing a vanilla store will be unsupported in a future version. Instead use `import { useStore } from 'zustand'`.");const t=typeof e=="function"?em(e):e,n=(r,l)=>Em(t,r,l);return Object.assign(n,t),n},cs=e=>e?Ou(e):Ou,Ol=cs((e,t)=>({courses:[],courseCache:{},isLoading:!1,error:null,loadCourses:async()=>{e({isLoading:!0,error:null});try{const n=await fetch("/api/courses");if(!n.ok)throw new Error("Failed to load courses");const r=await n.json();e({courses:r.courses,isLoading:!1})}catch(n){e({error:n.message,isLoading:!1})}},loadCourse:async n=>{const r=t().courseCache[n];if(r)return r;try{const l=await fetch(`/api/courses/${n}`);if(!l.ok)return null;const i=await l.json();return e(o=>({courseCache:{...o.courseCache,[n]:i}})),i}catch{return null}}})),yf="paradigm-university-progress";function jm(){try{const e=localStorage.getItem(yf);return e?JSON.parse(e):{}}catch{return{}}}function pi(e){try{localStorage.setItem(yf,JSON.stringify(e))}catch{}}const Ml=cs((e,t)=>({progress:jm(),completeLesson:(n,r)=>{e(l=>{const i=l.progress[n]||{courseId:n,completedLessons:[],quizResults:{}};if(i.completedLessons.includes(r))return l;const o={...l.progress,[n]:{...i,completedLessons:[...i.completedLessons,r]}};return pi(o),{progress:o}})},recordQuiz:n=>{e(r=>{const l=r.progress[n.courseId]||{courseId:n.courseId,completedLessons:[],quizResults:{}},i={...r.progress,[n.courseId]:{...l,quizResults:{...l.quizResults,[n.lessonId]:n}}};return pi(i),{progress:i}})},getCourseProgress:n=>t().progress[n]||{courseId:n,completedLessons:[],quizResults:{}},isLessonCompleted:(n,r)=>{const l=t().progress[n];return l?l.completedLessons.includes(r):!1},getCoursePercentage:(n,r)=>{if(r===0)return 0;const l=t().progress[n];return l?Math.round(l.completedLessons.length/r*100):0},resetProgress:()=>{pi({}),e({progress:{}})}})),xf="paradigm-university-plsat";function Nm(){try{const e=localStorage.getItem(xf);return e?JSON.parse(e):{certificates:[],studentName:""}}catch{return{certificates:[],studentName:""}}}function Mu(e){try{localStorage.setItem(xf,JSON.stringify(e))}catch{}}const fs=cs((e,t)=>{const n=Nm();return{certificates:n.certificates,studentName:n.studentName,setStudentName:r=>{e({studentName:r});const l=t();Mu({certificates:l.certificates,studentName:r})},addCertificate:r=>{e(l=>{const i=[...l.certificates,r];return Mu({certificates:i,studentName:l.studentName}),{certificates:i}})},getLatestCertificate:()=>{const r=t().certificates;return r.length===0?null:r.reduce((l,i)=>new Date(i.date)>new Date(l.date)?i:l)},getCertificateForVersion:r=>t().certificates.find(l=>l.plsatVersion===r&&l.passed)||null,hasPassed:()=>t().certificates.some(r=>r.passed)}});function wf({percentage:e,size:t=48,strokeWidth:n=4}){const r=(t-n)/2,l=2*Math.PI*r,i=l-e/100*l;return a.jsxs("div",{className:"progress-ring",style:{width:t,height:t},children:[a.jsxs("svg",{width:t,height:t,children:[a.jsx("circle",{className:"ring-bg",cx:t/2,cy:t/2,r,fill:"none",strokeWidth:n}),a.jsx("circle",{className:"ring-fill",cx:t/2,cy:t/2,r,fill:"none",strokeWidth:n,strokeLinecap:"round",strokeDasharray:l,strokeDashoffset:i})]}),a.jsxs("span",{className:"ring-label",children:[e,"%"]})]})}function Pm(){const{courses:e,isLoading:t,loadCourses:n}=Ol(),r=Ml(i=>i.getCoursePercentage),l=fs(i=>i.hasPassed);return S.useEffect(()=>{n()},[n]),t?a.jsx("div",{className:"loading",children:"Opening the campus gates..."}):a.jsxs("div",{className:"home",children:[a.jsxs("div",{className:"home-hero",children:[a.jsx(pn,{size:140}),a.jsx("h1",{children:"Paradigm University"}),a.jsx("p",{className:"motto",children:"Universitas Paradigmatica — Lux in Codice"}),a.jsx("p",{className:"description",children:"Master the Paradigm framework through structured courses, hands-on quizzes, and the legendary PLSAT certification exam."})]}),a.jsx("div",{className:"gold-divider"}),a.jsxs("section",{className:"course-catalog",children:[a.jsx("h2",{children:"Course Catalog"}),e.map(i=>{const o=r(i.id,i.lessonCount);return a.jsxs(q,{to:`/course/${i.id}`,className:"course-card",children:[a.jsxs("div",{className:"course-card-header",children:[a.jsxs("div",{className:"course-card-title",children:[a.jsx("span",{className:"course-number",children:i.id.replace("para-","PARA ")}),a.jsx("h3",{children:i.title.replace(/^PARA \d+: /,"")})]}),a.jsx(wf,{percentage:o})]}),a.jsx("p",{className:"course-description",children:i.description}),a.jsx("div",{className:"course-topics",children:i.lessons.map(s=>a.jsx("span",{className:"course-topic-tag",children:s.title},s.id))}),a.jsxs("div",{className:"course-meta",children:[a.jsxs("span",{children:[i.lessonCount," lessons"]}),a.jsx("span",{className:"course-meta-cta",children:"Start course →"})]})]},i.id)})]}),a.jsx("div",{className:"gold-divider"}),a.jsxs("section",{children:[a.jsx("h2",{className:"mb-lg",children:"Quick Links"}),a.jsxs("div",{className:"quick-links",children:[a.jsx(q,{to:"/plsat",className:"quick-link",children:l()?"Retake the PLSAT":"Take the PLSAT"}),a.jsx(q,{to:"/reference",className:"quick-link",children:"Reference Library"}),a.jsx(q,{to:"/certificate",className:"quick-link",children:"View Certificates"}),a.jsx(q,{to:"/course/para-101",className:"quick-link",children:"Start Learning"})]})]})]})}function _m(){const{courses:e,isLoading:t,loadCourses:n}=Ol(),r=Ml(l=>l.getCoursePercentage);return S.useEffect(()=>{n()},[n]),t?a.jsx("div",{className:"loading",children:"Loading courses..."}):a.jsx("div",{className:"home",children:a.jsxs("section",{className:"course-catalog",children:[a.jsx("h2",{children:"Course Catalog"}),e.map(l=>{const i=r(l.id,l.lessonCount);return a.jsxs(q,{to:`/course/${l.id}`,className:"course-card",children:[a.jsx("span",{className:"course-number",children:l.id.replace("para-","PARA ")}),a.jsx("h3",{children:l.title.replace(/^PARA \d+: /,"")}),a.jsx("p",{className:"course-description",children:l.description}),a.jsxs("div",{className:"course-meta",children:[a.jsxs("span",{children:[l.lessonCount," lessons"]}),a.jsx(wf,{percentage:i})]})]},l.id)})]})})}function Du(e){return e.replace(/`([^`]+)`/g,"<code>$1</code>").replace(/\*\*([^*]+)\*\*/g,"<strong>$1</strong>").replace(/\*([^*]+)\*/g,"<em>$1</em>")}function Lm(e){const t=e.trim().split(`
|
|
84
84
|
`);if(t.length<2)return e;const n=o=>o.split("|").map(s=>s.trim()).filter(s=>s.length>0),r=n(t[0]),l=t.slice(2).map(n);let i="<table><thead><tr>";for(const o of r)i+=`<th>${Du(o)}</th>`;i+="</tr></thead><tbody>";for(const o of l){i+="<tr>";for(const s of o)i+=`<td>${Du(s)}</td>`;i+="</tr>"}return i+="</tbody></table>",i}function Ut(e){const t=[];let n=e.replace(/```(\w*)\n([\s\S]*?)```/g,(r,l,i)=>{const o=t.length;return t.push(`<pre><code>${i}</code></pre>`),`\0BLOCK${o}\0`});return n=n.replace(/((?:^\|.+\|\n?)+)/gm,r=>{const l=r.trim().split(`
|
|
85
85
|
`);if(l.length>=3&&/^[\s-:|]+$/.test(l[1])){const i=t.length;return t.push(Lm(r)),`\0BLOCK${i}\0`}return r}),n=n.replace(/`([^`]+)`/g,"<code>$1</code>").replace(/^#### (.+)$/gm,"<h4>$1</h4>").replace(/^### (.+)$/gm,"<h3>$1</h3>").replace(/^## (.+)$/gm,"<h2>$1</h2>").replace(/\*\*([^*]+)\*\*/g,"<strong>$1</strong>").replace(/\*([^*]+)\*/g,"<em>$1</em>").replace(/^> (.+)$/gm,"<blockquote>$1</blockquote>").replace(/^\d+\.\s+(.+)$/gm,"<oli>$1</oli>").replace(/((?:<oli>.*<\/oli>\n?)+)/g,r=>"<ol>"+r.replace(/<\/?oli>/g,l=>l.replace("oli","li"))+"</ol>").replace(/^- (.+)$/gm,"<li>$1</li>").replace(/((?:<li>.*<\/li>\n?)+)/g,"<ul>$1</ul>").replace(/^(?!<(?:h[1-6]|ul|ol|li|p|blockquote|pre|table|thead|tbody|tr|td|th|\x00)).+$/gm,"<p>$&</p>").replace(/\n{2,}/g,`
|
|
86
|
-
`),n=n.replace(/\x00BLOCK(\d+)\x00/g,(r,l)=>t[Number(l)]),n}function Au(){const{courseId:e,lessonId:t}=uf(),n=sf(),r=Ol(d=>d.loadCourse),[l,i]=S.useState(null),[o,s]=S.useState(null),[u,c]=S.useState(!0),{isLessonCompleted:h,completeLesson:m}=Ml();if(S.useEffect(()=>{e&&(c(!0),r(e).then(d=>{if(i(d),d&&d.lessons.length>0){const f=t?d.lessons.find(p=>p.id===t):null;f?s(f):(s(d.lessons[0]),n(`/course/${e}/${d.lessons[0].id}`,{replace:!0}))}c(!1)}))},[e,t,r,n]),u)return a.jsx("div",{className:"loading",children:"Opening the textbook..."});if(!l)return a.jsxs("div",{className:"empty-state",children:[a.jsx("h3",{children:"Course not found"}),a.jsx("p",{children:"The requested course does not exist."}),a.jsx(q,{to:"/",className:"btn btn-primary mt-lg",children:"Return to Campus"})]});const v=o?l.lessons.findIndex(d=>d.id===o.id):0,x=()=>{o&&e&&m(e,o.id)},y=(d,f=!1)=>{s(d),n(`/course/${e}/${d.id}`),f&&window.scrollTo(0,0)},w=()=>{v<l.lessons.length-1&&y(l.lessons[v+1],!0)},N=()=>{v>0&&y(l.lessons[v-1],!0)};return a.jsxs("div",{className:"course-layout",children:[a.jsxs("aside",{className:"course-sidebar",children:[a.jsx("h2",{children:l.title}),a.jsx("nav",{className:"lesson-nav",children:l.lessons.map(d=>{const f=e?h(e,d.id):!1,p=(o==null?void 0:o.id)===d.id;let g="lesson-nav-item";return p&&(g+=" active"),f&&!p&&(g+=" completed"),a.jsx("button",{className:g,onClick:()=>y(d),children:d.title},d.id)})})]}),a.jsx("div",{className:"course-content",children:o&&a.jsxs(a.Fragment,{children:[a.jsx("h1",{children:o.title}),o.keyConcepts.length>0&&a.jsx("div",{className:"key-concepts",children:o.keyConcepts.map(d=>a.jsx("span",{className:"concept-tag",children:d},d))}),a.jsx("div",{className:"lesson-content",dangerouslySetInnerHTML:{__html:Ut(o.content)}}),a.jsxs("div",{className:"lesson-actions",children:[a.jsx("div",{children:v>0&&a.jsx("button",{className:"btn btn-secondary",onClick:N,children:"Previous"})}),a.jsxs("div",{style:{display:"flex",gap:"0.5rem"},children:[e&&!h(e,o.id)&&a.jsx("button",{className:"btn btn-secondary",onClick:x,children:"Mark Complete"}),o.quiz.length>0&&e&&a.jsx(q,{to:`/course/${e}/quiz/${o.id}`,className:"btn btn-gold",children:"Take Quiz"}),v<l.lessons.length-1&&a.jsx("button",{className:"btn btn-primary",onClick:w,children:"Next Lesson"})]})]})]})})]})}function co({number:e,question:t,scenario:n,choices:r,correct:l,explanation:i,selectedAnswer:o,onSelect:s,showResult:u,onAnswered:c,splitLayout:h}){const[m,v]=S.useState(null),[x,y]=S.useState(!1),w=s!==void 0,N=w?o||null:m,d=w?u:x,f=j=>{d&&!w||(w?s==null||s(j):(v(j),y(!0),c==null||c(j)))},p=N===l,g=Object.keys(r).sort(),E=a.jsxs(a.Fragment,{children:[a.jsxs("div",{className:"question-number",children:["Question ",e]}),n&&a.jsx("div",{className:"scenario",dangerouslySetInnerHTML:{__html:Ut(n)}}),a.jsx("div",{className:"question-text",dangerouslySetInnerHTML:{__html:Ut(t)}})]}),k=a.jsx("div",{className:"choices",children:g.map(j=>{let P="choice-btn";return N===j&&(P+=" selected"),d&&j===l&&(P+=" correct"),d&&N===j&&j!==l&&(P+=" incorrect"),a.jsxs("button",{className:P,onClick:()=>f(j),disabled:d&&!w,children:[a.jsxs("span",{className:"choice-letter",children:[j,"."]}),a.jsx("span",{dangerouslySetInnerHTML:{__html:Ut(r[j])}})]},j)})});return h?a.jsxs("div",{className:"question-card",children:[a.jsxs("div",{className:"question-split-layout",children:[a.jsx("div",{className:"question-content",children:E}),a.jsx("div",{className:"answer-choices",children:k})]}),d&&a.jsxs("div",{className:`explanation ${p?"":"wrong"}`,children:[a.jsx("strong",{children:p?"Correct!":`Incorrect. The answer is ${l}.`}),a.jsx("br",{}),a.jsx("span",{dangerouslySetInnerHTML:{__html:Ut(i)}})]})]}):a.jsxs("div",{className:"question-card",children:[E,k,d&&a.jsxs("div",{className:`explanation ${p?"":"wrong"}`,children:[a.jsx("strong",{children:p?"Correct!":`Incorrect. The answer is ${l}.`}),a.jsx("br",{}),a.jsx("span",{dangerouslySetInnerHTML:{__html:Ut(i)}})]})]})}function Tm(){const{courseId:e,lessonId:t}=uf(),n=Ol(g=>g.loadCourse),{recordQuiz:r,completeLesson:l,getCourseProgress:i}=Ml(),[o,s]=S.useState(null),[u,c]=S.useState(null),[h,m]=S.useState(!0),[v,x]=S.useState(!1),[y,w]=S.useState(0),N=e&&t?i(e).quizResults[t]:void 0;S.useEffect(()=>{e&&(m(!0),n(e).then(g=>{if(g&&t){const E=g.lessons.findIndex(k=>k.id===t);s(E>=0?g.lessons[E]:null),E>=0&&E<g.lessons.length-1&&c(g.lessons[E+1].id)}m(!1)}))},[e,t,n]);const[d,f]=S.useState({}),p=(g,E)=>{if(f(k=>({...k,[g]:E})),o){const k={...d,[g]:E};if(Object.keys(k).length===o.quiz.length){const j=o.quiz.filter(P=>k[P.id]===P.correct).length;if(w(j),x(!0),e&&t){const P={courseId:e,lessonId:t,score:j,total:o.quiz.length,answers:k,date:new Date().toISOString()};r(P),l(e,t)}}}};return h?a.jsx("div",{className:"loading",children:"Preparing your examination..."}):!o||o.quiz.length===0?a.jsxs("div",{className:"empty-state",children:[a.jsx("h3",{children:"No quiz available"}),a.jsx("p",{children:"This lesson does not have a quiz."}),a.jsx(q,{to:`/course/${e}`,className:"btn btn-primary mt-lg",children:"Back to Course"})]}):a.jsxs("div",{className:"quiz-container",children:[a.jsxs("div",{className:"quiz-header",children:[a.jsxs("h1",{children:[o.title," — Quiz"]}),a.jsx("p",{className:"quiz-progress",children:v?`Score: ${y}/${o.quiz.length} (${Math.round(y/o.quiz.length*100)}%)`:`${Object.keys(d).length}/${o.quiz.length} answered`}),N&&!v&&a.jsxs("p",{className:"text-muted mt-sm",children:["Previous best: ",N.score,"/",N.total]})]}),o.quiz.map((g,E)=>a.jsx(co,{number:E+1,question:g.question,choices:g.choices,correct:g.correct,explanation:g.explanation,onAnswered:k=>p(g.id,k)},g.id)),v&&a.jsxs("div",{className:"text-center mt-xl",children:[a.jsx("p",{className:"mb-lg",style:{fontSize:"1.25rem",fontFamily:"var(--font-serif)"},children:y===o.quiz.length?"Perfect score! Exemplary scholarship.":y>=o.quiz.length*.8?"Well done, scholar. You have demonstrated understanding.":"Review the material and try again. Persistence is the path to mastery."}),u?a.jsx(q,{to:`/course/${e}/${u}`,className:"btn btn-primary",children:"Next Lesson"}):a.jsx(q,{to:`/course/${e}`,className:"btn btn-primary",children:"Return to Course"})]})]})}function zm({totalSeconds:e,onTimeUp:t,running:n}){const[r,l]=S.useState(e),i=S.useCallback(()=>{t()},[t]);S.useEffect(()=>{if(!n)return;const h=setInterval(()=>{l(m=>m<=1?(clearInterval(h),i(),0):m-1)},1e3);return()=>clearInterval(h)},[n,i]);const o=Math.floor(r/60),s=r%60,u=r/e*100;let c="timer-display";return u<20?c+=" critical":u<40&&(c+=" warning"),a.jsxs("span",{className:c,children:[String(o).padStart(2,"0"),":",String(s).padStart(2,"0")]})}function Fu({text:e}){const t=e.split(/(```[\s\S]*?```)/g);return a.jsx("div",{className:"passage-block",children:a.jsx("div",{className:"passage-content",children:t.map((n,r)=>{if(n.startsWith("```")){const l=n.match(/^```(\w*)\n?([\s\S]*?)```$/),i=l?l[2]:n.slice(3,-3);return a.jsx("pre",{children:a.jsx("code",{children:i})},r)}return n.split(/\n\n+/).map((l,i)=>a.jsx("p",{children:l},`${r}-${i}`))})})})}function $u(e,t,n){if(!t)return null;const r=e[n];return r.passageId?t[r.passageId]??null:null}function Rm(){const[e,t]=S.useState(null),[n,r]=S.useState("intro"),[l,i]=S.useState({}),[o,s]=S.useState(0),[u,c]=S.useState(!0),[h,m]=S.useState(null),{studentName:v,setStudentName:x,addCertificate:y}=fs(),[w,N]=S.useState(v);S.useEffect(()=>{fetch("/api/plsat/3.0").then(k=>k.json()).then(k=>{t(k),c(!1)}).catch(()=>c(!1))},[]);const d=S.useCallback(()=>{if(!e)return;const k=e.questions.filter(de=>l[de.id]===de.correct).length,j=e.questions.length,P=Math.round(k/j*100),M=P>=e.passThreshold*100,z={name:w||"Anonymous Scholar",score:k,total:j,percentage:P,passed:M,plsatVersion:e.version,frameworkVersion:e.frameworkVersion,date:new Date().toISOString()};m(z),y(z),w&&x(w),r("results")},[e,l,w,y,x]),f=S.useCallback(()=>{d()},[d]),p=()=>{d()},g=()=>{i({}),s(0),r("exam")},E=S.useMemo(()=>!e||n!=="exam"?null:$u(e.questions,e.passages,o),[e,n,o]);if(u)return a.jsx("div",{className:"loading",children:"The examination board is convening..."});if(!e)return a.jsxs("div",{className:"empty-state",children:[a.jsx("h3",{children:"PLSAT Unavailable"}),a.jsx("p",{children:"Could not load the examination. Please try again."})]});if(n==="intro")return a.jsxs("div",{className:"plsat-container",children:[a.jsxs("div",{className:"plsat-intro",children:[a.jsx(pn,{size:100}),a.jsx("h1",{children:"The PLSAT"}),a.jsx("p",{className:"plsat-subtitle",children:"Paradigm Licensure Standardized Assessment Test"}),a.jsxs("p",{className:"text-muted",children:["Version ",e.version]})]}),a.jsxs("div",{className:"plsat-rules",children:[a.jsx("h3",{children:"Examination Rules"}),a.jsxs("ul",{children:[a.jsxs("li",{children:[a.jsxs("strong",{children:[e.questions.length," questions"]})," covering all aspects of the Paradigm framework"]}),a.jsxs("li",{children:[a.jsxs("strong",{children:[Math.floor(e.timeLimit/60)," minutes"]})," to complete the examination"]}),a.jsxs("li",{children:[a.jsxs("strong",{children:[e.passThreshold*100,"%"]})," required to pass and receive certification"]}),a.jsx("li",{children:"All questions are multiple choice (A through E)"}),a.jsx("li",{children:"Some questions reference a shared passage — read it carefully"}),a.jsx("li",{children:"You may navigate between questions freely"}),a.jsx("li",{children:"There is no penalty for guessing — answer every question"}),a.jsx("li",{children:"Your certificate will display the PLSAT version for posterity"})]})]}),a.jsxs("div",{className:"text-center",children:[a.jsx("div",{className:"mb-lg",children:a.jsx("input",{type:"text",className:"name-input",placeholder:"Enter your name, scholar",value:w,onChange:k=>N(k.target.value)})}),a.jsx("button",{className:"btn btn-primary btn-lg",onClick:g,children:"Begin Examination"})]})]});if(n==="exam"){const k=e.questions[o],j=Object.keys(l).length;return a.jsxs("div",{className:"plsat-container",children:[a.jsxs("div",{className:"plsat-timer",children:[a.jsx(zm,{totalSeconds:e.timeLimit,onTimeUp:f,running:!0}),a.jsxs("span",{className:"plsat-progress-text",children:["Question ",o+1," of ",e.questions.length," | ",j," answered"]})]}),a.jsxs("div",{style:{marginTop:"var(--space-lg)"},children:[E&&a.jsx(Fu,{text:E}),a.jsx(co,{number:o+1,question:k.question,scenario:k.scenario,choices:k.choices,correct:k.correct,explanation:k.explanation,selectedAnswer:l[k.id],onSelect:P=>i(M=>({...M,[k.id]:P})),showResult:!1,splitLayout:!0})]}),a.jsxs("div",{style:{display:"flex",justifyContent:"space-between",marginTop:"var(--space-lg)"},children:[a.jsx("button",{className:"btn btn-secondary",disabled:o===0,onClick:()=>s(P=>P-1),children:"Previous"}),a.jsxs("div",{style:{display:"flex",gap:"0.5rem"},children:[j===e.questions.length&&a.jsx("button",{className:"btn btn-gold",onClick:p,children:"Submit Examination"}),a.jsx("button",{className:"btn btn-primary",disabled:o===e.questions.length-1,onClick:()=>s(P=>P+1),children:"Next"})]})]}),a.jsx("div",{style:{display:"flex",flexWrap:"wrap",gap:"4px",marginTop:"var(--space-xl)",justifyContent:"center"},children:e.questions.map((P,M)=>a.jsx("button",{onClick:()=>s(M),style:{width:28,height:28,borderRadius:"50%",border:M===o?"2px solid var(--burgundy)":"1px solid var(--parchment-dark)",background:l[P.id]?"var(--gold-bg)":"var(--cream)",color:"var(--ink)",fontSize:"0.6875rem",cursor:"pointer",fontWeight:M===o?600:400},children:M+1},P.id))})]})}return n==="results"&&h?a.jsx("div",{className:"plsat-container",children:a.jsxs("div",{className:"plsat-results",children:[a.jsx(pn,{size:80}),a.jsxs("div",{className:`score-display ${h.passed?"passed":"failed"}`,children:[h.percentage,"%"]}),a.jsx("p",{className:"verdict",children:h.passed?"Congratulations! You have passed the PLSAT.":"The examination board regrets to inform you that you did not pass."}),a.jsxs("p",{className:"text-muted mb-lg",children:["Score: ",h.score,"/",h.total," | PLSAT v",h.plsatVersion," | ",new Date(h.date).toLocaleDateString()]}),a.jsxs("div",{style:{display:"flex",gap:"1rem",justifyContent:"center"},children:[h.passed&&a.jsx(q,{to:"/certificate",className:"btn btn-gold btn-lg",children:"View Certificate"}),a.jsx("button",{className:"btn btn-secondary",onClick:()=>r("review"),children:"Review Answers"}),a.jsx("button",{className:"btn btn-primary",onClick:()=>r("intro"),children:h.passed?"Retake":"Try Again"})]})]})}):n==="review"?a.jsxs("div",{className:"plsat-container",children:[a.jsxs("div",{className:"quiz-header",children:[a.jsx("h1",{children:"PLSAT Review"}),a.jsx("p",{className:"quiz-progress",children:h?`Score: ${h.score}/${h.total} (${h.percentage}%)`:""})]}),e.questions.map((k,j)=>{const P=$u(e.questions,e.passages,j);return a.jsxs("div",{children:[P&&a.jsx(Fu,{text:P}),a.jsx(co,{number:j+1,question:k.question,scenario:k.scenario,choices:k.choices,correct:k.correct,explanation:k.explanation,selectedAnswer:l[k.id],onSelect:()=>{},showResult:!0,splitLayout:!0})]},k.id)}),a.jsx("div",{className:"text-center mt-xl",children:a.jsx("button",{className:"btn btn-primary",onClick:()=>r("results"),children:"Back to Results"})})]}):null}function Im(){const[e,t]=S.useState(null),[n,r]=S.useState(!0);return S.useEffect(()=>{fetch("/api/reference").then(l=>l.json()).then(l=>{t(l),r(!1)}).catch(()=>r(!1))},[]),n?a.jsx("div",{className:"loading",children:"Opening the reference library..."}):e?a.jsxs("div",{className:"reference-container",children:[a.jsx("h1",{className:"mb-lg",children:"Reference Library"}),e.sections.map(l=>a.jsxs("section",{className:"reference-section",children:[a.jsx("h2",{children:l.title}),a.jsx("div",{className:"reference-grid",children:l.cards.map(i=>a.jsxs("div",{className:"ref-card",children:[i.symbol&&a.jsx("div",{className:"ref-symbol",children:i.symbol}),a.jsx("h4",{children:i.name}),a.jsx("p",{children:i.description}),i.examples&&i.examples.length>0&&a.jsx("div",{className:"ref-examples",children:i.examples.map(o=>a.jsx("span",{className:"ref-example",children:o},o))}),i.logger&&a.jsx("p",{style:{marginTop:"0.5rem"},children:a.jsx("code",{children:i.logger})}),i.when&&a.jsx("p",{className:"text-muted",style:{fontSize:"0.8125rem",marginTop:"0.25rem"},children:a.jsx("em",{children:i.when})}),i.command&&a.jsx("p",{style:{marginTop:"0.5rem"},children:a.jsx("code",{children:i.command})}),i.steps&&i.steps.length>0&&a.jsx("ol",{style:{fontSize:"0.875rem",paddingLeft:"1.25rem",marginTop:"0.5rem"},children:i.steps.map((o,s)=>a.jsx("li",{style:{marginBottom:"0.25rem"},children:o},s))})]},i.id))})]},l.id))]}):a.jsxs("div",{className:"empty-state",children:[a.jsx("h3",{children:"Reference library unavailable"}),a.jsx("p",{children:"Could not load reference data."})]})}function Om(){const{certificates:e}=fs(),t=e.filter(r=>r.passed),n=t.length>0?t.reduce((r,l)=>new Date(l.date)>new Date(r.date)?l:r):null;return n?a.jsxs("div",{className:"certificate-container",children:[a.jsx("div",{className:"no-print text-center mb-lg",children:a.jsx("button",{className:"btn btn-gold",onClick:()=>window.print(),children:"Print Certificate"})}),a.jsxs("div",{className:"certificate",children:[a.jsx(pn,{size:100,className:"cert-seal"}),a.jsx("h1",{children:"Paradigm University"}),a.jsx("p",{className:"cert-title",children:"Universitas Paradigmatica — Lux in Codice"}),a.jsx("div",{className:"gold-divider"}),a.jsx("p",{style:{fontSize:"0.875rem",color:"var(--ink-muted)",marginTop:"var(--space-lg)"},children:"This is to certify that"}),a.jsx("div",{className:"cert-name",children:n.name}),a.jsxs("p",{className:"cert-body",children:["has successfully completed the",a.jsx("br",{}),a.jsx("strong",{children:"Paradigm Licensure Standardized Assessment Test"}),a.jsx("br",{}),"and is hereby recognized as a certified Paradigm practitioner."]}),a.jsxs("p",{className:"cert-score",children:["Score: ",n.score,"/",n.total," (",n.percentage,"%)"]}),a.jsx("div",{className:"gold-divider"}),a.jsxs("dl",{className:"cert-meta",children:[a.jsxs("div",{children:[a.jsx("dt",{children:"PLSAT Version"}),a.jsxs("dd",{children:["v",n.plsatVersion]})]}),a.jsxs("div",{children:[a.jsx("dt",{children:"Framework Version"}),a.jsxs("dd",{children:["v",n.frameworkVersion]})]}),a.jsxs("div",{children:[a.jsx("dt",{children:"Date Issued"}),a.jsx("dd",{children:new Date(n.date).toLocaleDateString("en-US",{year:"numeric",month:"long",day:"numeric"})})]})]})]}),e.length>1&&a.jsxs("div",{className:"no-print mt-xl",children:[a.jsx("h3",{className:"mb-md",children:"All Attempts"}),[...e].reverse().map((r,l)=>a.jsx("div",{className:"ref-card",style:{marginBottom:"0.5rem"},children:a.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:[a.jsxs("span",{children:["PLSAT v",r.plsatVersion," — ",r.score,"/",r.total," (",r.percentage,"%)",r.passed?" ✓":""]}),a.jsx("span",{className:"text-muted",children:new Date(r.date).toLocaleDateString()})]})},l))]})]}):a.jsxs("div",{className:"certificate-container",children:[a.jsxs("div",{className:"empty-state",children:[a.jsx(pn,{size:80}),a.jsx("h3",{className:"mt-lg",children:"No Certificates Yet"}),a.jsx("p",{children:"Pass the PLSAT examination to earn your Paradigm certification."}),a.jsx(q,{to:"/plsat",className:"btn btn-primary mt-lg",children:"Take the PLSAT"})]}),e.length>0&&a.jsxs("div",{className:"mt-xl",children:[a.jsx("h3",{className:"mb-md",children:"Previous Attempts"}),e.map((r,l)=>a.jsx("div",{className:"ref-card",style:{marginBottom:"0.5rem"},children:a.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:[a.jsxs("span",{children:["PLSAT v",r.plsatVersion," — ",r.score,"/",r.total," (",r.percentage,"%)"]}),a.jsx("span",{className:"text-muted",children:new Date(r.date).toLocaleDateString()})]})},l))]})]})}function Mm(){return a.jsxs("div",{className:"app",children:[a.jsx(Zh,{version:"6.0.2"}),a.jsx("main",{className:"main-content",children:a.jsxs(Bh,{children:[a.jsx(We,{path:"/",element:a.jsx(Pm,{})}),a.jsx(We,{path:"/courses",element:a.jsx(_m,{})}),a.jsx(We,{path:"/course/:courseId",element:a.jsx(Au,{})}),a.jsx(We,{path:"/course/:courseId/:lessonId",element:a.jsx(Au,{})}),a.jsx(We,{path:"/course/:courseId/quiz/:lessonId",element:a.jsx(Tm,{})}),a.jsx(We,{path:"/plsat",element:a.jsx(Rm,{})}),a.jsx(We,{path:"/reference",element:a.jsx(Im,{})}),a.jsx(We,{path:"/certificate",element:a.jsx(Om,{})})]})})]})}hi.createRoot(document.getElementById("root")).render(a.jsx(vo.StrictMode,{children:a.jsx(Gh,{children:a.jsx(Mm,{})})}));
|
|
87
|
-
//# sourceMappingURL=index-
|
|
86
|
+
`),n=n.replace(/\x00BLOCK(\d+)\x00/g,(r,l)=>t[Number(l)]),n}function Au(){const{courseId:e,lessonId:t}=uf(),n=sf(),r=Ol(d=>d.loadCourse),[l,i]=S.useState(null),[o,s]=S.useState(null),[u,c]=S.useState(!0),{isLessonCompleted:h,completeLesson:m}=Ml();if(S.useEffect(()=>{e&&(c(!0),r(e).then(d=>{if(i(d),d&&d.lessons.length>0){const f=t?d.lessons.find(p=>p.id===t):null;f?s(f):(s(d.lessons[0]),n(`/course/${e}/${d.lessons[0].id}`,{replace:!0}))}c(!1)}))},[e,t,r,n]),u)return a.jsx("div",{className:"loading",children:"Opening the textbook..."});if(!l)return a.jsxs("div",{className:"empty-state",children:[a.jsx("h3",{children:"Course not found"}),a.jsx("p",{children:"The requested course does not exist."}),a.jsx(q,{to:"/",className:"btn btn-primary mt-lg",children:"Return to Campus"})]});const v=o?l.lessons.findIndex(d=>d.id===o.id):0,x=()=>{o&&e&&m(e,o.id)},y=(d,f=!1)=>{s(d),n(`/course/${e}/${d.id}`),f&&window.scrollTo(0,0)},w=()=>{v<l.lessons.length-1&&y(l.lessons[v+1],!0)},N=()=>{v>0&&y(l.lessons[v-1],!0)};return a.jsxs("div",{className:"course-layout",children:[a.jsxs("aside",{className:"course-sidebar",children:[a.jsx("h2",{children:l.title}),a.jsx("nav",{className:"lesson-nav",children:l.lessons.map(d=>{const f=e?h(e,d.id):!1,p=(o==null?void 0:o.id)===d.id;let g="lesson-nav-item";return p&&(g+=" active"),f&&!p&&(g+=" completed"),a.jsx("button",{className:g,onClick:()=>y(d),children:d.title},d.id)})})]}),a.jsx("div",{className:"course-content",children:o&&a.jsxs(a.Fragment,{children:[a.jsx("h1",{children:o.title}),o.keyConcepts.length>0&&a.jsx("div",{className:"key-concepts",children:o.keyConcepts.map(d=>a.jsx("span",{className:"concept-tag",children:d},d))}),a.jsx("div",{className:"lesson-content",dangerouslySetInnerHTML:{__html:Ut(o.content)}}),a.jsxs("div",{className:"lesson-actions",children:[a.jsx("div",{children:v>0&&a.jsx("button",{className:"btn btn-secondary",onClick:N,children:"Previous"})}),a.jsxs("div",{style:{display:"flex",gap:"0.5rem"},children:[e&&!h(e,o.id)&&a.jsx("button",{className:"btn btn-secondary",onClick:x,children:"Mark Complete"}),o.quiz.length>0&&e&&a.jsx(q,{to:`/course/${e}/quiz/${o.id}`,className:"btn btn-gold",children:"Take Quiz"}),v<l.lessons.length-1&&a.jsx("button",{className:"btn btn-primary",onClick:w,children:"Next Lesson"})]})]})]})})]})}function co({number:e,question:t,scenario:n,choices:r,correct:l,explanation:i,selectedAnswer:o,onSelect:s,showResult:u,onAnswered:c,splitLayout:h}){const[m,v]=S.useState(null),[x,y]=S.useState(!1),w=s!==void 0,N=w?o||null:m,d=w?u:x,f=j=>{d&&!w||(w?s==null||s(j):(v(j),y(!0),c==null||c(j)))},p=N===l,g=Object.keys(r).sort(),E=a.jsxs(a.Fragment,{children:[a.jsxs("div",{className:"question-number",children:["Question ",e]}),n&&a.jsx("div",{className:"scenario",dangerouslySetInnerHTML:{__html:Ut(n)}}),a.jsx("div",{className:"question-text",dangerouslySetInnerHTML:{__html:Ut(t)}})]}),k=a.jsx("div",{className:"choices",children:g.map(j=>{let P="choice-btn";return N===j&&(P+=" selected"),d&&j===l&&(P+=" correct"),d&&N===j&&j!==l&&(P+=" incorrect"),a.jsxs("button",{className:P,onClick:()=>f(j),disabled:d&&!w,children:[a.jsxs("span",{className:"choice-letter",children:[j,"."]}),a.jsx("span",{dangerouslySetInnerHTML:{__html:Ut(r[j])}})]},j)})});return h?a.jsxs("div",{className:"question-card",children:[a.jsxs("div",{className:"question-split-layout",children:[a.jsx("div",{className:"question-content",children:E}),a.jsx("div",{className:"answer-choices",children:k})]}),d&&a.jsxs("div",{className:`explanation ${p?"":"wrong"}`,children:[a.jsx("strong",{children:p?"Correct!":`Incorrect. The answer is ${l}.`}),a.jsx("br",{}),a.jsx("span",{dangerouslySetInnerHTML:{__html:Ut(i)}})]})]}):a.jsxs("div",{className:"question-card",children:[E,k,d&&a.jsxs("div",{className:`explanation ${p?"":"wrong"}`,children:[a.jsx("strong",{children:p?"Correct!":`Incorrect. The answer is ${l}.`}),a.jsx("br",{}),a.jsx("span",{dangerouslySetInnerHTML:{__html:Ut(i)}})]})]})}function Tm(){const{courseId:e,lessonId:t}=uf(),n=Ol(g=>g.loadCourse),{recordQuiz:r,completeLesson:l,getCourseProgress:i}=Ml(),[o,s]=S.useState(null),[u,c]=S.useState(null),[h,m]=S.useState(!0),[v,x]=S.useState(!1),[y,w]=S.useState(0),N=e&&t?i(e).quizResults[t]:void 0;S.useEffect(()=>{e&&(m(!0),n(e).then(g=>{if(g&&t){const E=g.lessons.findIndex(k=>k.id===t);s(E>=0?g.lessons[E]:null),E>=0&&E<g.lessons.length-1&&c(g.lessons[E+1].id)}m(!1)}))},[e,t,n]);const[d,f]=S.useState({}),p=(g,E)=>{if(f(k=>({...k,[g]:E})),o){const k={...d,[g]:E};if(Object.keys(k).length===o.quiz.length){const j=o.quiz.filter(P=>k[P.id]===P.correct).length;if(w(j),x(!0),e&&t){const P={courseId:e,lessonId:t,score:j,total:o.quiz.length,answers:k,date:new Date().toISOString()};r(P),l(e,t)}}}};return h?a.jsx("div",{className:"loading",children:"Preparing your examination..."}):!o||o.quiz.length===0?a.jsxs("div",{className:"empty-state",children:[a.jsx("h3",{children:"No quiz available"}),a.jsx("p",{children:"This lesson does not have a quiz."}),a.jsx(q,{to:`/course/${e}`,className:"btn btn-primary mt-lg",children:"Back to Course"})]}):a.jsxs("div",{className:"quiz-container",children:[a.jsxs("div",{className:"quiz-header",children:[a.jsxs("h1",{children:[o.title," — Quiz"]}),a.jsx("p",{className:"quiz-progress",children:v?`Score: ${y}/${o.quiz.length} (${Math.round(y/o.quiz.length*100)}%)`:`${Object.keys(d).length}/${o.quiz.length} answered`}),N&&!v&&a.jsxs("p",{className:"text-muted mt-sm",children:["Previous best: ",N.score,"/",N.total]})]}),o.quiz.map((g,E)=>a.jsx(co,{number:E+1,question:g.question,choices:g.choices,correct:g.correct,explanation:g.explanation,onAnswered:k=>p(g.id,k)},g.id)),v&&a.jsxs("div",{className:"text-center mt-xl",children:[a.jsx("p",{className:"mb-lg",style:{fontSize:"1.25rem",fontFamily:"var(--font-serif)"},children:y===o.quiz.length?"Perfect score! Exemplary scholarship.":y>=o.quiz.length*.8?"Well done, scholar. You have demonstrated understanding.":"Review the material and try again. Persistence is the path to mastery."}),u?a.jsx(q,{to:`/course/${e}/${u}`,className:"btn btn-primary",children:"Next Lesson"}):a.jsx(q,{to:`/course/${e}`,className:"btn btn-primary",children:"Return to Course"})]})]})}function zm({totalSeconds:e,onTimeUp:t,running:n}){const[r,l]=S.useState(e),i=S.useCallback(()=>{t()},[t]);S.useEffect(()=>{if(!n)return;const h=setInterval(()=>{l(m=>m<=1?(clearInterval(h),i(),0):m-1)},1e3);return()=>clearInterval(h)},[n,i]);const o=Math.floor(r/60),s=r%60,u=r/e*100;let c="timer-display";return u<20?c+=" critical":u<40&&(c+=" warning"),a.jsxs("span",{className:c,children:[String(o).padStart(2,"0"),":",String(s).padStart(2,"0")]})}function Fu({text:e}){const t=e.split(/(```[\s\S]*?```)/g);return a.jsx("div",{className:"passage-block",children:a.jsx("div",{className:"passage-content",children:t.map((n,r)=>{if(n.startsWith("```")){const l=n.match(/^```(\w*)\n?([\s\S]*?)```$/),i=l?l[2]:n.slice(3,-3);return a.jsx("pre",{children:a.jsx("code",{children:i})},r)}return n.split(/\n\n+/).map((l,i)=>a.jsx("p",{children:l},`${r}-${i}`))})})})}function $u(e,t,n){if(!t)return null;const r=e[n];return r.passageId?t[r.passageId]??null:null}function Rm(){const[e,t]=S.useState(null),[n,r]=S.useState("intro"),[l,i]=S.useState({}),[o,s]=S.useState(0),[u,c]=S.useState(!0),[h,m]=S.useState(null),{studentName:v,setStudentName:x,addCertificate:y}=fs(),[w,N]=S.useState(v);S.useEffect(()=>{fetch("/api/plsat/3.0").then(k=>k.json()).then(k=>{t(k),c(!1)}).catch(()=>c(!1))},[]);const d=S.useCallback(()=>{if(!e)return;const k=e.questions.filter(de=>l[de.id]===de.correct).length,j=e.questions.length,P=Math.round(k/j*100),M=P>=e.passThreshold*100,z={name:w||"Anonymous Scholar",score:k,total:j,percentage:P,passed:M,plsatVersion:e.version,frameworkVersion:e.frameworkVersion,date:new Date().toISOString()};m(z),y(z),w&&x(w),r("results")},[e,l,w,y,x]),f=S.useCallback(()=>{d()},[d]),p=()=>{d()},g=()=>{i({}),s(0),r("exam")},E=S.useMemo(()=>!e||n!=="exam"?null:$u(e.questions,e.passages,o),[e,n,o]);if(u)return a.jsx("div",{className:"loading",children:"The examination board is convening..."});if(!e)return a.jsxs("div",{className:"empty-state",children:[a.jsx("h3",{children:"PLSAT Unavailable"}),a.jsx("p",{children:"Could not load the examination. Please try again."})]});if(n==="intro")return a.jsxs("div",{className:"plsat-container",children:[a.jsxs("div",{className:"plsat-intro",children:[a.jsx(pn,{size:100}),a.jsx("h1",{children:"The PLSAT"}),a.jsx("p",{className:"plsat-subtitle",children:"Paradigm Licensure Standardized Assessment Test"}),a.jsxs("p",{className:"text-muted",children:["Version ",e.version]})]}),a.jsxs("div",{className:"plsat-rules",children:[a.jsx("h3",{children:"Examination Rules"}),a.jsxs("ul",{children:[a.jsxs("li",{children:[a.jsxs("strong",{children:[e.questions.length," questions"]})," covering all aspects of the Paradigm framework"]}),a.jsxs("li",{children:[a.jsxs("strong",{children:[Math.floor(e.timeLimit/60)," minutes"]})," to complete the examination"]}),a.jsxs("li",{children:[a.jsxs("strong",{children:[e.passThreshold*100,"%"]})," required to pass and receive certification"]}),a.jsx("li",{children:"All questions are multiple choice (A through E)"}),a.jsx("li",{children:"Some questions reference a shared passage — read it carefully"}),a.jsx("li",{children:"You may navigate between questions freely"}),a.jsx("li",{children:"There is no penalty for guessing — answer every question"}),a.jsx("li",{children:"Your certificate will display the PLSAT version for posterity"})]})]}),a.jsxs("div",{className:"text-center",children:[a.jsx("div",{className:"mb-lg",children:a.jsx("input",{type:"text",className:"name-input",placeholder:"Enter your name, scholar",value:w,onChange:k=>N(k.target.value)})}),a.jsx("button",{className:"btn btn-primary btn-lg",onClick:g,children:"Begin Examination"})]})]});if(n==="exam"){const k=e.questions[o],j=Object.keys(l).length;return a.jsxs("div",{className:"plsat-container",children:[a.jsxs("div",{className:"plsat-timer",children:[a.jsx(zm,{totalSeconds:e.timeLimit,onTimeUp:f,running:!0}),a.jsxs("span",{className:"plsat-progress-text",children:["Question ",o+1," of ",e.questions.length," | ",j," answered"]})]}),a.jsxs("div",{style:{marginTop:"var(--space-lg)"},children:[E&&a.jsx(Fu,{text:E}),a.jsx(co,{number:o+1,question:k.question,scenario:k.scenario,choices:k.choices,correct:k.correct,explanation:k.explanation,selectedAnswer:l[k.id],onSelect:P=>i(M=>({...M,[k.id]:P})),showResult:!1,splitLayout:!0})]}),a.jsxs("div",{style:{display:"flex",justifyContent:"space-between",marginTop:"var(--space-lg)"},children:[a.jsx("button",{className:"btn btn-secondary",disabled:o===0,onClick:()=>s(P=>P-1),children:"Previous"}),a.jsxs("div",{style:{display:"flex",gap:"0.5rem"},children:[j===e.questions.length&&a.jsx("button",{className:"btn btn-gold",onClick:p,children:"Submit Examination"}),a.jsx("button",{className:"btn btn-primary",disabled:o===e.questions.length-1,onClick:()=>s(P=>P+1),children:"Next"})]})]}),a.jsx("div",{style:{display:"flex",flexWrap:"wrap",gap:"4px",marginTop:"var(--space-xl)",justifyContent:"center"},children:e.questions.map((P,M)=>a.jsx("button",{onClick:()=>s(M),style:{width:28,height:28,borderRadius:"50%",border:M===o?"2px solid var(--burgundy)":"1px solid var(--parchment-dark)",background:l[P.id]?"var(--gold-bg)":"var(--cream)",color:"var(--ink)",fontSize:"0.6875rem",cursor:"pointer",fontWeight:M===o?600:400},children:M+1},P.id))})]})}return n==="results"&&h?a.jsx("div",{className:"plsat-container",children:a.jsxs("div",{className:"plsat-results",children:[a.jsx(pn,{size:80}),a.jsxs("div",{className:`score-display ${h.passed?"passed":"failed"}`,children:[h.percentage,"%"]}),a.jsx("p",{className:"verdict",children:h.passed?"Congratulations! You have passed the PLSAT.":"The examination board regrets to inform you that you did not pass."}),a.jsxs("p",{className:"text-muted mb-lg",children:["Score: ",h.score,"/",h.total," | PLSAT v",h.plsatVersion," | ",new Date(h.date).toLocaleDateString()]}),a.jsxs("div",{style:{display:"flex",gap:"1rem",justifyContent:"center"},children:[h.passed&&a.jsx(q,{to:"/certificate",className:"btn btn-gold btn-lg",children:"View Certificate"}),a.jsx("button",{className:"btn btn-secondary",onClick:()=>r("review"),children:"Review Answers"}),a.jsx("button",{className:"btn btn-primary",onClick:()=>r("intro"),children:h.passed?"Retake":"Try Again"})]})]})}):n==="review"?a.jsxs("div",{className:"plsat-container",children:[a.jsxs("div",{className:"quiz-header",children:[a.jsx("h1",{children:"PLSAT Review"}),a.jsx("p",{className:"quiz-progress",children:h?`Score: ${h.score}/${h.total} (${h.percentage}%)`:""})]}),e.questions.map((k,j)=>{const P=$u(e.questions,e.passages,j);return a.jsxs("div",{children:[P&&a.jsx(Fu,{text:P}),a.jsx(co,{number:j+1,question:k.question,scenario:k.scenario,choices:k.choices,correct:k.correct,explanation:k.explanation,selectedAnswer:l[k.id],onSelect:()=>{},showResult:!0,splitLayout:!0})]},k.id)}),a.jsx("div",{className:"text-center mt-xl",children:a.jsx("button",{className:"btn btn-primary",onClick:()=>r("results"),children:"Back to Results"})})]}):null}function Im(){const[e,t]=S.useState(null),[n,r]=S.useState(!0);return S.useEffect(()=>{fetch("/api/reference").then(l=>l.json()).then(l=>{t(l),r(!1)}).catch(()=>r(!1))},[]),n?a.jsx("div",{className:"loading",children:"Opening the reference library..."}):e?a.jsxs("div",{className:"reference-container",children:[a.jsx("h1",{className:"mb-lg",children:"Reference Library"}),e.sections.map(l=>a.jsxs("section",{className:"reference-section",children:[a.jsx("h2",{children:l.title}),a.jsx("div",{className:"reference-grid",children:l.cards.map(i=>a.jsxs("div",{className:"ref-card",children:[i.symbol&&a.jsx("div",{className:"ref-symbol",children:i.symbol}),a.jsx("h4",{children:i.name}),a.jsx("p",{children:i.description}),i.examples&&i.examples.length>0&&a.jsx("div",{className:"ref-examples",children:i.examples.map(o=>a.jsx("span",{className:"ref-example",children:o},o))}),i.logger&&a.jsx("p",{style:{marginTop:"0.5rem"},children:a.jsx("code",{children:i.logger})}),i.when&&a.jsx("p",{className:"text-muted",style:{fontSize:"0.8125rem",marginTop:"0.25rem"},children:a.jsx("em",{children:i.when})}),i.command&&a.jsx("p",{style:{marginTop:"0.5rem"},children:a.jsx("code",{children:i.command})}),i.steps&&i.steps.length>0&&a.jsx("ol",{style:{fontSize:"0.875rem",paddingLeft:"1.25rem",marginTop:"0.5rem"},children:i.steps.map((o,s)=>a.jsx("li",{style:{marginBottom:"0.25rem"},children:o},s))})]},i.id))})]},l.id))]}):a.jsxs("div",{className:"empty-state",children:[a.jsx("h3",{children:"Reference library unavailable"}),a.jsx("p",{children:"Could not load reference data."})]})}function Om(){const{certificates:e}=fs(),t=e.filter(r=>r.passed),n=t.length>0?t.reduce((r,l)=>new Date(l.date)>new Date(r.date)?l:r):null;return n?a.jsxs("div",{className:"certificate-container",children:[a.jsx("div",{className:"no-print text-center mb-lg",children:a.jsx("button",{className:"btn btn-gold",onClick:()=>window.print(),children:"Print Certificate"})}),a.jsxs("div",{className:"certificate",children:[a.jsx(pn,{size:100,className:"cert-seal"}),a.jsx("h1",{children:"Paradigm University"}),a.jsx("p",{className:"cert-title",children:"Universitas Paradigmatica — Lux in Codice"}),a.jsx("div",{className:"gold-divider"}),a.jsx("p",{style:{fontSize:"0.875rem",color:"var(--ink-muted)",marginTop:"var(--space-lg)"},children:"This is to certify that"}),a.jsx("div",{className:"cert-name",children:n.name}),a.jsxs("p",{className:"cert-body",children:["has successfully completed the",a.jsx("br",{}),a.jsx("strong",{children:"Paradigm Licensure Standardized Assessment Test"}),a.jsx("br",{}),"and is hereby recognized as a certified Paradigm practitioner."]}),a.jsxs("p",{className:"cert-score",children:["Score: ",n.score,"/",n.total," (",n.percentage,"%)"]}),a.jsx("div",{className:"gold-divider"}),a.jsxs("dl",{className:"cert-meta",children:[a.jsxs("div",{children:[a.jsx("dt",{children:"PLSAT Version"}),a.jsxs("dd",{children:["v",n.plsatVersion]})]}),a.jsxs("div",{children:[a.jsx("dt",{children:"Framework Version"}),a.jsxs("dd",{children:["v",n.frameworkVersion]})]}),a.jsxs("div",{children:[a.jsx("dt",{children:"Date Issued"}),a.jsx("dd",{children:new Date(n.date).toLocaleDateString("en-US",{year:"numeric",month:"long",day:"numeric"})})]})]})]}),e.length>1&&a.jsxs("div",{className:"no-print mt-xl",children:[a.jsx("h3",{className:"mb-md",children:"All Attempts"}),[...e].reverse().map((r,l)=>a.jsx("div",{className:"ref-card",style:{marginBottom:"0.5rem"},children:a.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:[a.jsxs("span",{children:["PLSAT v",r.plsatVersion," — ",r.score,"/",r.total," (",r.percentage,"%)",r.passed?" ✓":""]}),a.jsx("span",{className:"text-muted",children:new Date(r.date).toLocaleDateString()})]})},l))]})]}):a.jsxs("div",{className:"certificate-container",children:[a.jsxs("div",{className:"empty-state",children:[a.jsx(pn,{size:80}),a.jsx("h3",{className:"mt-lg",children:"No Certificates Yet"}),a.jsx("p",{children:"Pass the PLSAT examination to earn your Paradigm certification."}),a.jsx(q,{to:"/plsat",className:"btn btn-primary mt-lg",children:"Take the PLSAT"})]}),e.length>0&&a.jsxs("div",{className:"mt-xl",children:[a.jsx("h3",{className:"mb-md",children:"Previous Attempts"}),e.map((r,l)=>a.jsx("div",{className:"ref-card",style:{marginBottom:"0.5rem"},children:a.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:[a.jsxs("span",{children:["PLSAT v",r.plsatVersion," — ",r.score,"/",r.total," (",r.percentage,"%)"]}),a.jsx("span",{className:"text-muted",children:new Date(r.date).toLocaleDateString()})]})},l))]})]})}function Mm(){return a.jsxs("div",{className:"app",children:[a.jsx(Zh,{version:"6.0.3"}),a.jsx("main",{className:"main-content",children:a.jsxs(Bh,{children:[a.jsx(We,{path:"/",element:a.jsx(Pm,{})}),a.jsx(We,{path:"/courses",element:a.jsx(_m,{})}),a.jsx(We,{path:"/course/:courseId",element:a.jsx(Au,{})}),a.jsx(We,{path:"/course/:courseId/:lessonId",element:a.jsx(Au,{})}),a.jsx(We,{path:"/course/:courseId/quiz/:lessonId",element:a.jsx(Tm,{})}),a.jsx(We,{path:"/plsat",element:a.jsx(Rm,{})}),a.jsx(We,{path:"/reference",element:a.jsx(Im,{})}),a.jsx(We,{path:"/certificate",element:a.jsx(Om,{})})]})})]})}hi.createRoot(document.getElementById("root")).render(a.jsx(vo.StrictMode,{children:a.jsx(Gh,{children:a.jsx(Mm,{})})}));
|
|
87
|
+
//# sourceMappingURL=index-SNyIB61M.js.map
|