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
5 changes: 4 additions & 1 deletion .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ jobs:
# Zola fails the build on broken internal links.
run: zola build

- name: Verify editor, demo outputs and publication downloads
run: python3 -m unittest discover -s scripts -p 'test_*.py' -v

- name: Verify the build produced pages
run: |
pages=$(find public -name '*.html' | wc -l)
Expand All @@ -64,4 +67,4 @@ jobs:
uses: actions/checkout@v6

- name: Verify advertised downloads exist on the public channel
run: python3 scripts/check-release-links.py
run: python3 scripts/check-release-links.py
2 changes: 1 addition & 1 deletion config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ include_content = true

[extra]
version = "1.21.16"
release_version = "1.21.18"
release_version = "1.21.19"

navbar_items = [
{ code = "en", nav_items = [
Expand Down
16 changes: 13 additions & 3 deletions content/how-tos/synonym-search.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ date = 2026-10-11
[taxonomies]
categories = ["How-tos"]
tags = ["editor", "knowledge-graph", "search"]
[extra]
social_image = "/demos/synonym-search/poster.jpg"
+++

Your project brief says **risk**. Later, you search for **concern**. Terraphim connects the two so a change of wording does not hide the decisions you need.
Expand Down Expand Up @@ -32,12 +34,12 @@ Download the graph and the clean text. This explicitly shares the document's aut
Use the graph downloaded from that editing session:

```sh
terraphim-grep concern --thesaurus knowledge-graph.json --paths corpus -C 2 --json
terraphim-grep concern --thesaurus knowledge-graph.json --paths corpus -C 2 --search-only --json
```

The actual result contains three risk passages and their related decisions, with file and line locations. No generated answer is requested.

Add `--answer` to the same command for synthesis:
Replace `--search-only` with `--answer` for synthesis:

```sh
terraphim-grep concern --thesaurus knowledge-graph.json --paths corpus -C 2 --json --answer
Expand All @@ -54,9 +56,17 @@ Editing and local search use your local data. Optional synthesis sends the retri
- [Saved Markdown with alternatives](/demos/synonym-search/annotated.md)
- [Actual result without synthesis](/demos/synonym-search/without-synthesis.json)
- [Actual result with synthesis](/demos/synonym-search/with-synthesis.json)
- [Download the complete example ZIP](/demos/synonym-search/synonym-search-example.zip), including a step-by-step README
- [English subtitles (SRT)](/demos/synonym-search/captions.srt)

The community garden brief is authored public sample input. The alternatives, downloaded graph, retrieved passages and generated answer are actual outputs. The command-line section displays those JSON fields in a readable presentation; it is not a separate Terraphim interface. The voice is synthetic British English (Emma). Setup is omitted, and the recorded interaction runs at its original speed. [Recording details and file identities](/demos/synonym-search/manifest.json).

This is a preview of the new export and search flow. It uses the [editor graph-sharing candidate](https://git.terraphim.cloud/terraphim/terraphim-editor/pulls/131) and the [grep synonym/synthesis candidate](https://git.terraphim.cloud/terraphim/terraphim-clients/pulls/385); older installed binaries may differ. A fresh synthesis run may produce different wording.
## Reproduce it with released builds

The recording preserves its original candidate-build identities. The same flow was separately verified on 12 October 2026 using the published [Editor v0.1.0-rc.1 prerelease](https://github.com/terraphim/terraphim-editor/releases/tag/v0.1.0-rc.1) and [terraphim-grep v1.21.19](https://github.com/terraphim/terraphim-clients/releases/tag/v1.21.19). The editor is still an RC; the video is not a claim that every host or feature is fully qualified.

Download the example ZIP, extract it, and follow `README.md`. It uses the same graph and clean brief as the recording. Verify `terraphim-grep --version` before running the two commands above. The release includes macOS and Linux builds; Windows is not claimed by this example.

Inspect the separate released-binary outputs: [before sharing the synonym graph](/demos/synonym-search/released-before-sharing.json), [without synthesis](/demos/synonym-search/released-without-synthesis.json), and [with synthesis](/demos/synonym-search/released-with-synthesis.json). The baseline used the editor's default role, which lacks the authored synonym: zero passages became three when the exported graph was supplied. The paired modes retrieved the same passages. [Released-build identities, commands and file checksums](/demos/synonym-search/reproduction.json) distinguish this verification from the original recording. A fresh synthesis run may produce different wording.

[Earlier browser and Zed host walkthroughs](/how-tos/knowledge-work-editor/) retain their own recorded versions and limitations. This focused story does not qualify all 41 source-video requirements. The Zed fork remains separate.
80 changes: 80 additions & 0 deletions scripts/test_synonym_publication.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
"""Exercise the built page and the downloadable reproduction kit."""
import hashlib
from html.parser import HTMLParser
import json
from pathlib import Path
import subprocess
import tempfile
import unittest
import zipfile

ROOT = Path(__file__).resolve().parents[1]
MEDIA = ROOT / "static/demos/synonym-search"


class HeadParser(HTMLParser):
def __init__(self):
super().__init__()
self.meta = {}
self.canonicals = []

def handle_starttag(self, tag, attrs):
attrs = dict(attrs)
if tag == "meta":
self.meta[attrs.get("property", attrs.get("name"))] = attrs.get("content")
if tag == "link" and attrs.get("rel") == "canonical":
self.canonicals.append(attrs["href"])


class PublicationTests(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.output = tempfile.TemporaryDirectory()
built = Path(cls.output.name) / "site"
subprocess.run(["zola", "build", "--output-dir", str(built)], cwd=ROOT, check=True, text=True)
cls.html = (built / "how-tos/synonym-search/index.html").read_text()

@classmethod
def tearDownClass(cls):
cls.output.cleanup()

def test_production_metadata_and_privacy_wording(self):
head = HeadParser()
head.feed(self.html)
url = "https://terraphim.ai/how-tos/synonym-search/"
self.assertEqual(head.canonicals, [url])
self.assertEqual(head.meta["og:url"], url)
self.assertEqual(head.meta["og:title"], "Different words. The same idea.")
self.assertEqual(head.meta["og:image"], "https://terraphim.ai/demos/synonym-search/poster.jpg")
self.assertEqual(head.meta["twitter:card"], "summary_large_image")
self.assertNotIn("All data processed locally", self.html)
self.assertIn("Optional synthesis uses your configured model provider", self.html)
self.assertNotIn("editor graph-sharing candidate", self.html)
self.assertIn("v0.1.0-rc.1", self.html)
self.assertIn("v1.21.19", self.html)

def test_released_evidence_and_bundle_match_actual_files(self):
receipt = json.loads((MEDIA / "reproduction.json").read_text())
self.assertEqual(receipt["grepVersion"], "1.21.19")
self.assertEqual(receipt["editorVersion"], "0.1.0-rc.1")
before = json.loads((MEDIA / "released-before-sharing.json").read_text())
off = json.loads((MEDIA / "released-without-synthesis.json").read_text())
on = json.loads((MEDIA / "released-with-synthesis.json").read_text())
self.assertEqual(before["chunks"], [])
self.assertEqual(off["chunks"], on["chunks"])
self.assertEqual(len(off["chunks"]), 3)
self.assertIsNone(off["answer"])
self.assertTrue(on["answer"]["answer"])
self.assertEqual(len(on["answer"]["citations"]), 3)
with zipfile.ZipFile(MEDIA / "synonym-search-example.zip") as bundle:
self.assertEqual(set(bundle.namelist()), set(receipt["bundleFiles"]))
for name in receipt["bundleFiles"]:
self.assertEqual(bundle.read(name), (MEDIA / name).read_bytes())
for item in receipt["files"]:
self.assertEqual(hashlib.sha256((MEDIA / item["file"]).read_bytes()).hexdigest(), item["sha256"])
for name in ["reproduction.json", "synonym-search-example.zip", "captions.srt"]:
self.assertIn("/demos/synonym-search/" + name, self.html)


if __name__ == "__main__":
unittest.main()
70 changes: 70 additions & 0 deletions static/demos/synonym-search/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Different words. The same idea.

Source: https://terraphim.ai/how-tos/synonym-search/

This kit contains the actual graph and clean brief exported in the 80-second
recording, and separate evidence from released builds. The brief is public sample
input. The graph and search results are actual outputs.

## Reproduce local retrieval

1. Download terraphim-grep v1.21.19 for your macOS or Linux architecture:
https://github.com/terraphim/terraphim-clients/releases/tag/v1.21.19
Check the archive against that release's SHA256SUMS, then extract it and put
terraphim-grep on PATH. No Windows build is claimed by this kit.
2. In this extracted directory, run:

```sh
terraphim-grep --version
mkdir -p corpus
cp project-brief.md corpus/project-brief.md
terraphim-grep concern --thesaurus baseline-role.json --paths corpus -C 2 --search-only --json
terraphim-grep concern --thesaurus knowledge-graph.json --paths corpus -C 2 --search-only --json
```

The first search uses the editor's default role, which lacks this authored
synonym. It returns zero passages. The exported graph connects Risk and Concern;
the second search returns three Risk passages even though Concern is absent
from the clean brief. `released-before-sharing.json` and
`released-without-synthesis.json` contain those actual outputs.

## Compare optional synthesis

Configure a model provider using the client release documentation. Then run:

```sh
terraphim-grep concern --thesaurus knowledge-graph.json --paths corpus -C 2 --json --answer
```

Optional synthesis sends the retrieved passages to your configured model
provider and may incur provider charges. The released verification used
DeepSeek (deepseek-v4-flash-0731). No credentials are included. Generated wording
can vary. Compare the chunks and citations, not an exact answer string:
`released-with-synthesis.json` has the same three chunks as the search-only run.
Decisions in the source do not prove that the actions have been completed.

## Recreate the editor export

Use https://terraphim.ai/editor/ or the published v0.1.0-rc.1 editor prerelease:
https://github.com/terraphim/terraphim-editor/releases/tag/v0.1.0-rc.1

Open the brief, add Concern as an alternative to Risk, swap between them, and
retain Risk in the final text. Choose Knowledge graph from the Markdown export
menu. The definition is `synonyms:: Risk, Concern`. Export the graph and clean
text, then use your exported filenames in the commands above. This explicitly
shares document synonyms; it does not silently update the active role.
`annotated.md` preserves the alternatives for reopening.

## Provenance

- `manifest.json`, `without-synthesis.json`, and `with-synthesis.json` describe
the original candidate-build recording. They have not been relabelled as
released-binary evidence.
- `reproduction.json` and the `released-*.json` files describe the separate
v0.1.0-rc.1 / v1.21.19 verification on 12 October 2026.
- `captions.vtt`, `captions.srt`, and `transcript.txt` accompany the original video.
The British female narration is synthetic (Emma, Kokoro).
- Video and poster are available on the source page; they are not in this ZIP.

This focused flow does not qualify all 41 requirements or every extension.
The Zed fork remains separate.
91 changes: 91 additions & 0 deletions static/demos/synonym-search/baseline-role.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
{
"name": "terraphim-editor-default",
"data": {
"alternative": {
"id": 100,
"nterm": "alternatives"
},
"alternatives": {
"id": 100,
"nterm": "alternatives"
},
"caf\u00e9": {
"id": 4,
"nterm": "caf\u00e9"
},
"choice": {
"id": 1,
"nterm": "decision"
},
"coffee shop": {
"id": 4,
"nterm": "caf\u00e9"
},
"coffeehouse": {
"id": 4,
"nterm": "caf\u00e9"
},
"decision": {
"id": 1,
"nterm": "decision"
},
"employ": {
"id": 8,
"nterm": "use"
},
"eraser": {
"id": 2,
"nterm": "eraser"
},
"honour": {
"id": 5,
"nterm": "honour"
},
"judgment": {
"id": 1,
"nterm": "decision"
},
"large language model": {
"id": 3,
"nterm": "llm",
"display_value": "LLM"
},
"llm": {
"id": 3,
"nterm": "llm",
"display_value": "LLM"
},
"option": {
"id": 1,
"nterm": "decision"
},
"options set": {
"id": 100,
"nterm": "alternatives"
},
"paperclip": {
"id": 7,
"nterm": "paperclip"
},
"privilege": {
"id": 5,
"nterm": "honour"
},
"rubber": {
"id": 2,
"nterm": "eraser"
},
"use": {
"id": 8,
"nterm": "use"
},
"utilise": {
"id": 8,
"nterm": "use"
},
"variants": {
"id": 100,
"nterm": "alternatives"
}
}
}
75 changes: 75 additions & 0 deletions static/demos/synonym-search/captions.srt
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
1
00:00:00,250 --> 00:00:04,443
When people use different words for the same idea, useful decisions can

2
00:00:04,443 --> 00:00:06,190
become surprisingly hard to find.

3
00:00:07,250 --> 00:00:10,852
Here is our community garden brief. It records three risks, and the

4
00:00:10,852 --> 00:00:13,553
decisions we have made to deal with each one.

5
00:00:15,250 --> 00:00:18,996
I add concern as an alternative to risk. Now I can swap

6
00:00:18,996 --> 00:00:22,742
between the two words, choosing the wording that fits without losing the

7
00:00:22,742 --> 00:00:23,366
other option.

8
00:00:26,250 --> 00:00:30,840
The editor connects those alternatives to one idea in the knowledge graph.

9
00:00:30,840 --> 00:00:35,047
Here is the actual synonym definition: risk and concern belong together.

10
00:00:37,250 --> 00:00:41,059
I download that graph and the finished text. Notice that I leave

11
00:00:41,059 --> 00:00:43,915
risk in the document. The word concern is absent.

12
00:00:46,250 --> 00:00:50,497
Now I search for concern using the graph I just downloaded. It

13
00:00:50,497 --> 00:00:54,744
finds all three risk passages, including the related decisions, even though the

14
00:00:54,744 --> 00:00:55,805
wording is different.

15
00:00:58,250 --> 00:01:02,632
Without synthesis, I get the original passages and their locations. Adding the

16
00:01:02,632 --> 00:01:07,014
answer flag gives me a summary from the same evidence, with source

17
00:01:07,014 --> 00:01:07,379
references.

18
00:01:10,250 --> 00:01:14,735
The summary keeps decisions distinct from completed actions. From choosing a word

19
00:01:14,735 --> 00:01:19,219
to finding a decision, the same knowledge graph keeps the meaning connected.
Loading
Loading