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
3 changes: 3 additions & 0 deletions .github/workflows/idric-core.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ jobs:
- name: Exercise filesystem category and hot views
run: sh bin/ci_browser_foundation.grease exercise-filesystem-views

- name: Exercise saved-tab text question mock
run: sh bin/ci_browser_foundation.grease exercise-tab-qa

- name: Install system dependencies through Grease
run: sh bin/ci_browser_foundation.grease install-dependencies

Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ The browser core owns resource, tab, event, and task identity; sleeping and waki
- `docs/filesystem-views.md` — category links, `_active`, and the requested `hot/` presentation set
- `docs/storage-model.md` — identity levels and canonical, proposed, and derived state
- `docs/developer-workbench.md` — fixture and memory-pressure harness
- `docs/vector-index.md` — readable multi-model vector views and rebuildable Float32 query caches
- `docs/tab-qa-mock.md` — console questions over saved reading pages with replaceable processing stages
- `experiments/category-hyperplanes/README.md` — disposable embedding and explicit affine-separator probe
- `experiments/embedding-models/README.md` — pinned tiny ONNX models and an end-to-end filesystem-index comparison

Expand Down
30 changes: 30 additions & 0 deletions bin/ask_saved_pages.grease
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/bin/sh
set -eu

repository_root=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)
export IB_TAB_QA_REPOSITORY_ROOT="$repository_root"
. "$repository_root/lib/tab_qa.grease"

case "${1:-}" in
--index)
test "$#" -eq 1 || exit 2
ib_tab_qa_build_index
;;
--inspect)
test "$#" -eq 1 || exit 2
ib_tab_qa_inspect
;;
--help)
printf '%s\n' \
"usage: $0 [--index|--inspect|QUESTION]" \
'With no argument, read one question from the console.'
;;
'')
printf 'question> ' >&2
IFS= read -r question || exit 1
ib_tab_qa_answer "$question"
;;
*)
ib_tab_qa_answer "$*"
;;
esac
16 changes: 15 additions & 1 deletion bin/ci_browser_foundation.grease
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,19 @@ exercise_filesystem_views() {
sh tests/test_filesystem_views.grease
}

exercise_tab_qa() {
cd "$repository_root"
sh -n lib/tab_qa.grease
sh -n bin/ask_saved_pages.grease
sh -n bin/mock_tab_model.grease
sh -n bin/mock_tab_qa_reducer.grease
sh -n tests/test_mock_tab_model.grease
sh -n tests/test_tab_qa_pipeline.grease
make -C native/vector-index
sh tests/test_mock_tab_model.grease
sh tests/test_tab_qa_pipeline.grease
}

exercise_workbench() {
cd "$repository_root"
sh -n tests/test_real_world_url_fixture.grease
Expand Down Expand Up @@ -199,11 +212,12 @@ case "${1:-}" in
exercise-workbench) exercise_workbench ;;
exercise-file-store) exercise_file_store ;;
exercise-filesystem-views) exercise_filesystem_views ;;
exercise-tab-qa) exercise_tab_qa ;;
exercise-scientific-media) exercise_scientific_media ;;
exercise-live-arxiv) exercise_live_arxiv ;;
exercise-live-arxiv-prepaint) exercise_live_arxiv_prepaint ;;
*)
printf 'usage: %s {install-dependencies|build-idric|verify-pdf-harvester|exercise-information|exercise-core|exercise-workbench|exercise-file-store|exercise-filesystem-views|exercise-scientific-media|exercise-live-arxiv|exercise-live-arxiv-prepaint}\n' "$0" >&2
printf 'usage: %s {install-dependencies|build-idric|verify-pdf-harvester|exercise-information|exercise-core|exercise-workbench|exercise-file-store|exercise-filesystem-views|exercise-tab-qa|exercise-scientific-media|exercise-live-arxiv|exercise-live-arxiv-prepaint}\n' "$0" >&2
exit 2
;;
esac
116 changes: 116 additions & 0 deletions bin/mock_tab_model.grease
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
#!/bin/sh
set -eu

model_name=mock-token-i8-v1
dimensions=32

inspect_model() {
printf '%s\n' \
"model=$model_name" \
'available=True' \
'model-kind=deterministic-token-test-double' \
'llm=False' \
'quantization=int8-counts' \
"dimensions=$dimensions" \
'tasks=embedding,extractive-answer'
}

embed_text() {
awk -v dimensions="$dimensions" '
function token_slot(token, alphabet, character, hash, index_in_alphabet, position) {
alphabet = "abcdefghijklmnopqrstuvwxyz0123456789"
hash = 0
for (position = 1; position <= length(token); position++) {
character = substr(token, position, 1)
index_in_alphabet = index(alphabet, character)
hash = (hash * 37 + index_in_alphabet) % dimensions
}
return hash + 1
}
{
text = tolower($0)
gsub(/[^[:alnum:]]+/, " ", text)
token_count = split(text, tokens, / +/)
for (token_index = 1; token_index <= token_count; token_index++) {
token = tokens[token_index]
if (length(token) < 2)
continue
slot = token_slot(token)
if (values[slot] < 127)
values[slot]++
}
}
END {
for (slot = 1; slot <= dimensions; slot++)
printf "%s%d", slot == 1 ? "" : " ", values[slot] + 0
printf "\n"
}
'
}

answer_from_document() {
question=$1
document=$2
test -s "$document" || {
printf 'mock tab model: source document is empty: %s\n' "$document" >&2
return 1
}

awk -v question="$question" '
BEGIN {
normalized_question = tolower(question)
gsub(/[^[:alnum:]]+/, " ", normalized_question)
question_count = split(normalized_question, question_tokens, / +/)
for (question_index = 1; question_index <= question_count; question_index++)
if (length(question_tokens[question_index]) >= 2)
wanted[question_tokens[question_index]] = 1
}
NF {
if (first_line == "")
first_line = $0
normalized_line = tolower($0)
gsub(/[^[:alnum:]]+/, " ", normalized_line)
line_count = split(normalized_line, line_tokens, / +/)
score = 0
for (line_index = 1; line_index <= line_count; line_index++) {
token = line_tokens[line_index]
if (token in wanted && seen_on_line[token] != NR) {
score++
seen_on_line[token] = NR
}
}
if (best_line == "" || score > best_score) {
best_line = $0
best_score = score
}
}
END {
if (best_line != "")
print best_line
else if (first_line != "")
print first_line
}
' "$document"
}

case "${1:-}" in
inspect)
test "$#" -eq 1 || exit 2
inspect_model
;;
embed)
test "$#" -eq 1 || exit 2
embed_text
;;
answer)
test "$#" -eq 3 || {
printf 'usage: %s answer QUESTION DOCUMENT\n' "$0" >&2
exit 2
}
answer_from_document "$2" "$3"
;;
*)
printf 'usage: %s {inspect|embed|answer QUESTION DOCUMENT}\n' "$0" >&2
exit 2
;;
esac
68 changes: 68 additions & 0 deletions bin/mock_tab_qa_reducer.grease
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#!/bin/sh
set -eu

reducer_name=mock-single-member-weighted-reducer-v1

inspect_reducer() {
printf '%s\n' \
"reducer=$reducer_name" \
'available=True' \
'ensemble=single-member-test-double' \
'member-count=1' \
'xgboost=False'
}

reduce_candidate() {
retrieval_score=$1
source_document=$2
report=${IB_TAB_QA_REDUCER_REPORT:?IB_TAB_QA_REDUCER_REPORT must name the reducer report}
candidate=$(sed -n '1p')

test -n "$candidate" || {
printf 'mock reducer: model candidate is empty\n' >&2
return 1
}
test -s "$source_document" || {
printf 'mock reducer: source document is unavailable\n' >&2
return 1
}
awk -v value="$retrieval_score" 'BEGIN {
numeric = value ~ /^[-+]?([0-9]+([.][0-9]*)?|[.][0-9]+)([eE][-+]?[0-9]+)?$/
exit !numeric
}' || {
printf 'mock reducer: retrieval score is not numeric\n' >&2
return 1
}

printf '%s\n' \
"reducer=$reducer_name" \
'ensemble-stage-ran=True' \
'member-count=1' \
'checks-run=3' \
'candidate-nonempty=True' \
'source-readable=True' \
'score-numeric=True' \
"aggregate-score=$retrieval_score" > "$report"

# This one-member reducer deliberately preserves the model text. A later
# voting, bagging, rank-aggregation, or XGBoost adapter occupies this stage.
printf '%s\n' "$candidate"
}

case "${1:-}" in
inspect)
test "$#" -eq 1 || exit 2
inspect_reducer
;;
reduce)
test "$#" -eq 3 || {
printf 'usage: %s reduce RETRIEVAL_SCORE SOURCE_DOCUMENT < candidate.txt\n' "$0" >&2
exit 2
}
reduce_candidate "$2" "$3"
;;
*)
printf 'usage: %s {inspect|reduce RETRIEVAL_SCORE SOURCE_DOCUMENT}\n' "$0" >&2
exit 2
;;
esac
84 changes: 84 additions & 0 deletions docs/tab-qa-mock.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Saved-tab question-and-answer mock

This is the first executable vertical slice of the ChatGPT-like text frontend.
It is a console prompt, not the eventual phone UI, and it answers only from
plain-text documents deliberately present below `~/reading`.

The stages are explicit:

1. `mock-token-i8-v1` tokenizes text into a 32-component, bounded 8-bit-count
test vector and selects one source line as an extractive answer.
2. `ib-vector-index` stores one exact cosine index in the existing model-view
tree. Authoritative fixed-width text and its rebuildable Float32 cache are
two query paths over that index. Each query can record whether its dot
products used a GPU; the current C backend records `False` and `compute=cpu`.
3. `mock-single-member-weighted-reducer-v1` is a one-member ensemble test
double. It runs three validations, records an aggregate score, and preserves
the candidate. This is the replaceable slot for voting, bagging, rank
aggregation, XGBoost, or another reducer; it does not claim to run XGBoost.
4. `ib_tab_qa_null_render` is an identity post-processing step before the text
is returned.

The bundled model is intentionally not described as an LLM. It is a tiny,
queryable deterministic mock that exercises token, embedding, retrieval,
model-output, reducer, and renderer boundaries without a model download.
`IB_TAB_QA_MODEL_COMMAND` can name a later adapter implementing `inspect`,
`embed`, and `answer`. `IB_TAB_QA_REDUCER_COMMAND` can replace the one-member
reducer. The two pinned Hugging Face embedding manifests remain available for
real model views; this mock writes `model-adapter.txt`, never a misleading
`embedding-model.txt` manifest. A model name is bound to one exact adapter
record, including the adapter command's SHA-256, so changed adapter code cannot
silently reuse old vectors. An adapter with external model or vocabulary files
must report their immutable hashes from `inspect` as part of the same record.

## Filesystem boundaries

Saved source text stays below `${IB_READING_DIR:-~/reading}`. The rebuildable
index defaults to:

```text
${XDG_DATA_HOME:-~/.local/share}/ib/views/
organizing-the-information/vector-spaces/mock-token-i8-v1/reading/
```

Successful questions are appended as one directory per exchange below the
separate requested folder:

```text
~/questions and answers about tabs that the user has visited/
<UTC-time>-<process>/
question.txt
model-candidate.txt
reduced-answer.txt
answer.txt
source.tsv
vector-query.tsv
vector-format.txt
reducer.tsv
indexing.tsv
model.tsv
reducer-model.tsv
reading-source.tsv
pipeline.tsv
```

The exchange preserves the raw model candidate, reduction evidence, selected
source identity and content hash, upstream reading-source record, exact vector
generation, adapter and reducer command hashes, vector execution report, and
final response separately. It snapshots the selected document for processing
and fails closed if those bytes differ from the indexed corpus record. The
snapshot is temporary: canonical reading text is neither moved nor duplicated
into the Q&A store. The command rejects a Q&A root equal to or nested with the
reading root.

## Run the mock

```text
make -C native/vector-index
sh bin/ask_saved_pages.grease --index
sh bin/ask_saved_pages.grease "What do feed-forward networks do to input space?"
```

Running the last command without a question displays `question>` and reads one
line from the console. The index is reused until `--index` is run again; corpus
change detection is deliberately left for the next slice.
6 changes: 6 additions & 0 deletions docs/vector-index.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ document-id<TAB>0.8125

`query` memory-maps the Float32 cache. `query-text` performs the same exact scan by parsing the readable file and works with the cache removed. `column` uses the fixed-width layout to print one coordinate across every ID. `compile-cache` atomically recreates the Float32 file from text. A later exact or approximate program can occupy the same process boundary without changing canonical browser state or callers that stream rows and queries.

When `IB_VECTOR_QUERY_REPORT` names a file, either query command also writes a
small execution report containing the compute device, storage path, metric,
dimensions, and number of row dot products. The current portable C scan reports
`dot-product-used-gpu=False`; a future accelerated backend must report its own
execution rather than letting callers infer it.

## Files

One model-specific view lives below the derived view root:
Expand Down
Loading
Loading