site: publish the platform guides at /platforms/ and link them from an About page

(cherry picked from commit 408d6cdfd76d13945db1d9727b58feca23d1e48b)
This commit is contained in:
Paperclip Builder
2026-10-26 22:50:09 +11:00
committed by Sam Rolfe
parent d793ab0871
commit 59580b6e45
4 changed files with 226 additions and 0 deletions

View File

@@ -0,0 +1,49 @@
---
id: about-sources
area: about
level: 3
title: "What the assistant reads"
claim: "Four sources, one pool, and a published rule for every one of them."
confidence: running
period: "2026–"
tech: [Gitea, Obsidian, Graphify, Qdrant, SQLite]
metrics: []
artefacts: []
public: true
last_verified: 2026-10-26
tags: [ai, sources, corpus, retrieval]
---
# What the assistant reads
The assistant answers from a pool built out of four sources, not from a single
folder of copy.
| Source | Tier | What it contributes |
|---|---|---|
| This site's content | 1 | The curated claims: what Sam says is true about the work |
| The Gitea estate | 2 | README files, file trees, selected source files, commit messages and language statistics |
| The notes vault | 2 | Project and area notes, in Sam's own words |
| The knowledge graph | 2 | Nodes and edges over the vault, each joined back to the note it came from |
Tier 1 wins when the two disagree. A harvested README can be out of date; the
curated claim is the one that is maintained.
Every chunk records the platform it came from, the URL or repository path it can
be opened at, the area it feeds, its tier, its honest confidence and when it last
changed. A chunk without an origin is refused, not defaulted.
The rules are not hidden in code. Each platform has a guide that says what it is,
where it lives, what is included, what is excluded and whether it is enabled.
Those guides are shown at [the sources page](/platforms/) and are the same files
the ingestion pipeline reads.
## What is excluded
`node_modules`, virtualenvs, git internals, trash, editor state, the SilverBullet
auth file, credential-shaped files, binaries and media. Media is recorded as an
image reference and never turned into text. Personal and family notes are not
read.
The finished pool is scanned for credential-shaped content before a run can
succeed, so the exclusion list is checked rather than trusted.

View File

@@ -100,6 +100,13 @@ func (s *Site) Build() error {
if err := writePage("/404.html", templates.NotFoundPage(s.NotFoundPage())); err != nil {
return err
}
// The platform guides are configuration and public copy at the same time.
// Rendering them here keeps the page and the pipeline's include/exclude rules
// from drifting: both read platforms/*.yml.
if _, err := RenderPlatforms(s.Config.Root, s.Config.OutDir); err != nil {
return fmt.Errorf("platform guides: %w", err)
}
pages++
for _, f := range s.Fragments {
if err := writeFile(filepath.Join(s.Config.OutDir, filepath.FromSlash(f.File)), []byte(f.HTML)); err != nil {

128
internal/site/platforms.go Normal file
View File

@@ -0,0 +1,128 @@
package site
import (
"encoding/json"
"fmt"
"html/template"
"os"
"path/filepath"
"sort"
"strings"
"gopkg.in/yaml.v3"
)
// PlatformGuide is one `platforms/<name>.yml` file: configuration and public
// copy at the same time. The pipeline reads include/exclude from here; the site
// shows what, where it lives, and what is read.
type PlatformGuide struct {
Name string `yaml:"name" json:"name"`
Enabled bool `yaml:"enabled" json:"enabled"`
What string `yaml:"what" json:"what"`
Fits []string `yaml:"fits" json:"fits"`
Base string `yaml:"base" json:"base"`
Read []string `yaml:"read" json:"read"`
Public bool `yaml:"public" json:"public"`
Include struct {
Repos any `yaml:"repos" json:"repos"`
Paths []string `yaml:"paths" json:"paths"`
} `yaml:"include" json:"include"`
Exclude struct {
Repos []string `yaml:"repos" json:"repos"`
Paths []string `yaml:"paths" json:"paths"`
} `yaml:"exclude" json:"exclude"`
}
// LoadPlatforms reads every guide. A file that does not parse is an error: the
// site must not silently show a different list from the one the pipeline reads.
func LoadPlatforms(root string) ([]PlatformGuide, error) {
dir := filepath.Join(root, "platforms")
entries, err := os.ReadDir(dir)
if err != nil {
return nil, err
}
var out []PlatformGuide
for _, entry := range entries {
if entry.IsDir() || !(strings.HasSuffix(entry.Name(), ".yml") || strings.HasSuffix(entry.Name(), ".yaml")) {
continue
}
raw, err := os.ReadFile(filepath.Join(dir, entry.Name()))
if err != nil {
return nil, err
}
var guide PlatformGuide
if err := yaml.Unmarshal(raw, &guide); err != nil {
return nil, fmt.Errorf("%s: %w", entry.Name(), err)
}
if guide.Name == "" || guide.What == "" {
return nil, fmt.Errorf("%s: name and what are required", entry.Name())
}
out = append(out, guide)
}
sort.Slice(out, func(i, j int) bool { return out[i].Name < out[j].Name })
return out, nil
}
// RenderPlatforms writes /platforms/index.html and /platforms/index.json.
//
// The page is generated outside the templ layout because templ needs a Node-free
// generator on PATH and the build host has no network requirement. It uses the
// same stylesheet, the same navigation and the same wording as the rest of the
// site; the only thing it does not have is the presentation panel, which has no
// meaning on a reference page.
func RenderPlatforms(root, outDir string) (int, error) {
guides, err := LoadPlatforms(root)
if err != nil {
return 0, err
}
target := filepath.Join(outDir, "platforms")
if err := os.MkdirAll(target, 0o755); err != nil {
return 0, err
}
var body strings.Builder
body.WriteString(`<p class="lede">The assistant reads four sources. Three are harvested from the estate; the fourth is the curated text this site is built from. Everything below is the same configuration the pipeline runs.</p>`)
for _, guide := range guides {
state := "enabled"
if !guide.Enabled {
state = "disabled"
}
body.WriteString(`<section class="platform">`)
fmt.Fprintf(&body, `<h2>%s <span class="conf">%s</span></h2>`, template.HTMLEscapeString(guide.Name), state)
fmt.Fprintf(&body, `<p>%s</p>`, template.HTMLEscapeString(strings.TrimSpace(guide.What)))
fmt.Fprintf(&body, `<dl><dt>Where it lives</dt><dd>%s</dd>`, template.HTMLEscapeString(guide.Base))
fmt.Fprintf(&body, `<dt>Feeds</dt><dd>%s</dd>`, template.HTMLEscapeString(strings.Join(guide.Fits, ", ")))
fmt.Fprintf(&body, `<dt>Reads</dt><dd>%s</dd>`, template.HTMLEscapeString(strings.Join(guide.Read, ", ")))
if len(guide.Include.Paths) > 0 {
fmt.Fprintf(&body, `<dt>Includes</dt><dd>%s</dd>`, template.HTMLEscapeString(strings.Join(guide.Include.Paths, ", ")))
}
if len(guide.Exclude.Paths) > 0 {
fmt.Fprintf(&body, `<dt>Excludes</dt><dd>%s</dd>`, template.HTMLEscapeString(strings.Join(guide.Exclude.Paths, ", ")))
}
body.WriteString(`</dl></section>`)
}
page, err := template.New("platforms").Parse(platformsPage)
if err != nil {
return 0, err
}
file, err := os.Create(filepath.Join(target, "index.html"))
if err != nil {
return 0, err
}
defer file.Close()
if err := page.Execute(file, map[string]any{"Body": template.HTML(body.String())}); err != nil {
return 0, err
}
raw, err := json.MarshalIndent(map[string]any{"version": 1, "platforms": guides}, "", " ")
if err != nil {
return 0, err
}
if err := os.WriteFile(filepath.Join(target, "index.json"), append(raw, '\n'), 0o644); err != nil {
return 0, err
}
return len(guides), nil
}
const platformsPage = `<!doctype html><html lang="en-AU"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Sources and platform guides — Sam Rolfe</title><meta name="description" content="Every source the assistant reads, with the include and exclude rules, shown as configuration and as public copy."><meta name="color-scheme" content="dark"><link rel="stylesheet" href="/static/site.css"></head><body><a class="skip-link" href="#main">Skip to content</a><header class="topbar"><a class="brand" href="/"><span class="brand-mark">SR</span> <span class="brand-text">Sam Rolfe <span class="brand-sub">AI · Platform · Edge</span></span></a><nav class="nav nav-rail" aria-label="Sections"><a href="/ai/" class="nav-link"><span class="nav-gutter" aria-hidden="true">AI</span> <span class="nav-title">AI &amp; Agentic Systems</span></a><a href="/platform/" class="nav-link"><span class="nav-gutter" aria-hidden="true">PL</span> <span class="nav-title">Platform &amp; Infrastructure</span></a><a href="/edge/" class="nav-link"><span class="nav-gutter" aria-hidden="true">ED</span> <span class="nav-title">Edge &amp; Devices</span></a><a href="/products/" class="nav-link"><span class="nav-gutter" aria-hidden="true">PR</span> <span class="nav-title">Products</span></a><a href="/history/" class="nav-link"><span class="nav-gutter" aria-hidden="true">HI</span> <span class="nav-title">History</span></a><a href="/about/" class="nav-link"><span class="nav-gutter" aria-hidden="true">AB</span> <span class="nav-title">About</span></a><a href="/evidence/" class="nav-link"><span class="nav-gutter" aria-hidden="true">EV</span> <span class="nav-title">Evidence index</span></a></nav></header><div class="shell"><main id="main" class="main"><nav class="crumbs" aria-label="Breadcrumb"><ol><li><a href="/">Home</a></li><li><span aria-current="page">Sources</span></li></ol></nav><article class="doc"><header class="doc-head"><p class="doc-kicker">AI overlay</p><h1>What the assistant reads</h1><p class="doc-claim">Four sources, one pool. Content is tier 1: a curated claim outranks harvested text when the two disagree.</p></header>{{.Body}}<p class="doc-foot"><a href="/evidence/">Every artefact</a> · <a href="/search">Search the site</a></p></article></main></div><footer class="footer"><p class="footer-line">Twenty-five years shipping software · Melbourne · remote · hybrid · office · travel</p><p class="footer-links"><a href="/evidence/">Evidence index</a> <a href="/search">Search</a></p></footer></body></html>`

View File

@@ -0,0 +1,42 @@
package site
import (
"os"
"path/filepath"
"strings"
"testing"
)
func TestRenderPlatformsShowsTheGuides(t *testing.T) {
root, err := filepath.Abs(filepath.Join("..", ".."))
if err != nil {
t.Fatal(err)
}
out := t.TempDir()
count, err := RenderPlatforms(root, out)
if err != nil {
t.Fatalf("RenderPlatforms: %v", err)
}
if count != 3 {
t.Fatalf("got %d guides, want 3", count)
}
raw, err := os.ReadFile(filepath.Join(out, "platforms", "index.html"))
if err != nil {
t.Fatalf("read page: %v", err)
}
page := strings.ToLower(string(raw))
for _, want := range []string{
"what the assistant reads",
"self-hosted git",
"personal knowledge base",
"knowledge graph over the notes",
"node_modules",
} {
if !strings.Contains(page, want) {
t.Errorf("page does not contain %q", want)
}
}
if _, err := os.Stat(filepath.Join(out, "platforms", "index.json")); err != nil {
t.Errorf("index.json missing: %v", err)
}
}