Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,20 @@ jobs:
mkdir -p "$RUNNER_TEMP/dp-docs-bin"
GOBIN="$RUNNER_TEMP/dp-docs-bin" go install github.com/scbrown/desire-path/cmd/dp@v0.2.1
env -i HOME="$RUNNER_TEMP/dp-docs-home" PATH="$RUNNER_TEMP/dp-docs-bin:/usr/bin:/bin" dp version

repository-pendant-source:
name: Repository pendant source controls
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install pinned RDF test parser
run: python3 -m pip install rdflib==7.6.0
- name: Test copied pointer and publication boundaries
run: |
python3 scripts/test-repository-share-query.py
python3 scripts/test-repository-knowledge.py
python3 scripts/test-repository-share-publication.py
18 changes: 18 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,21 @@ jobs:
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

repository-pendant:
name: Verify repository pendant
needs: goreleaser
runs-on: ubuntu-latest
timeout-minutes: 45
permissions:
contents: read
env:
RELEASE_TAG: ${{ github.ref_name }}
GH_TOKEN: ${{ github.token }}
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.ref }}
fetch-depth: 0
- name: Verify the bounded public pointer corpus
run: python3 scripts/verify-repository-share.py "$RELEASE_TAG" "$(git rev-parse HEAD)"
8 changes: 8 additions & 0 deletions docs/knowledge/alignment-status.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"status": "no-approved-mappings",
"approved_record_count": 0,
"carrier_sha256": "f74d895765cf2975b23c6a095b3c09a992865950f9199a7e53f9d2042679db10",
"scope": "scbrown/desire-path repository pendant source",
"basis": "No verified approved artifact or pairs supplied at source review; empty carrier is explicit. This is not a global absence claim.",
"curation_contract": "https://github.com/scbrown/quipu/blob/main/docs/design/cross-graph-alignment.md"
}
6 changes: 6 additions & 0 deletions docs/knowledge/alignments.ttl
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# SSSOM/RDF carrier: explicitly no approved Chaski cross-stack mappings.
# This is an empty mapping graph, not an absent/corrupt input or a claim that
# no mappings exist anywhere. Candidate records require the existing curator
# path before publication as accepted mappings. Dependencies remain dependencies.
@prefix sssom: <https://w3id.org/sssom/> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
113 changes: 113 additions & 0 deletions docs/knowledge/repository-knowledge.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
{
"source_revision": "f742fea0e10d33c211825d775a9d3d696b1a4452",
"reviewed_at": "2026-10-21T00:08:08.544980Z",
"max_age_seconds": 2592000,
"records": [
{
"kind": "idea",
"source": "README.md",
"subject": "http://aegis.gastown.local/ontology/doc/desire-path/README.md",
"summary": "Desire Path records tool-call failures, groups repeated desires and records mappings to real tool names. An alias records a mapping; active interception has separate setup.",
"source_sha256": "c3e9650b3bc7232fbbb698fac3b78b04815877c1c23f40b6f1a597f668c9e6e9",
"type": "Concept"
},
{
"kind": "idea",
"source": "docs/book/src/architecture.md",
"subject": "http://aegis.gastown.local/ontology/doc/desire-path/docs%2Fbook%2Fsrc%2Farchitecture.md",
"summary": "Source plugins normalize raw tool payloads into shared fields; ingestion persists calls through the store interface and query commands expose patterns. The defining Go interfaces remain the authority.",
"source_sha256": "d40d4b4b180ebae18d41e91114f82d0fbaa2cc9c105daf4c2543f7979f255dfa",
"type": "Concept"
},
{
"kind": "interface",
"source": "internal/cli/root.go",
"subject": "http://aegis.gastown.local/ontology/code/desire-path/internal%2Fcli%2Froot.go",
"summary": "The dp command defines its Cobra root, database and JSON output flags, and configuration-driven store selection.",
"source_sha256": "45ed64b779cec7ed56688d1cc2fc5b80d681afc0b7ebd7ef542518be6681305e",
"properties": {
"interfaceKind": "CLI",
"publicName": "dp --db, --json and command tree"
}
},
{
"kind": "interface",
"source": "internal/config/config.go",
"subject": "http://aegis.gastown.local/ontology/code/desire-path/internal%2Fconfig%2Fconfig.go",
"summary": "Configuration uses config.toml with explicit valid keys for database, source, known tools, output and store selection; legacy JSON loading is handled separately.",
"source_sha256": "24123a0173daed8211eaa51c74124ccce6322daad7facbf92e62bdaa690a7fbe",
"properties": {
"interfaceKind": "file-format",
"publicName": "config.toml and legacy JSON configuration"
}
},
{
"kind": "interface",
"source": "internal/source/source.go",
"subject": "http://aegis.gastown.local/ontology/code/desire-path/internal%2Fsource%2Fsource.go",
"summary": "Source plugins expose Name, Description and Extract over raw bytes and normalized Fields; optional Installer methods govern hook setup and installed-state checks.",
"source_sha256": "22e15a3d17a4679e093b8fdfd08e6dd3c1abee980a90a4885e3616add7178023",
"properties": {
"interfaceKind": "library",
"publicName": "internal source.Source and optional source.Installer"
}
},
{
"kind": "interface",
"source": "internal/signpost/signpost.go",
"subject": "http://aegis.gastown.local/ontology/code/desire-path/internal%2Fsignpost%2Fsignpost.go",
"summary": "Optional signposting uses a configured Bobbin search endpoint, scoped result pointers and explicit payload budgets. This integration is separate from local recording.",
"source_sha256": "3e65591d26b0137413b333338ac3c83e5d8383ff9cc36906b2b4a5f1ff9377eb",
"properties": {
"interfaceKind": "REST",
"publicName": "Optional Bobbin search integration"
},
"depends_on": [
"http://aegis.gastown.local/ontology/repo_bobbin"
]
},
{
"kind": "decision",
"source": "AGENTS.md",
"subject": "http://aegis.gastown.local/ontology/doc/desire-path/AGENTS.md",
"summary": "Keep dependencies minimal, use the standard testing package with table-driven cases, and use pure-Go SQLite to preserve builds without CGo.",
"source_sha256": "3104c1737550fdf8878afaf4557de4cbdb4c04db2c6c1cfc5dea3461339756ef",
"type": "DecisionRecord",
"properties": {
"status": "active",
"supersessionStatus": "not-recorded-in-source"
}
},
{
"kind": "start-here",
"source": "README.md",
"subject": "http://aegis.gastown.local/ontology/doc/desire-path/README.md",
"summary": "Start with the temporary-database failed-call example before installing agent hooks or sharing exports.",
"source_sha256": "c3e9650b3bc7232fbbb698fac3b78b04815877c1c23f40b6f1a597f668c9e6e9",
"properties": {
"startHereOrder": 1,
"glossaryTerm": "https://scbrown.github.io/quechua/ns#Tool"
}
},
{
"kind": "start-here",
"source": "docs/book/src/configuration.md",
"subject": "http://aegis.gastown.local/ontology/doc/desire-path/docs%2Fbook%2Fsrc%2Fconfiguration.md",
"summary": "Read configuration and per-command overrides before selecting a persistent database or changing capture defaults.",
"source_sha256": "40f8029b2f5c5a8e7b867071c4d930bf653e899b6d3cdf29a1f30788c499a40f",
"properties": {
"startHereOrder": 2
}
},
{
"kind": "start-here",
"source": "AGENTS.md",
"subject": "http://aegis.gastown.local/ontology/doc/desire-path/AGENTS.md",
"summary": "Use the source development instructions for package layout, source plugins, dependency policy and tests.",
"source_sha256": "3104c1737550fdf8878afaf4557de4cbdb4c04db2c6c1cfc5dea3461339756ef",
"properties": {
"startHereOrder": 3
}
}
]
}
53 changes: 53 additions & 0 deletions docs/knowledge/repository-knowledge.shapes.ttl
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
@prefix a: <http://aegis.gastown.local/ontology/> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix sssom: <https://w3id.org/sssom/> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix prov: <http://www.w3.org/ns/prov#> .

# This profile constrains only explicitly curated repository knowledge. It
# does not turn every imported Concept or CodeModule into a Bobbin record.
a:DesirePathKnowledgeProfile a sh:NodeShape ;
sh:targetSubjectsOf a:knowledgeKind ;
sh:property [ sh:path rdfs:label ; sh:minCount 1 ; ] ;
sh:property [ sh:path rdfs:comment ; sh:minCount 1 ; sh:datatype xsd:string ; ] ;
sh:property [ sh:path a:knowledgeKind ; sh:minCount 1 ;
sh:in ( "idea" "interface" "decision" "start-here" ) ; ] ;
sh:property [ sh:path a:filePath ; sh:minCount 1 ; sh:datatype xsd:string ; ] ;
sh:property [ sh:path a:reviewAfter ; sh:minCount 1 ; sh:maxCount 1 ; sh:datatype xsd:dateTime ; ] ;
sh:property [ sh:path a:glossaryTerm ; sh:nodeKind sh:IRI ; ] ;
sh:property [ sh:path a:sourceHash ; sh:minCount 1 ; sh:maxCount 1 ; sh:pattern "^[0-9a-f]{64}$" ; ] ;
# maxAge is seconds since the explicit source review, not an eviction rule.
sh:property [ sh:path a:maxAge ; sh:minCount 1 ; sh:maxCount 1 ; sh:datatype xsd:integer ; sh:minExclusive 0 ; ] ;
sh:property [ sh:path prov:wasDerivedFrom ; sh:minCount 1 ; sh:nodeKind sh:IRI ; ] .

a:DesirePathInterfaceProfile a sh:NodeShape ;
sh:targetSubjectsOf a:interfaceKind ;
sh:property [ sh:path rdfs:label ; sh:minCount 1 ; ] ;
sh:property [ sh:path a:interfaceKind ; sh:minCount 1 ; sh:maxCount 1 ;
sh:in ( "CLI" "MCP" "REST" "config" "file-format" "library" ) ; ] ;
sh:property [ sh:path a:publicName ; sh:minCount 1 ; sh:datatype xsd:string ; ] ;
sh:property [ sh:path a:depends_on ; sh:nodeKind sh:IRI ; ] .

a:DesirePathDecisionProfile a sh:NodeShape ;
sh:targetSubjectsOf a:supersessionStatus ;
sh:property [ sh:path rdfs:label ; sh:minCount 1 ; ] ;
sh:property [ sh:path a:status ; sh:minCount 1 ; sh:maxCount 1 ; sh:in ( "active" "superseded" "proposed" ) ; ] ;
sh:property [ sh:path a:supersessionStatus ; sh:minCount 1 ; sh:maxCount 1 ;
sh:in ( "not-recorded-in-source" "recorded" ) ; ] .

# Existing SSSOM/RDF is a record, not a second identity-assertion format. The
# native align decide/apply path remains the only way to derive identity knots.
a:DesirePathMappingRecordProfile a sh:NodeShape ;
sh:targetSubjectsOf sssom:subject_id ;
sh:property [ sh:path rdfs:label ; sh:minCount 1 ; ] ;
sh:property [ sh:path sssom:subject_id ; sh:minCount 1 ; sh:maxCount 1 ; sh:nodeKind sh:IRI ; ] ;
sh:property [ sh:path sssom:object_id ; sh:minCount 1 ; sh:maxCount 1 ; sh:nodeKind sh:IRI ; ] ;
sh:property [ sh:path sssom:predicate_id ; sh:minCount 1 ; sh:maxCount 1 ; sh:nodeKind sh:IRI ; ] ;
sh:property [ sh:path sssom:mapping_justification ; sh:minCount 1 ; sh:maxCount 1 ; sh:nodeKind sh:IRI ; ] .

a:DesirePathNoHandAuthoredIdentity a sh:NodeShape ;
sh:targetSubjectsOf owl:sameAs ;
sh:property [ sh:path rdfs:label ; sh:minCount 1 ; ] ;
sh:property [ sh:path owl:sameAs ; sh:maxCount 0 ; ] .
32 changes: 32 additions & 0 deletions docs/knowledge/stored-queries.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
[
{
"name": "repository_ideas",
"description": "Repository-owned repository ideas",
"template": "PREFIX a: <http://aegis.gastown.local/ontology/> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> SELECT * WHERE { ?s a a:Concept; rdfs:comment ?summary . FILTER(STRSTARTS(STR(?s), \"http://aegis.gastown.local/ontology/doc/desire-path/\") || STRSTARTS(STR(?s), \"http://aegis.gastown.local/ontology/code/desire-path/\")) } ORDER BY ?s LIMIT 100",
"params": []
},
{
"name": "repository_interfaces",
"description": "Repository-owned repository interfaces",
"template": "PREFIX a: <http://aegis.gastown.local/ontology/> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> SELECT * WHERE { ?s a:interfaceKind ?kind; a:publicName ?name . FILTER(STRSTARTS(STR(?s), \"http://aegis.gastown.local/ontology/doc/desire-path/\") || STRSTARTS(STR(?s), \"http://aegis.gastown.local/ontology/code/desire-path/\")) } ORDER BY ?s LIMIT 100",
"params": []
},
{
"name": "repository_decisions",
"description": "Repository-owned repository decisions",
"template": "PREFIX a: <http://aegis.gastown.local/ontology/> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> SELECT * WHERE { ?s a a:DecisionRecord; a:status ?status . OPTIONAL { ?s <http://purl.org/dc/terms/isReplacedBy> ?successor } FILTER(STRSTARTS(STR(?s), \"http://aegis.gastown.local/ontology/doc/desire-path/\") || STRSTARTS(STR(?s), \"http://aegis.gastown.local/ontology/code/desire-path/\")) } ORDER BY ?s LIMIT 100",
"params": []
},
{
"name": "repository_start_here",
"description": "Repository-owned repository start here",
"template": "PREFIX a: <http://aegis.gastown.local/ontology/> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> SELECT * WHERE { ?s a:startHereOrder ?order . FILTER(STRSTARTS(STR(?s), \"http://aegis.gastown.local/ontology/doc/desire-path/\") || STRSTARTS(STR(?s), \"http://aegis.gastown.local/ontology/code/desire-path/\")) } ORDER BY ?s LIMIT 100",
"params": []
},
{
"name": "repository_freshness",
"description": "Repository-owned repository freshness",
"template": "PREFIX a: <http://aegis.gastown.local/ontology/> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> SELECT * WHERE { ?s a:reviewAfter ?reviewAfter; a:maxAge ?maxAgeSeconds . FILTER(STRSTARTS(STR(?s), \"http://aegis.gastown.local/ontology/doc/desire-path/\") || STRSTARTS(STR(?s), \"http://aegis.gastown.local/ontology/code/desire-path/\")) } ORDER BY ?s LIMIT 100",
"params": []
}
]
76 changes: 76 additions & 0 deletions queries/repository-share-desire-path.rq
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
PREFIX aegis: <http://aegis.gastown.local/ontology/>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX prov: <http://www.w3.org/ns/prov#>
PREFIX dct: <http://purl.org/dc/terms/>
PREFIX sssom: <https://w3id.org/sssom/>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

# Public repository knowledge only. Bobbin publishes its replaceable snapshot
# into ROOT, so graph/group selectors cannot see it. Keep this predicate list
# aligned with Bobbin's generate_chunk_turtle output: selecting every outgoing
# edge also pulls private operational literals into a public release artifact.
CONSTRUCT { ?s ?p ?o }
WHERE {
{
?s ?p ?o .
FILTER(
STRSTARTS(STR(?s), "http://aegis.gastown.local/ontology/code/desire-path/") ||
STRSTARTS(STR(?s), "http://aegis.gastown.local/ontology/chunk/desire-path/") ||
STRSTARTS(STR(?s), "http://aegis.gastown.local/ontology/doc/desire-path/")
)
VALUES ?p {
rdf:type rdfs:label
aegis:filePath aegis:repo aegis:language
aegis:inDocument aegis:chunkOrder aegis:nextChunk aegis:mentions
aegis:name aegis:definedIn aegis:symbolKind
aegis:heading aegis:headingDepth
rdfs:comment rdfs:seeAlso prov:wasDerivedFrom dct:modified dct:isReplacedBy
aegis:knowledgeKind aegis:interfaceKind aegis:publicName aegis:status
aegis:supersessionStatus aegis:startHereOrder aegis:glossaryTerm
aegis:reviewAfter aegis:maxAge aegis:depends_on aegis:sourceHash
}
# Bobbin emits weak mention names as strings. Quipu may additionally
# resolve those names to IRIs under the same predicate in its local store;
# those derived edges do not satisfy the shipped string-valued shape.
FILTER(?p != aegis:mentions || isLiteral(?o))
}
UNION
{
?s ?p ?o .
{ ?s a sssom:MappingSet } UNION { ?s a owl:Axiom }
VALUES ?p {
rdf:type rdfs:label prov:wasDerivedFrom
sssom:mappings sssom:subject_id sssom:object_id sssom:predicate_id
sssom:subject_label sssom:object_label sssom:mapping_justification
sssom:predicate_modifier sssom:confidence sssom:author_id
}
}
UNION
{
VALUES ?s {
aegis:repo_desire-path
aegis:repo-embedded-knowledge-databases-directive-2026-09-03
}
?s ?p ?o .
}
# Versioned crew memory is internal source, including references attached to
# otherwise public context nodes. Internal backups use a separate explicit scope.
FILTER(!STRSTARTS(STR(?s), "urn:quipu:memory:"))
FILTER(!STRSTARTS(STR(?p), "https://quipu.dev/memory#"))
FILTER(!STRSTARTS(STR(?o), "urn:quipu:memory:"))
# Work tracking identifiers are not public repository knowledge. Filter
# both endpoints and literal mentions instead of renaming entity identity.
FILTER(!REGEX(STR(?s), "(^|[^A-Za-z0-9_])aegis-[A-Za-z0-9]"))
FILTER(!REGEX(STR(?o), "(^|[^A-Za-z0-9_])aegis-[A-Za-z0-9]"))
# Exclude the whole node when a required label contains an internal ID.
# Dropping only its label would leave a typed, SHACL-invalid fragment.
MINUS {
?s ?internalPredicate ?internalValue .
FILTER(REGEX(STR(?internalValue), "(^|[^A-Za-z0-9_])aegis-[A-Za-z0-9]"))
}
MINUS {
?o ?targetPredicate ?targetValue .
FILTER(REGEX(STR(?targetValue), "(^|[^A-Za-z0-9_])aegis-[A-Za-z0-9]"))
}
}
Loading
Loading