@hippo-digital/hippocampus 1.0.0-rc.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/CHANGELOG.md +55 -0
- package/LICENSE +21 -0
- package/README.md +153 -0
- package/assets/dist/hippocampus.css +1 -0
- package/assets/hippocampus.scss +896 -0
- package/assets/javascript/blueprint.js +123 -0
- package/bin/hippocampus.js +106 -0
- package/docs/agent-roadmap.md +217 -0
- package/docs/agent-workflow.md +56 -0
- package/docs/agentic-patterns-to-port.md +273 -0
- package/docs/colour-pairings.md +41 -0
- package/docs/components.md +52 -0
- package/docs/copilot-ncrs-research-curator-agent.md +298 -0
- package/docs/custom-agents-usage.md +95 -0
- package/docs/design-actions-and-decisions.md +95 -0
- package/docs/gp-connect-real-data-to-production.md +66 -0
- package/docs/hippocampus-for-designers-and-researchers.md +261 -0
- package/docs/hippocampus-technical.md +373 -0
- package/docs/prompt-architecture-guardrails.md +39 -0
- package/docs/repeatable-research-round-ingestion.md +239 -0
- package/docs/research-knowledge-graph.md +552 -0
- package/docs/research-source-file-conventions.md +121 -0
- package/docs/source-model.md +252 -0
- package/index.js +47 -0
- package/lib/config.js +46 -0
- package/lib/context.js +59 -0
- package/lib/create-router.js +187 -0
- package/lib/discover-projects.js +45 -0
- package/lib/docs.js +72 -0
- package/lib/host-edit.js +151 -0
- package/lib/lint-knowledge.js +133 -0
- package/lib/load-knowledge.js +629 -0
- package/lib/package-paths.js +32 -0
- package/lib/paths.js +33 -0
- package/lib/resolve-root.js +84 -0
- package/lib/schema-version.js +96 -0
- package/lib/schema.js +346 -0
- package/package.json +70 -0
- package/scripts/audit-provenance.js +147 -0
- package/scripts/doctor.js +114 -0
- package/scripts/eject.js +51 -0
- package/scripts/import-blueprint-spreadsheet.js +242 -0
- package/scripts/import-design-actions.js +230 -0
- package/scripts/import-project-context.js +427 -0
- package/scripts/import-research-batch.js +160 -0
- package/scripts/import-research-deck.js +448 -0
- package/scripts/index-source-artefacts.js +261 -0
- package/scripts/init.js +232 -0
- package/scripts/install-skills.js +160 -0
- package/scripts/lib/artefact-text.js +347 -0
- package/scripts/lib/xlsx-grid.js +114 -0
- package/scripts/link-insights-to-needs.js +209 -0
- package/scripts/migrate-knowledge.js +73 -0
- package/scripts/promote-project-context-draft.js +125 -0
- package/scripts/promote-research-draft.js +236 -0
- package/scripts/smoke-routes.js +157 -0
- package/scripts/sync-project-context.js +236 -0
- package/scripts/sync-research-artefacts.js +294 -0
- package/scripts/triage-research-corpus.js +274 -0
- package/scripts/validate-knowledge.js +49 -0
- package/scripts/validate-skills.js +247 -0
- package/skills/COVERAGE-MATRIX.md +39 -0
- package/skills/README.md +77 -0
- package/skills/SKILL-FORMAT.md +100 -0
- package/skills/add-prototype-screen.skill.md +54 -0
- package/skills/add-scenario.skill.md +47 -0
- package/skills/add-user-needs.skill.md +51 -0
- package/skills/audit-knowledge-source.skill.md +47 -0
- package/skills/capture-route-review-pack.skill.md +52 -0
- package/skills/create-journey-from-scenario.skill.md +50 -0
- package/skills/deliver-service-slice.skill.md +65 -0
- package/skills/examples/README.md +15 -0
- package/skills/examples/non-copilot-research-ingestion.md +68 -0
- package/skills/examples/non-copilot-service-slice.md +64 -0
- package/skills/generate-service-slice.skill.md +57 -0
- package/skills/ingest-project-context.skill.md +58 -0
- package/skills/ingest-research-round.skill.md +60 -0
- package/skills/map-research-to-graph.skill.md +58 -0
- package/skills/record-accessibility-review.skill.md +52 -0
- package/skills/record-design-decision.skill.md +53 -0
- package/skills/review-research-import-draft.skill.md +45 -0
- package/skills/skills.json +464 -0
- package/skills/skills.schema.json +111 -0
- package/skills/structure-project-context-draft.skill.md +51 -0
- package/skills/structure-research-draft.skill.md +51 -0
- package/skills/triage-research-corpus.skill.md +51 -0
- package/skills/write-delivery-summary.skill.md +51 -0
- package/skills/write-route-review-summary.skill.md +55 -0
- package/views/hippocampus/_layout.html +45 -0
- package/views/hippocampus/blueprint-classic.html +39 -0
- package/views/hippocampus/blueprint.html +52 -0
- package/views/hippocampus/components/_blueprint-cell.njk +42 -0
- package/views/hippocampus/components/_blueprint-controls.njk +20 -0
- package/views/hippocampus/components/_blueprint-minimap.njk +14 -0
- package/views/hippocampus/components/_empty-state.njk +12 -0
- package/views/hippocampus/components/_journey-step.njk +21 -0
- package/views/hippocampus/components/_list.njk +23 -0
- package/views/hippocampus/components/_summary-card.njk +15 -0
- package/views/hippocampus/doc.html +11 -0
- package/views/hippocampus/docs.html +19 -0
- package/views/hippocampus/evidence-impact.html +53 -0
- package/views/hippocampus/graph.html +48 -0
- package/views/hippocampus/handover-empty.html +12 -0
- package/views/hippocampus/handover.html +56 -0
- package/views/hippocampus/index.html +46 -0
- package/views/hippocampus/journey-flow.html +31 -0
- package/views/hippocampus/journey.html +23 -0
- package/views/hippocampus/not-found.html +10 -0
- package/views/hippocampus/project.html +102 -0
- package/views/hippocampus/research.html +68 -0
- package/views/hippocampus/route-review.html +83 -0
- package/views/hippocampus/scenarios.html +56 -0
- package/views/hippocampus/trace.html +113 -0
- package/views/hippocampus/user-needs.html +32 -0
- package/views/hippocampus/user.html +157 -0
- package/views/hippocampus/users.html +32 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{% extends "hippocampus/_layout.html" %}
|
|
2
|
+
{% from "hippocampus/components/_summary-card.njk" import summaryCard %}
|
|
3
|
+
|
|
4
|
+
{% block pageTitle %}
|
|
5
|
+
{{ knowledge.project.name }}
|
|
6
|
+
{% endblock %}
|
|
7
|
+
|
|
8
|
+
{% block content %}
|
|
9
|
+
<div class="nhsuk-grid-row">
|
|
10
|
+
<div class="nhsuk-grid-column-two-thirds">
|
|
11
|
+
<span class="nhsuk-caption-l">Prototype Kit add-on spike</span>
|
|
12
|
+
<h1>{{ knowledge.project.name }}</h1>
|
|
13
|
+
<p class="nhsuk-lede-text">{{ knowledge.project.description }}</p>
|
|
14
|
+
|
|
15
|
+
{% if knowledgeValidation.valid %}
|
|
16
|
+
<div class="nhsuk-inset-text">Knowledge validation passed. Source links are intact.</div>
|
|
17
|
+
{% else %}
|
|
18
|
+
<div class="nhsuk-warning-callout">
|
|
19
|
+
<h2 class="nhsuk-warning-callout__label">Knowledge validation failed</h2>
|
|
20
|
+
<ul>
|
|
21
|
+
{% for error in knowledgeValidation.errors %}
|
|
22
|
+
<li>{{ error }}</li>
|
|
23
|
+
{% endfor %}
|
|
24
|
+
</ul>
|
|
25
|
+
</div>
|
|
26
|
+
{% endif %}
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
<div class="knowledge-grid">
|
|
31
|
+
{{ summaryCard("Project context", "Purpose, vision, policy context, channels, risks and source facts.", basePath + "/project", knowledge.projectContext.sourceArtefacts.length + " artefacts") }}
|
|
32
|
+
{{ summaryCard("Users", "The user groups and responsibilities used by the slice.", basePath + "/users", knowledge.users.length + " records") }}
|
|
33
|
+
{{ summaryCard("User needs", "Needs linked to users, scenarios, screens and evidence.", basePath + "/user-needs", knowledge.needs.length + " records") }}
|
|
34
|
+
{{ summaryCard("Scenarios", "Happy paths, edge cases and risks.", basePath + "/scenarios", knowledge.scenarios.length + " records") }}
|
|
35
|
+
{{ summaryCard("Research", "Rounds, participants, insights and design actions.", basePath + "/research", knowledge.researchRounds.length + " rounds") }}
|
|
36
|
+
{{ summaryCard("Relationship graph", "Explicit user, scenario, need, evidence, journey and screen links.", basePath + "/graph", knowledge.relationships.length + " relationships") }}
|
|
37
|
+
{{ summaryCard("Trace tree", "Navigate upstream and downstream through relationship paths.", basePath + "/trace", "graph view") }}
|
|
38
|
+
{{ summaryCard("Documentation", "How to ingest research, record design actions and work with the graph.", basePath + "/docs", "guides") }}
|
|
39
|
+
{% for journey in knowledge.journeys %}
|
|
40
|
+
{{ summaryCard(journey.title, "Journey rendered from structured source data.", basePath + "/journeys/" + journey.id, "journey") }}
|
|
41
|
+
{{ summaryCard(journey.title + " blueprint", "Stacked service blueprint generated from the journey.", basePath + "/journeys/" + journey.id + "/blueprint", "generated view") }}
|
|
42
|
+
{{ summaryCard(journey.title + " flow diagram", "Mermaid flow diagram generated from the same journey steps.", basePath + "/journeys/" + journey.id + "/flow", "generated view") }}
|
|
43
|
+
{{ summaryCard(journey.title + " handover", "Team documentation generated from the same source.", basePath + "/journeys/" + journey.id + "/handover", "documentation") }}
|
|
44
|
+
{% endfor %}
|
|
45
|
+
</div>
|
|
46
|
+
{% endblock %}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{% extends "hippocampus/_layout.html" %}
|
|
2
|
+
|
|
3
|
+
{% block pageTitle %}{{ flow.meta.journeyTitle }} flow diagram{% endblock %}
|
|
4
|
+
|
|
5
|
+
{% block content %}
|
|
6
|
+
<a class="nhsuk-back-link" href="{{ basePath }}/journeys/{{ flow.journey.id }}">Back to journey</a>
|
|
7
|
+
<span class="nhsuk-caption-l">Flow diagram</span>
|
|
8
|
+
<h1>{{ flow.meta.journeyTitle }}</h1>
|
|
9
|
+
<p class="nhsuk-lede-text">Generated from the same journey steps as the blueprint - dashed arrows are exception paths, not the happy path.</p>
|
|
10
|
+
|
|
11
|
+
<div class="knowledge-flow-diagram">
|
|
12
|
+
<pre class="mermaid">{{ flow.mermaidSource }}</pre>
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
<details class="nhsuk-details">
|
|
16
|
+
<summary class="nhsuk-details__summary">
|
|
17
|
+
<span class="nhsuk-details__summary-text">View diagram source</span>
|
|
18
|
+
</summary>
|
|
19
|
+
<div class="nhsuk-details__text">
|
|
20
|
+
<pre class="knowledge-flow-source">{{ flow.mermaidSource }}</pre>
|
|
21
|
+
</div>
|
|
22
|
+
</details>
|
|
23
|
+
{% endblock %}
|
|
24
|
+
|
|
25
|
+
{% block bodyEnd %}
|
|
26
|
+
{{ super() }}
|
|
27
|
+
<script type="module">
|
|
28
|
+
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs'
|
|
29
|
+
mermaid.initialize({ startOnLoad: true, theme: 'neutral', securityLevel: 'strict' })
|
|
30
|
+
</script>
|
|
31
|
+
{% endblock %}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{% extends "hippocampus/_layout.html" %}
|
|
2
|
+
{% from "hippocampus/components/_journey-step.njk" import journeyStep %}
|
|
3
|
+
|
|
4
|
+
{% block pageTitle %}{{ journey.title }}{% endblock %}
|
|
5
|
+
|
|
6
|
+
{% block content %}
|
|
7
|
+
<a class="nhsuk-back-link" href="{{ basePath }}">Back to knowledge base</a>
|
|
8
|
+
<span class="nhsuk-caption-l">Journey</span>
|
|
9
|
+
<h1>{{ journey.title }}</h1>
|
|
10
|
+
<p class="nhsuk-lede-text">{{ journey.description }}</p>
|
|
11
|
+
|
|
12
|
+
<p>
|
|
13
|
+
<a class="nhsuk-button" href="{{ basePath }}/journeys/{{ journey.id }}/blueprint">View blueprint</a>
|
|
14
|
+
<a class="nhsuk-button nhsuk-button--secondary" href="{{ basePath }}/journeys/{{ journey.id }}/blueprint/classic">View matrix</a>
|
|
15
|
+
<a class="nhsuk-button nhsuk-button--secondary" href="{{ basePath }}/journeys/{{ journey.id }}/flow">View flow diagram</a>
|
|
16
|
+
</p>
|
|
17
|
+
|
|
18
|
+
<ol class="knowledge-timeline">
|
|
19
|
+
{% for step in journey.steps %}
|
|
20
|
+
{{ journeyStep(step, knowledge) }}
|
|
21
|
+
{% endfor %}
|
|
22
|
+
</ol>
|
|
23
|
+
{% endblock %}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{% extends "hippocampus/_layout.html" %}
|
|
2
|
+
|
|
3
|
+
{% block pageTitle %}Not found{% endblock %}
|
|
4
|
+
|
|
5
|
+
{% block content %}
|
|
6
|
+
<h1>Not found</h1>
|
|
7
|
+
<p>The requested knowledge base artefact could not be found.</p>
|
|
8
|
+
<p><a href="{{ basePath }}">Return to knowledge base</a></p>
|
|
9
|
+
{% endblock %}
|
|
10
|
+
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
{% extends "hippocampus/_layout.html" %}
|
|
2
|
+
|
|
3
|
+
{% macro itemList(items, emptyText) %}
|
|
4
|
+
{% if items.length %}
|
|
5
|
+
<div class="knowledge-list">
|
|
6
|
+
{% for item in items %}
|
|
7
|
+
<article class="knowledge-card">
|
|
8
|
+
<h3>{{ item.label or item.title }}</h3>
|
|
9
|
+
{% if item.value %}<p><strong>{{ item.value }}</strong></p>{% endif %}
|
|
10
|
+
{% if item.group %}<p class="knowledge-card__meta">{{ item.group }}</p>{% endif %}
|
|
11
|
+
{% if item.usage %}<p class="knowledge-card__meta">{{ item.usage }}</p>{% endif %}
|
|
12
|
+
{% if item.detail %}<p>{{ item.detail }}</p>{% endif %}
|
|
13
|
+
{% if item.description %}<p>{{ item.description }}</p>{% endif %}
|
|
14
|
+
{% if item.summary %}<p>{{ item.summary }}</p>{% endif %}
|
|
15
|
+
{% if item.impact %}<p><strong>Impact:</strong> {{ item.impact }}</p>{% endif %}
|
|
16
|
+
{% if item.sourcePath %}<p class="knowledge-card__meta">{{ item.sourcePath }}</p>{% endif %}
|
|
17
|
+
</article>
|
|
18
|
+
{% endfor %}
|
|
19
|
+
</div>
|
|
20
|
+
{% else %}
|
|
21
|
+
<p class="knowledge-muted">{{ emptyText }}</p>
|
|
22
|
+
{% endif %}
|
|
23
|
+
{% endmacro %}
|
|
24
|
+
|
|
25
|
+
{% block pageTitle %}Project context{% endblock %}
|
|
26
|
+
|
|
27
|
+
{% block content %}
|
|
28
|
+
<a class="nhsuk-back-link" href="{{ basePath }}">Back to knowledge base</a>
|
|
29
|
+
|
|
30
|
+
<span class="nhsuk-caption-l">{{ knowledge.project.name }}</span>
|
|
31
|
+
<h1>{{ knowledge.projectContext.title }}</h1>
|
|
32
|
+
<p class="nhsuk-lede-text">{{ knowledge.projectContext.summary }}</p>
|
|
33
|
+
|
|
34
|
+
{% if knowledge.projectContext.purpose or knowledge.projectContext.vision or knowledge.projectContext.problemStatement or knowledge.projectContext.serviceProposition %}
|
|
35
|
+
<section class="knowledge-section">
|
|
36
|
+
<h2>Overview</h2>
|
|
37
|
+
{% if knowledge.projectContext.purpose %}
|
|
38
|
+
<h3>Purpose</h3>
|
|
39
|
+
<p>{{ knowledge.projectContext.purpose }}</p>
|
|
40
|
+
{% endif %}
|
|
41
|
+
{% if knowledge.projectContext.vision %}
|
|
42
|
+
<h3>Vision</h3>
|
|
43
|
+
<p>{{ knowledge.projectContext.vision }}</p>
|
|
44
|
+
{% endif %}
|
|
45
|
+
{% if knowledge.projectContext.problemStatement %}
|
|
46
|
+
<h3>Problem statement</h3>
|
|
47
|
+
<p>{{ knowledge.projectContext.problemStatement }}</p>
|
|
48
|
+
{% endif %}
|
|
49
|
+
{% if knowledge.projectContext.serviceProposition %}
|
|
50
|
+
<h3>Service proposition</h3>
|
|
51
|
+
<p>{{ knowledge.projectContext.serviceProposition }}</p>
|
|
52
|
+
{% endif %}
|
|
53
|
+
</section>
|
|
54
|
+
{% endif %}
|
|
55
|
+
|
|
56
|
+
<section class="knowledge-section">
|
|
57
|
+
<h2>Users</h2>
|
|
58
|
+
{{ itemList(knowledge.projectContext.users, "No project-level users have been added yet.") }}
|
|
59
|
+
</section>
|
|
60
|
+
|
|
61
|
+
<section class="knowledge-section">
|
|
62
|
+
<h2>Channels</h2>
|
|
63
|
+
{{ itemList(knowledge.projectContext.channels, "No service channels have been added yet.") }}
|
|
64
|
+
</section>
|
|
65
|
+
|
|
66
|
+
<section class="knowledge-section">
|
|
67
|
+
<h2>Policies and constraints</h2>
|
|
68
|
+
<div class="nhsuk-grid-row">
|
|
69
|
+
<div class="nhsuk-grid-column-one-half">
|
|
70
|
+
<h3>Policies</h3>
|
|
71
|
+
{{ itemList(knowledge.projectContext.policies, "No policies have been added yet.") }}
|
|
72
|
+
</div>
|
|
73
|
+
<div class="nhsuk-grid-column-one-half">
|
|
74
|
+
<h3>Constraints</h3>
|
|
75
|
+
{{ itemList(knowledge.projectContext.constraints, "No constraints have been added yet.") }}
|
|
76
|
+
</div>
|
|
77
|
+
</div>
|
|
78
|
+
</section>
|
|
79
|
+
|
|
80
|
+
<section class="knowledge-section">
|
|
81
|
+
<h2>Risks, milestones and facts</h2>
|
|
82
|
+
<div class="nhsuk-grid-row">
|
|
83
|
+
<div class="nhsuk-grid-column-one-third">
|
|
84
|
+
<h3>Risks</h3>
|
|
85
|
+
{{ itemList(knowledge.projectContext.risks, "No risks have been added yet.") }}
|
|
86
|
+
</div>
|
|
87
|
+
<div class="nhsuk-grid-column-one-third">
|
|
88
|
+
<h3>Milestones</h3>
|
|
89
|
+
{{ itemList(knowledge.projectContext.milestones, "No milestones have been added yet.") }}
|
|
90
|
+
</div>
|
|
91
|
+
<div class="nhsuk-grid-column-one-third">
|
|
92
|
+
<h3>Facts</h3>
|
|
93
|
+
{{ itemList(knowledge.projectContext.facts, "No facts have been added yet.") }}
|
|
94
|
+
</div>
|
|
95
|
+
</div>
|
|
96
|
+
</section>
|
|
97
|
+
|
|
98
|
+
<section class="knowledge-section">
|
|
99
|
+
<h2>Source artefacts</h2>
|
|
100
|
+
{{ itemList(knowledge.projectContext.sourceArtefacts, "No project overview artefacts have been promoted yet.") }}
|
|
101
|
+
</section>
|
|
102
|
+
{% endblock %}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{% extends "hippocampus/_layout.html" %}
|
|
2
|
+
|
|
3
|
+
{% block pageTitle %}Research{% endblock %}
|
|
4
|
+
|
|
5
|
+
{% block content %}
|
|
6
|
+
<a class="nhsuk-back-link" href="{{ basePath }}">Back to knowledge base</a>
|
|
7
|
+
|
|
8
|
+
<span class="nhsuk-caption-l">Knowledge graph inputs</span>
|
|
9
|
+
<h1>Research</h1>
|
|
10
|
+
<p class="nhsuk-lede-text">Research rounds, participants, insights and design actions that can be linked into the design knowledge graph.</p>
|
|
11
|
+
|
|
12
|
+
<div class="knowledge-graph-summary">
|
|
13
|
+
<div><strong>{{ research.rounds.length }}</strong><span>Rounds</span></div>
|
|
14
|
+
<div><strong>{{ research.participants.length }}</strong><span>Participants</span></div>
|
|
15
|
+
<div><strong>{{ research.insights.length }}</strong><span>Insights</span></div>
|
|
16
|
+
<div><strong>{{ research.designActions.length }}</strong><span>Design actions</span></div>
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
{% if research.rounds.length %}
|
|
20
|
+
{% for round in research.rounds %}
|
|
21
|
+
<section class="knowledge-section">
|
|
22
|
+
<p class="knowledge-card__meta">{{ round.date }} · {{ round.sourceType }}</p>
|
|
23
|
+
<h2>{{ round.title }}</h2>
|
|
24
|
+
<p>{{ round.summary }}</p>
|
|
25
|
+
|
|
26
|
+
<div class="nhsuk-grid-row">
|
|
27
|
+
<div class="nhsuk-grid-column-one-third">
|
|
28
|
+
<h3 class="nhsuk-heading-s">Participants</h3>
|
|
29
|
+
<ul class="nhsuk-list">
|
|
30
|
+
{% for participant in round.participants %}
|
|
31
|
+
<li>{{ participant.label }} <span class="knowledge-muted">{{ participant.role }}</span></li>
|
|
32
|
+
{% else %}
|
|
33
|
+
<li class="knowledge-muted">None linked</li>
|
|
34
|
+
{% endfor %}
|
|
35
|
+
</ul>
|
|
36
|
+
</div>
|
|
37
|
+
<div class="nhsuk-grid-column-one-third">
|
|
38
|
+
<h3 class="nhsuk-heading-s">Insights</h3>
|
|
39
|
+
<ul class="nhsuk-list">
|
|
40
|
+
{% for insight in round.insights %}
|
|
41
|
+
<li>{{ insight.title }}</li>
|
|
42
|
+
{% else %}
|
|
43
|
+
<li class="knowledge-muted">None linked</li>
|
|
44
|
+
{% endfor %}
|
|
45
|
+
</ul>
|
|
46
|
+
</div>
|
|
47
|
+
<div class="nhsuk-grid-column-one-third">
|
|
48
|
+
<h3 class="nhsuk-heading-s">Design actions</h3>
|
|
49
|
+
<ul class="nhsuk-list">
|
|
50
|
+
{% for action in round.designActions %}
|
|
51
|
+
<li>{{ action.title }} <span class="knowledge-muted">{{ action.status }}</span></li>
|
|
52
|
+
{% else %}
|
|
53
|
+
<li class="knowledge-muted">None linked</li>
|
|
54
|
+
{% endfor %}
|
|
55
|
+
</ul>
|
|
56
|
+
</div>
|
|
57
|
+
</div>
|
|
58
|
+
</section>
|
|
59
|
+
{% endfor %}
|
|
60
|
+
{% else %}
|
|
61
|
+
<section class="knowledge-section">
|
|
62
|
+
<h2>No research rounds imported yet</h2>
|
|
63
|
+
<p>Place PowerPoint or text-based PDF research artefacts in <code>hippocampus/inbox/research</code>, then run <code>npm run research:sync</code> to detect new files, create reviewable drafts and update the research manifest.</p>
|
|
64
|
+
<p>The sync command reports fit warnings when the artefact does not expose participants, insights or design actions clearly, then asks before promoting imported drafts into source data.</p>
|
|
65
|
+
<p>After review, check promotion with <code>npm run promote:research-draft -- --draft hippocampus/imports/research/round-id.json --dry-run</code>, then remove <code>--dry-run</code> to merge it into source data.</p>
|
|
66
|
+
</section>
|
|
67
|
+
{% endif %}
|
|
68
|
+
{% endblock %}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
{% extends "hippocampus/_layout.html" %}
|
|
2
|
+
|
|
3
|
+
{% block pageTitle %}{{ screen.title }}{% endblock %}
|
|
4
|
+
|
|
5
|
+
{% block content %}
|
|
6
|
+
<a class="nhsuk-back-link" href="{{ basePath }}">Back to knowledge base</a>
|
|
7
|
+
<span class="nhsuk-caption-l">Fictional design review task</span>
|
|
8
|
+
<h1>{{ screen.title }}</h1>
|
|
9
|
+
<p class="nhsuk-lede-text">{{ screen.purpose }}</p>
|
|
10
|
+
|
|
11
|
+
<div class="nhsuk-inset-text">
|
|
12
|
+
This page demonstrates a source-backed review workflow. It does not capture or store real delivery evidence.
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
<h2>Route review context</h2>
|
|
16
|
+
<dl class="nhsuk-summary-list">
|
|
17
|
+
<div class="nhsuk-summary-list__row">
|
|
18
|
+
<dt class="nhsuk-summary-list__key">Prototype route</dt>
|
|
19
|
+
<dd class="nhsuk-summary-list__value">{{ screen.route }}</dd>
|
|
20
|
+
</div>
|
|
21
|
+
<div class="nhsuk-summary-list__row">
|
|
22
|
+
<dt class="nhsuk-summary-list__key">Linked journey</dt>
|
|
23
|
+
<dd class="nhsuk-summary-list__value">
|
|
24
|
+
<a href="{{ basePath }}/journeys/{{ journey.id }}">{{ journey.title }}</a>
|
|
25
|
+
</dd>
|
|
26
|
+
</div>
|
|
27
|
+
<div class="nhsuk-summary-list__row">
|
|
28
|
+
<dt class="nhsuk-summary-list__key">Next artefacts</dt>
|
|
29
|
+
<dd class="nhsuk-summary-list__value">Smoke test result, screenshot or route notes, accessibility note and handover summary</dd>
|
|
30
|
+
</div>
|
|
31
|
+
</dl>
|
|
32
|
+
|
|
33
|
+
<h2>Linked user needs</h2>
|
|
34
|
+
<ul class="nhsuk-list nhsuk-list--bullet">
|
|
35
|
+
{% for need in linkedNeeds %}
|
|
36
|
+
<li>{{ need.statement }}</li>
|
|
37
|
+
{% endfor %}
|
|
38
|
+
</ul>
|
|
39
|
+
|
|
40
|
+
{{ checkboxes({
|
|
41
|
+
name: "reviewEvidence",
|
|
42
|
+
fieldset: {
|
|
43
|
+
legend: {
|
|
44
|
+
text: "What evidence is ready for handover?",
|
|
45
|
+
classes: "nhsuk-fieldset__legend--m"
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
items: [
|
|
49
|
+
{
|
|
50
|
+
value: "smoke-tested",
|
|
51
|
+
text: "The changed route passed the smoke test"
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
value: "screenshots-or-notes",
|
|
55
|
+
text: "A screenshot pack or notes-only route review pack exists"
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
value: "accessibility-note",
|
|
59
|
+
text: "An accessibility note separates blockers from improvements"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
value: "handover-summary",
|
|
63
|
+
text: "A dated delivery summary records follow-up work"
|
|
64
|
+
}
|
|
65
|
+
]
|
|
66
|
+
}) }}
|
|
67
|
+
|
|
68
|
+
{{ textarea({
|
|
69
|
+
name: "routeReviewNote",
|
|
70
|
+
id: "route-review-note",
|
|
71
|
+
label: {
|
|
72
|
+
text: "Route review note"
|
|
73
|
+
},
|
|
74
|
+
hint: {
|
|
75
|
+
text: "Record blockers, missing checks or why a review pack is notes-only."
|
|
76
|
+
},
|
|
77
|
+
value: "Smoke test passed. Screenshot capture may be notes-only if tooling is unavailable. Accessibility blockers and follow-up improvements should be separated before handover."
|
|
78
|
+
}) }}
|
|
79
|
+
|
|
80
|
+
<a class="nhsuk-button" href="{{ basePath }}/journeys/{{ journey.id }}/handover">View linked handover</a>
|
|
81
|
+
<p><a href="{{ basePath }}/journeys/{{ journey.id }}/blueprint">View linked blueprint</a></p>
|
|
82
|
+
{% endblock %}
|
|
83
|
+
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{% extends "hippocampus/_layout.html" %}
|
|
2
|
+
{% from "hippocampus/components/_list.njk" import bulletList %}
|
|
3
|
+
{% from "hippocampus/components/_empty-state.njk" import emptyState %}
|
|
4
|
+
|
|
5
|
+
{% block pageTitle %}Scenarios{% endblock %}
|
|
6
|
+
|
|
7
|
+
{% block content %}
|
|
8
|
+
<a class="nhsuk-back-link" href="{{ basePath }}">Back to knowledge base</a>
|
|
9
|
+
<h1>Scenarios</h1>
|
|
10
|
+
{% if knowledge.scenarios.length %}
|
|
11
|
+
{% for scenario in knowledge.scenarios %}
|
|
12
|
+
{% set user = knowledge.index.users[scenario.userId] %}
|
|
13
|
+
<section class="knowledge-section">
|
|
14
|
+
<span class="nhsuk-tag nhsuk-tag--{{ 'red' if scenario.riskLevel == 'high' else 'yellow' }}">{{ scenario.riskLevel }} risk</span>
|
|
15
|
+
<h2>{{ scenario.title }}</h2>
|
|
16
|
+
<p><strong>User:</strong> {{ user.label }}</p>
|
|
17
|
+
<p><strong>Trigger:</strong> {{ scenario.trigger }}</p>
|
|
18
|
+
<p>{{ scenario.context }}</p>
|
|
19
|
+
|
|
20
|
+
{% if scenario.locationSearch %}
|
|
21
|
+
<h3 class="nhsuk-heading-s">Location search</h3>
|
|
22
|
+
<p><strong>Primary intent:</strong> {{ scenario.locationSearch.primaryIntent }}</p>
|
|
23
|
+
<p><strong>Search scope:</strong> {{ scenario.locationSearch.searchScope }}</p>
|
|
24
|
+
|
|
25
|
+
<h4 class="nhsuk-heading-xs">Trigger conditions</h4>
|
|
26
|
+
{{ bulletList(scenario.locationSearch.triggerConditions) }}
|
|
27
|
+
|
|
28
|
+
<h4 class="nhsuk-heading-xs">Available information</h4>
|
|
29
|
+
{{ bulletList(scenario.locationSearch.availableInformation) }}
|
|
30
|
+
|
|
31
|
+
<h4 class="nhsuk-heading-xs">Role of the address</h4>
|
|
32
|
+
<p>{{ scenario.locationSearch.addressRole }}</p>
|
|
33
|
+
|
|
34
|
+
<h4 class="nhsuk-heading-xs">What users learn from residents</h4>
|
|
35
|
+
{{ bulletList(scenario.locationSearch.learnedFromResidents) }}
|
|
36
|
+
|
|
37
|
+
<h4 class="nhsuk-heading-xs">Current and historic residents</h4>
|
|
38
|
+
{{ bulletList(scenario.locationSearch.currentAndHistoricResidents) }}
|
|
39
|
+
|
|
40
|
+
<h4 class="nhsuk-heading-xs">Outcomes</h4>
|
|
41
|
+
{{ bulletList(scenario.locationSearch.outcomes) }}
|
|
42
|
+
|
|
43
|
+
<h4 class="nhsuk-heading-xs">Risks</h4>
|
|
44
|
+
{{ bulletList(scenario.locationSearch.risks) }}
|
|
45
|
+
{% endif %}
|
|
46
|
+
|
|
47
|
+
<h3 class="nhsuk-heading-s">Edge cases</h3>
|
|
48
|
+
{{ bulletList(scenario.edgeCases) }}
|
|
49
|
+
</section>
|
|
50
|
+
{% endfor %}
|
|
51
|
+
{% else %}
|
|
52
|
+
{{ emptyState("No scenarios yet",
|
|
53
|
+
"A scenario is the situation a user is in when a need bites, and what makes it hard.",
|
|
54
|
+
"Add one with the add-scenario skill.") }}
|
|
55
|
+
{% endif %}
|
|
56
|
+
{% endblock %}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
{% extends "hippocampus/_layout.html" %}
|
|
2
|
+
|
|
3
|
+
{% macro renderBranches(branches, direction) %}
|
|
4
|
+
{% if branches.length %}
|
|
5
|
+
<ol class="knowledge-trace-children">
|
|
6
|
+
{% for branch in branches %}
|
|
7
|
+
<li class="knowledge-trace-item">
|
|
8
|
+
<div class="knowledge-trace-item__marker" aria-hidden="true"></div>
|
|
9
|
+
<div class="knowledge-trace-item__content">
|
|
10
|
+
{% if branch.entity.date %}
|
|
11
|
+
<p class="knowledge-trace-item__date">{{ branch.entity.date }}</p>
|
|
12
|
+
{% endif %}
|
|
13
|
+
<h3 class="knowledge-trace-item__heading">
|
|
14
|
+
<a href="{{ basePath }}/trace?entity={{ branch.entity.id }}">{{ branch.entity.label }}</a>
|
|
15
|
+
</h3>
|
|
16
|
+
<span class="knowledge-trace-item__type knowledge-trace-item__type--{{ branch.entity.typeSlug }}">{{ branch.entity.type }}</span>
|
|
17
|
+
<p class="knowledge-trace-item__relationship">
|
|
18
|
+
{{ branch.relationship.fromLabel }} <strong>{{ branch.relationship.label }}</strong> {{ branch.relationship.toLabel }}
|
|
19
|
+
</p>
|
|
20
|
+
{% if branch.seen %}
|
|
21
|
+
<p class="knowledge-muted">Cycle already shown.</p>
|
|
22
|
+
{% endif %}
|
|
23
|
+
{{ renderBranches(branch.children, direction) }}
|
|
24
|
+
</div>
|
|
25
|
+
</li>
|
|
26
|
+
{% endfor %}
|
|
27
|
+
</ol>
|
|
28
|
+
{% else %}
|
|
29
|
+
<p class="knowledge-muted">No linked entities in this direction.</p>
|
|
30
|
+
{% endif %}
|
|
31
|
+
{% endmacro %}
|
|
32
|
+
|
|
33
|
+
{% block pageTitle %}Trace tree{% endblock %}
|
|
34
|
+
|
|
35
|
+
{% block content %}
|
|
36
|
+
<a class="nhsuk-back-link" href="{{ basePath }}">Back to knowledge base</a>
|
|
37
|
+
|
|
38
|
+
<span class="nhsuk-caption-l">Knowledge graph</span>
|
|
39
|
+
<h1>Trace tree</h1>
|
|
40
|
+
<p class="nhsuk-lede-text">Navigate from old design inputs, through research and insight, into actions, newer design work and content.</p>
|
|
41
|
+
|
|
42
|
+
<section class="knowledge-section">
|
|
43
|
+
<form method="get" action="{{ basePath }}/trace" class="knowledge-trace-controls" data-hippocampus-trace-form>
|
|
44
|
+
<div class="knowledge-trace-controls__field">
|
|
45
|
+
<label class="nhsuk-label" for="type">Type</label>
|
|
46
|
+
<select class="nhsuk-select" id="type" name="type" data-trace-type>
|
|
47
|
+
<option value="">Select type</option>
|
|
48
|
+
{% for type in trace.entityTypes %}
|
|
49
|
+
<option value="{{ type }}" {{ "selected" if trace.entityType == type else "" }}>{{ type }}</option>
|
|
50
|
+
{% endfor %}
|
|
51
|
+
</select>
|
|
52
|
+
</div>
|
|
53
|
+
|
|
54
|
+
<div class="knowledge-trace-controls__field">
|
|
55
|
+
<label class="nhsuk-label" for="entity">Entity</label>
|
|
56
|
+
<select class="nhsuk-select" id="entity" name="entity" data-trace-entity {{ "disabled" if not trace.entityType else "" }}>
|
|
57
|
+
<option value="">Select entity</option>
|
|
58
|
+
{% for node in trace.nodes %}
|
|
59
|
+
{% set hiddenForType = trace.entityType and node.type != trace.entityType %}
|
|
60
|
+
<option value="{{ node.id }}" data-entity-type="{{ node.type }}" {{ "selected" if trace.selected and node.id == trace.selected.id else "" }} {{ "hidden disabled" if hiddenForType else "" }}>
|
|
61
|
+
{{ node.label }}
|
|
62
|
+
</option>
|
|
63
|
+
{% endfor %}
|
|
64
|
+
</select>
|
|
65
|
+
</div>
|
|
66
|
+
|
|
67
|
+
<button class="nhsuk-button knowledge-trace-controls__submit" type="submit">View trace</button>
|
|
68
|
+
</form>
|
|
69
|
+
</section>
|
|
70
|
+
|
|
71
|
+
{% if trace.selected %}
|
|
72
|
+
<section class="knowledge-section">
|
|
73
|
+
<h2>Timeline trace</h2>
|
|
74
|
+
|
|
75
|
+
<ol class="knowledge-trace-timeline" aria-label="Knowledge trace timeline">
|
|
76
|
+
<li class="knowledge-trace-group knowledge-trace-group--upstream">
|
|
77
|
+
<div class="knowledge-trace-group__content">
|
|
78
|
+
<h3>Earlier inputs</h3>
|
|
79
|
+
{{ renderBranches(trace.upstream, "upstream") }}
|
|
80
|
+
</div>
|
|
81
|
+
</li>
|
|
82
|
+
|
|
83
|
+
<li class="knowledge-trace-item knowledge-trace-item--selected">
|
|
84
|
+
<div class="knowledge-trace-item__marker" aria-hidden="true"></div>
|
|
85
|
+
<div class="knowledge-trace-item__content">
|
|
86
|
+
{% if trace.selected.date %}
|
|
87
|
+
<p class="knowledge-trace-item__date">{{ trace.selected.date }}</p>
|
|
88
|
+
{% endif %}
|
|
89
|
+
<h3 class="knowledge-trace-item__heading">{{ trace.selected.label }}</h3>
|
|
90
|
+
<span class="knowledge-trace-item__type knowledge-trace-item__type--{{ trace.selected.typeSlug }}">{{ trace.selected.type }}</span>
|
|
91
|
+
</div>
|
|
92
|
+
</li>
|
|
93
|
+
|
|
94
|
+
<li class="knowledge-trace-group knowledge-trace-group--downstream">
|
|
95
|
+
<div class="knowledge-trace-group__content">
|
|
96
|
+
<h3>Later outputs</h3>
|
|
97
|
+
{{ renderBranches(trace.downstream, "downstream") }}
|
|
98
|
+
</div>
|
|
99
|
+
</li>
|
|
100
|
+
</ol>
|
|
101
|
+
</section>
|
|
102
|
+
{% else %}
|
|
103
|
+
<section class="knowledge-section">
|
|
104
|
+
{% if trace.entityType %}
|
|
105
|
+
<h2>Choose an entity</h2>
|
|
106
|
+
<p>Select one of the {{ trace.entityType | lower }} entries to see its timeline trace.</p>
|
|
107
|
+
{% else %}
|
|
108
|
+
<h2>Choose a type</h2>
|
|
109
|
+
<p>Select an entity type first. The entity list will then show the matching results.</p>
|
|
110
|
+
{% endif %}
|
|
111
|
+
</section>
|
|
112
|
+
{% endif %}
|
|
113
|
+
{% endblock %}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{% extends "hippocampus/_layout.html" %}
|
|
2
|
+
{% from "hippocampus/components/_empty-state.njk" import emptyState %}
|
|
3
|
+
|
|
4
|
+
{% block pageTitle %}User needs{% endblock %}
|
|
5
|
+
|
|
6
|
+
{% block content %}
|
|
7
|
+
<a class="nhsuk-back-link" href="{{ basePath }}">Back to knowledge base</a>
|
|
8
|
+
<h1>User needs</h1>
|
|
9
|
+
<div class="knowledge-list">
|
|
10
|
+
{% if knowledge.needs.length %}
|
|
11
|
+
{% for need in knowledge.needs %}
|
|
12
|
+
{% set user = knowledge.index.users[need.userId] %}
|
|
13
|
+
<article class="knowledge-card">
|
|
14
|
+
<p class="knowledge-card__meta">{{ user.label }} · {{ need.priority }} priority</p>
|
|
15
|
+
<h2 class="nhsuk-heading-s">{{ need.statement }}</h2>
|
|
16
|
+
<h3 class="nhsuk-heading-xs">Evidence</h3>
|
|
17
|
+
<ul class="nhsuk-list">
|
|
18
|
+
{% for evidenceId in need.evidenceIds %}
|
|
19
|
+
{% set evidence = knowledge.index.evidence[evidenceId] %}
|
|
20
|
+
<li>{{ evidence.title }}</li>
|
|
21
|
+
{% endfor %}
|
|
22
|
+
</ul>
|
|
23
|
+
</article>
|
|
24
|
+
{% endfor %}
|
|
25
|
+
{% else %}
|
|
26
|
+
{{ emptyState("No user needs yet",
|
|
27
|
+
"A need says who wants what, and why - the \"so that\" clause is what stops two users' needs being merged into one.",
|
|
28
|
+
"Add them with the add-user-needs skill once there is at least one user.") }}
|
|
29
|
+
{% endif %}
|
|
30
|
+
</div>
|
|
31
|
+
{% endblock %}
|
|
32
|
+
|