docs(6209): forty test files — design cascade and stylesheet, embeddings, family canon, forge, backup round trips, inception, placement, platforms, moments, rule move and verification, search scope, facets
Module and test docstrings state what is pinned without the record number or step that introduced it. Incident accounts become the failure shape in the present tense: the pipefail head, the code_shapes import, the export order, the facet dialects, the cross-kind repeat, the write-once kind. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
"""The auto-inject query carries the conversation beside a thin prompt (#4364).
|
"""The auto-inject query carries the conversation beside a thin prompt.
|
||||||
|
|
||||||
The notes arm used to retrieve against the operator's typed words alone, and a
|
The operator's typed words alone are a poor query: a mid-session follow-up —
|
||||||
mid-session follow-up — "yes do that", "now fix the filter" — names nothing a
|
"yes do that", "now fix the filter" — names nothing a record can match. The
|
||||||
record can match. The hook now reads the tail of the last assistant reply out
|
hook reads the tail of the last assistant reply out
|
||||||
of the transcript and sends it as `ctx`; the server appends it to a SHORT
|
of the transcript and sends it as `ctx`; the server appends it to a SHORT
|
||||||
prompt only. Two halves, pinned separately: what the server builds, and what
|
prompt only. Two halves, pinned separately: what the server builds, and what
|
||||||
the hook extracts.
|
the hook extracts.
|
||||||
@@ -103,10 +103,10 @@ def test_no_transcript_is_silence_not_failure(tmp_path):
|
|||||||
assert recent(tmp_path, []) == ""
|
assert recent(tmp_path, []) == ""
|
||||||
|
|
||||||
|
|
||||||
# --- what a menu line carries (#4364) ----------------------------------------
|
# --- what a menu line carries -----------------------------------------------
|
||||||
#
|
#
|
||||||
# The name, the kind and System, and the WHOLE matched passage — once. A repeat
|
# The name, the kind and System, and the WHOLE matched passage — once. A repeat
|
||||||
# is a pointer. These pin the shape against the three ways it had gone wrong:
|
# is a pointer. These pin the shape against the three ways it goes wrong:
|
||||||
# a trigger-composed title rendered as the line (1,500+ chars), the passage cut
|
# a trigger-composed title rendered as the line (1,500+ chars), the passage cut
|
||||||
# to its head (which was the title again), and a `seen` repeat re-rendered whole.
|
# to its head (which was the title again), and a `seen` repeat re-rendered whole.
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
"""The CI-side token check (#2277).
|
"""The CI-side token check.
|
||||||
|
|
||||||
The checker is stdlib-only and lives in scripts/ so CI can run it without an
|
The checker is stdlib-only and lives in scripts/ so CI can run it without an
|
||||||
install, so these tests import it by path rather than as a package.
|
install, so these tests import it by path rather than as a package.
|
||||||
@@ -45,7 +45,7 @@ def test_declarations_after_a_comment_are_not_lost():
|
|||||||
|
|
||||||
|
|
||||||
def test_the_supersedes_block_is_read_from_the_sheet_not_hardcoded():
|
def test_the_supersedes_block_is_read_from_the_sheet_not_hardcoded():
|
||||||
"""Rule #115: the checker must know nothing about any install's palette.
|
"""The checker knows nothing about any install's palette.
|
||||||
Everything it enforces comes out of the stylesheet it is pointed at."""
|
Everything it enforces comes out of the stylesheet it is pointed at."""
|
||||||
assert check.superseded_literals(SHEET) == {
|
assert check.superseded_literals(SHEET) == {
|
||||||
"#fff": "--fs-text-primary",
|
"#fff": "--fs-text-primary",
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
"""Every create_* tool says what it is NOT for (#3123).
|
"""Every create_* tool says what it is NOT for.
|
||||||
|
|
||||||
WHY THIS EXISTS
|
WHY THIS EXISTS
|
||||||
|
|
||||||
Scribe's record kinds are reached for interchangeably — a note written where
|
Scribe's record kinds are reached for interchangeably — a note written where
|
||||||
a task was owed, a rule written where a snippet belonged — and the moment of
|
a task was owed, a rule written where a snippet belonged — and the moment of
|
||||||
choice is the only moment a correction is cheap. The tool docstring IS the
|
choice is the only moment a correction is cheap. The tool docstring IS the
|
||||||
agent-facing contract (rule 119 puts product guidance there and nowhere
|
agent-facing contract (product guidance lives there and nowhere else), so a docstring that only documents parameters answers "how do I call
|
||||||
else), so a docstring that only documents parameters answers "how do I call
|
|
||||||
this" while leaving "should I be calling this at all" unasked.
|
this" while leaving "should I be calling this at all" unasked.
|
||||||
|
|
||||||
The gap was lopsided before this: `create_rule` and `start_planning` both
|
The gap was lopsided before this: `create_rule` and `start_planning` both
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
"""The parent chain: walking it, and refusing to close it (milestone #254 step 1).
|
"""The parent chain: walking it, and refusing to close it.
|
||||||
|
|
||||||
Pure functions over a `{id: parent_id}` literal, so a whole hierarchy is one line
|
Pure functions over a `{id: parent_id}` literal, so a whole hierarchy is one line
|
||||||
of setup and no database is involved. That is the reason the cascade lives in its
|
of setup and no database is involved. That is the reason the cascade lives in its
|
||||||
@@ -99,7 +99,7 @@ def test_the_guard_survives_a_hierarchy_that_is_already_corrupt():
|
|||||||
|
|
||||||
# --- resolution -------------------------------------------------------------
|
# --- resolution -------------------------------------------------------------
|
||||||
#
|
#
|
||||||
# The cascade proper (milestone #254 step 2). Hierarchies are stated as literals
|
# The cascade proper. Hierarchies are stated as literals
|
||||||
# because resolve_tokens is pure and duck-typed — which is the whole reason it
|
# because resolve_tokens is pure and duck-typed — which is the whole reason it
|
||||||
# lives here rather than inside the service.
|
# lives here rather than inside the service.
|
||||||
|
|
||||||
@@ -384,7 +384,7 @@ def test_rows_without_a_supersedes_attribute_at_all_still_resolve():
|
|||||||
def test_rationale_cascades_like_purpose_and_is_a_different_question():
|
def test_rationale_cascades_like_purpose_and_is_a_different_question():
|
||||||
"""`purpose` is what the token is FOR; `rationale` is why it is this value.
|
"""`purpose` is what the token is FOR; `rationale` is why it is this value.
|
||||||
Rules carry the second routinely ("Success = Moss, aligned by design") and a
|
Rules carry the second routinely ("Success = Moss, aligned by design") and a
|
||||||
token row had nowhere to put it until now."""
|
token row needs a place to put it."""
|
||||||
resolved = _by_name(resolve_tokens(
|
resolved = _by_name(resolve_tokens(
|
||||||
APP, PARENTS,
|
APP, PARENTS,
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -120,8 +120,8 @@ def test_the_header_says_what_the_sheet_is_for():
|
|||||||
# --- modes ------------------------------------------------------------------
|
# --- modes ------------------------------------------------------------------
|
||||||
|
|
||||||
def test_base_goes_on_the_root_selector_and_other_modes_layer_over_it():
|
def test_base_goes_on_the_root_selector_and_other_modes_layer_over_it():
|
||||||
"""Matches the convention already in the codebase, and the one-way scoping
|
"""Matches the convention already in the codebase, and its one-way
|
||||||
#251 recorded: light on `:root`, dark layered on an attribute selector."""
|
scoping: light on `:root`, dark layered on an attribute selector."""
|
||||||
css = render_stylesheet([
|
css = render_stylesheet([
|
||||||
design_token_stub(name="--fs-bg", value_by_mode={"base": "#f5f1e8", "dark": "#14171a"}),
|
design_token_stub(name="--fs-bg", value_by_mode={"base": "#f5f1e8", "dark": "#14171a"}),
|
||||||
])
|
])
|
||||||
@@ -188,7 +188,7 @@ def test_a_declared_token_with_no_value_appears_as_a_comment_not_a_silence():
|
|||||||
|
|
||||||
|
|
||||||
def test_an_empty_system_renders_a_sheet_with_no_blocks_rather_than_failing():
|
def test_an_empty_system_renders_a_sheet_with_no_blocks_rather_than_failing():
|
||||||
"""A system with no tokens is an ordinary state (rule #115), including one
|
"""A system with no tokens is an ordinary state, including one
|
||||||
that was just created."""
|
that was just created."""
|
||||||
css = render_stylesheet([])
|
css = render_stylesheet([])
|
||||||
assert "{" not in css
|
assert "{" not in css
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ the dangerous one: a recurring task embedded to a different shape than the rest
|
|||||||
of the corpus is ranked against documents it doesn't match, and nothing reports
|
of the corpus is ranked against documents it doesn't match, and nothing reports
|
||||||
it. A wrong vector returns results; it just returns the wrong ones.
|
it. A wrong vector returns results; it just returns the wrong ones.
|
||||||
|
|
||||||
It is also the precondition for #2486. A dev-log's vector separates from five
|
It is also the precondition for comparing document shapes. A dev-log's vector separates from five
|
||||||
unrelated dev-logs by 0.023 where a snippet separates by 0.153, and the leading
|
unrelated dev-logs by 0.023 where a snippet separates by 0.153, and the leading
|
||||||
explanation is shape — a snippet states its purpose twice in a short document.
|
explanation is shape — a snippet states its purpose twice in a short document.
|
||||||
Testing an alternative against three copies would mean testing a shape that
|
Testing an alternative against three copies would mean testing a shape that
|
||||||
@@ -77,5 +77,5 @@ def test_nothing_else_builds_the_embedding_document_itself():
|
|||||||
f"these build the embedding document inline instead of calling "
|
f"these build the embedding document inline instead of calling "
|
||||||
f"embedding_text(): {offenders}. One definition — an inlined copy is "
|
f"embedding_text(): {offenders}. One definition — an inlined copy is "
|
||||||
f"ranked against a corpus it no longer matches the moment the shape "
|
f"ranked against a corpus it no longer matches the moment the shape "
|
||||||
f"changes, and nothing reports it (#2486)."
|
f"changes, and nothing reports it."
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
"""The embedding refresh must LOSE to a delete, not race it (#3262).
|
"""The embedding refresh must LOSE to a delete, not race it.
|
||||||
|
|
||||||
Both upserts replace a record's vectors as delete-then-insert. That takes two
|
Both upserts replace a record's vectors as delete-then-insert. That takes two
|
||||||
row locks — the chunk rows, then the parent row via the insert's foreign key —
|
row locks — the chunk rows, then the parent row via the insert's foreign key —
|
||||||
@@ -32,7 +32,7 @@ def _mock_session(lock_result: object = 7, execute_side_effect=None):
|
|||||||
session = MagicMock()
|
session = MagicMock()
|
||||||
claimed = MagicMock()
|
claimed = MagicMock()
|
||||||
claimed.scalar_one_or_none.return_value = lock_result
|
claimed.scalar_one_or_none.return_value = lock_result
|
||||||
# A task's document carries its work logs (#4251), so the refresh reads
|
# A task's document carries its work logs, so the refresh reads
|
||||||
# task_logs before it builds chunks. Answered explicitly — left to
|
# task_logs before it builds chunks. Answered explicitly — left to
|
||||||
# autovivify, `list(result.all())` would raise and be swallowed, and these
|
# autovivify, `list(result.all())` would raise and be swallowed, and these
|
||||||
# tests would be exercising the failure path without saying so.
|
# tests would be exercising the failure path without saying so.
|
||||||
@@ -72,7 +72,7 @@ async def test_a_note_refresh_claims_the_row_before_rewriting_its_vectors():
|
|||||||
|
|
||||||
sqls = [compiled_sql(c.args[0], dialect=PG) for c in session.execute.call_args_list]
|
sqls = [compiled_sql(c.args[0], dialect=PG) for c in session.execute.call_args_list]
|
||||||
# Located by what they ARE rather than by position: the work-log read a
|
# Located by what they ARE rather than by position: the work-log read a
|
||||||
# task's document needs (#4251) runs before any of this, and an index is
|
# task's document needs runs before any of this, and an index is
|
||||||
# not what the claim is about.
|
# not what the claim is about.
|
||||||
claim = next(i for i, sql in enumerate(sqls) if "FOR KEY SHARE NOWAIT" in sql)
|
claim = next(i for i, sql in enumerate(sqls) if "FOR KEY SHARE NOWAIT" in sql)
|
||||||
replace = next(
|
replace = next(
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ async def test_get_embedding_propagates_model_load_failures():
|
|||||||
await get_embedding("x")
|
await get_embedding("x")
|
||||||
|
|
||||||
|
|
||||||
# ─── query_embedding_memo (milestone 456 step 1) ─────────────────────────────
|
# ─── query_embedding_memo ────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
|
||||||
def _counting_embeddings():
|
def _counting_embeddings():
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
"""The promotion engine without a database (milestone 463 step 3).
|
"""The promotion engine without a database.
|
||||||
|
|
||||||
The parts that decide — which citations claim lineage, which criteria veto —
|
The parts that decide — which citations claim lineage, which criteria veto —
|
||||||
are pure and pinned here, beside the doors' wiring: the triggers ride the
|
are pure and pinned here, beside the doors' wiring: the triggers ride the
|
||||||
@@ -89,7 +89,7 @@ def test_proven_needs_named_evidence():
|
|||||||
|
|
||||||
|
|
||||||
def test_the_criteria_the_agent_is_told_are_the_ones_enforced():
|
def test_the_criteria_the_agent_is_told_are_the_ones_enforced():
|
||||||
"""Rule 119: the criteria are product text. The promote tool's docstring
|
"""The criteria are product text. The promote tool's docstring
|
||||||
must name every criterion the service checks, by its parameter name."""
|
must name every criterion the service checks, by its parameter name."""
|
||||||
doc = family_tools.promote_family_idea.__doc__
|
doc = family_tools.promote_family_idea.__doc__
|
||||||
for key in CRITERIA_KEYS:
|
for key in CRITERIA_KEYS:
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
"""The adoption ledger without a database (milestone 463 step 4).
|
"""The adoption ledger without a database.
|
||||||
|
|
||||||
The parts that decide are pure and pinned here: what an assessment needs
|
The parts that decide are pure and pinned here: what an assessment needs
|
||||||
before it can be recorded, what each ground of the conflict order needs —
|
before it can be recorded, what each ground of the conflict order needs —
|
||||||
@@ -166,7 +166,7 @@ def test_no_reference_at_all_points_at_the_idea():
|
|||||||
# --- the product text and the doors ---------------------------------------------------
|
# --- the product text and the doors ---------------------------------------------------
|
||||||
|
|
||||||
def test_the_outcomes_the_agent_is_told_are_the_ones_enforced():
|
def test_the_outcomes_the_agent_is_told_are_the_ones_enforced():
|
||||||
"""Rule 119: the outcomes and the order are product text. The tool
|
"""The outcomes and the order are product text. The tool
|
||||||
docstrings must name every outcome and every ground the service checks,
|
docstrings must name every outcome and every ground the service checks,
|
||||||
in the service's order."""
|
in the service's order."""
|
||||||
assess_doc = tool_doc("scribe.mcp.tools.family", "assess_family_adoption")
|
assess_doc = tool_doc("scribe.mcp.tools.family", "assess_family_adoption")
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
"""How family canon reaches a session (milestone 463 step 6), without a
|
"""How family canon reaches a session, without a
|
||||||
database: the line enter_project carries, the skill and its triggers, and the
|
database: the line enter_project carries, the skill and its triggers, and the
|
||||||
pointers every other surface gives to it. Retrieval reach, the readout's
|
pointers every other surface gives to it. Retrieval reach, the readout's
|
||||||
counts and the owed answers against Postgres are in
|
counts and the owed answers against Postgres are in
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
"""Forge-connection tokens are stored sealed (milestone 523, #5877).
|
"""Forge-connection tokens are stored sealed.
|
||||||
|
|
||||||
Migration 0122 seals the rows that existed before, with its OWN frozen copy of
|
Migration 0122 seals the rows that existed before, with its OWN frozen copy of
|
||||||
the v1 key derivation (so a later edit to services/secrets.py can never change
|
the v1 key derivation (so a later edit to services/secrets.py can never change
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
"""Forge push webhook (#2691) — signature gate, payload parsing, and the
|
"""Forge push webhook — signature gate, payload parsing, and the
|
||||||
end-to-end drift flag on real Postgres.
|
end-to-end drift flag on real Postgres.
|
||||||
|
|
||||||
The webhook is the seam that makes verification scale: a push names exactly
|
The webhook is the seam that makes verification scale: a push names exactly
|
||||||
@@ -43,7 +43,7 @@ def test_signature_gate():
|
|||||||
|
|
||||||
|
|
||||||
def test_delivered_signature_reads_both_forges_headers():
|
def test_delivered_signature_reads_both_forges_headers():
|
||||||
"""#2693: GitHub signs the same HMAC but ships it as
|
"""GitHub signs the same HMAC but ships it as
|
||||||
X-Hub-Signature-256: sha256=<hex> — the whole webhook payload mapping is
|
X-Hub-Signature-256: sha256=<hex> — the whole webhook payload mapping is
|
||||||
this header, so pin it."""
|
this header, so pin it."""
|
||||||
hexsig = _sign(b"{}")
|
hexsig = _sign(b"{}")
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
"""The create gate's similarity bars are settings, clamped and fail-open (#4385)."""
|
"""The create gate's similarity bars are settings, clamped and fail-open."""
|
||||||
from unittest.mock import AsyncMock, patch
|
from unittest.mock import AsyncMock, patch
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
"""Under `pipefail`, an early-exiting `head` must not void the output it kept (#4042).
|
"""Under `pipefail`, an early-exiting `head` must not void the output it kept.
|
||||||
|
|
||||||
The hooks run with `set -uo pipefail`. `hits=$(git grep -l … | head -4) ||
|
The hooks run with `set -uo pipefail`. `hits=$(git grep -l … | head -4) ||
|
||||||
hits=""` lost its four hits whenever git grep was still writing when head
|
hits=""` loses its four hits whenever git grep is still writing when head
|
||||||
exited: SIGPIPE, a failed substitution, and the fallback wiped the result. It
|
exits: SIGPIPE, a failed substitution, and the fallback wipes the result. It
|
||||||
only showed on big outputs, so the by-name duplicate arm went silent for
|
only shows on big outputs, so the by-name duplicate arm goes silent for
|
||||||
exactly the most-duplicated names.
|
exactly the most-duplicated names.
|
||||||
|
|
||||||
Two halves: the real function on a repo big enough to overflow the pipe, and
|
Two halves: the real function on a repo big enough to overflow the pipe, and
|
||||||
the check_plugin pattern that keeps the shape out of every hook (shown able to
|
the check_plugin pattern that keeps the shape out of every hook (shown able to
|
||||||
fail, rule #167).
|
fail).
|
||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
"""Real-Postgres round trip for code_shapes (#4197).
|
"""Real-Postgres round trip for code_shapes.
|
||||||
|
|
||||||
**What this guards is a column that was simply not there.** `code_shapes`
|
**What this guards is a column the import leaves out.** If `code_shapes`
|
||||||
exported `reason_code`, `recheck_at` and `diverges_from` and imported none of
|
exports `reason_code`, `recheck_at` and `diverges_from` and imports none of
|
||||||
them — a restore reported success and came back with every judgment's verdict
|
them, a restore reports success and comes back with every judgment's verdict
|
||||||
and no code for why, every recheck flag cleared, and every divergence pointer
|
and no code for why, every recheck flag cleared, and every divergence pointer
|
||||||
gone. The unit-level column guard in `test_services_backup.py` is what found
|
gone. The unit-level column guard in `test_services_backup.py` catches a
|
||||||
it and is what stops it recurring; this file is the behavioural half, because
|
column missing from either side; this file is the behavioural half, because
|
||||||
"the builder passes the kwarg" and "the value survives a real restore" are
|
"the builder passes the kwarg" and "the value survives a real restore" are
|
||||||
different claims.
|
different claims.
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
"""Real-Postgres check that the full export is ORDERED, so the backup file
|
"""Real-Postgres check that the full export is ORDERED, so the backup file
|
||||||
deduplicates between runs (milestone 523).
|
deduplicates between runs.
|
||||||
|
|
||||||
Only Postgres shows this. An unordered select returns rows in heap order, and
|
Only Postgres shows this. An unordered select returns rows in heap order, and
|
||||||
an UPDATE writes the row's new version at the end of the heap — so before
|
an UPDATE writes the row's new version at the end of the heap — so without an
|
||||||
export_full_backup ordered its queries, editing one old note moved it to the
|
ORDER BY in export_full_backup, editing one old note moves it to the bottom of
|
||||||
bottom of `notes`. Every byte after its old place shifted, and a restic run
|
`notes`. Every byte after its old place shifts, and a restic run over the next
|
||||||
over the next backup stored most of the table again. A mocked session returns
|
backup stores most of the table again. A mocked session returns
|
||||||
whatever order it was handed and could never catch it.
|
whatever order it was handed and could never catch it.
|
||||||
"""
|
"""
|
||||||
import io
|
import io
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ async def test_the_tar_restores_with_every_id_remapped(written):
|
|||||||
assert (note.project_id, note.milestone_id) == (project.id, milestone.id)
|
assert (note.project_id, note.milestone_id) == (project.id, milestone.id)
|
||||||
assert note.body == "From the tar, not the JSON."
|
assert note.body == "From the tar, not the JSON."
|
||||||
assert note.status == "todo"
|
assert note.status == "todo"
|
||||||
# The Profile page travels with its user (#5879); a field left blank stays
|
# The Profile page travels with its user; a field left blank stays
|
||||||
# blank rather than restoring as the page's default.
|
# blank rather than restoring as the page's default.
|
||||||
assert (profile.display_name, profile.tone) == ("Drill Owner", "technical")
|
assert (profile.display_name, profile.tone) == ("Drill Owner", "technical")
|
||||||
assert profile.interests == ["backups"]
|
assert profile.interests == ["backups"]
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
"""Real-Postgres round trip for rule_versions (milestone 323 step 1).
|
"""Real-Postgres round trip for rule_versions.
|
||||||
|
|
||||||
Two things here cannot be shown with mocks, and both are the kind that fail
|
Two things here cannot be shown with mocks, and both are the kind that fail
|
||||||
QUIETLY — a restore reports success and hands back history that is wrong.
|
QUIETLY — a restore reports success and hands back history that is wrong.
|
||||||
@@ -7,7 +7,7 @@ QUIETLY — a restore reports success and hands back history that is wrong.
|
|||||||
A restore that writes it straight through succeeds and attaches every
|
A restore that writes it straight through succeeds and attaches every
|
||||||
snapshot to whatever rule happens to hold that number here — an edit
|
snapshot to whatever rule happens to hold that number here — an edit
|
||||||
history filed against the wrong binding instruction, which is worse than
|
history filed against the wrong binding instruction, which is worse than
|
||||||
no history at all. This is #3182's `arose_from_id` trap on a new table.
|
no history at all. It is the same trap as a note's `arose_from_id`.
|
||||||
|
|
||||||
2. **A null actor does not drop the row.** `user_id` is SET NULL precisely so
|
2. **A null actor does not drop the row.** `user_id` is SET NULL precisely so
|
||||||
history outlives the account that wrote it, so the restore deliberately
|
history outlives the account that wrote it, so the restore deliberately
|
||||||
@@ -217,7 +217,7 @@ async def test_both_snapshots_come_back(restored):
|
|||||||
|
|
||||||
|
|
||||||
async def test_the_history_attaches_to_the_RESTORED_rule(restored):
|
async def test_the_history_attaches_to_the_RESTORED_rule(restored):
|
||||||
"""#3182's trap. The source rule still exists and holds a different id, so
|
"""The remap trap. The source rule still exists and holds a different id, so
|
||||||
a straight-through copy would file this history against it — or against
|
a straight-through copy would file this history against it — or against
|
||||||
whatever unrelated rule owns that number."""
|
whatever unrelated rule owns that number."""
|
||||||
new_rule_id = restored["rule"].id
|
new_rule_id = restored["rule"].id
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
"""The adoption ledger against real Postgres (milestone 463 step 4).
|
"""The adoption ledger against real Postgres.
|
||||||
|
|
||||||
What the unit lane can't show: an answer moves the row and logs exactly one
|
What the unit lane can't show: an answer moves the row and logs exactly one
|
||||||
decision; an owed answer files its task in the OWING project, tagged to the
|
decision; an owed answer files its task in the OWING project, tagged to the
|
||||||
@@ -236,7 +236,7 @@ async def test_another_projects_answer_is_recorded_as_precedent(family):
|
|||||||
assert first["decision"]["id"] in second["decision"]["precedent_ids"]
|
assert first["decision"]["id"] in second["decision"]["precedent_ids"]
|
||||||
assert second["precedents"][0]["relation"] == "same idea, another project"
|
assert second["precedents"][0]["relation"] == "same idea, another project"
|
||||||
assert second["precedents"][0]["project_title"] == "android one"
|
assert second["precedents"][0]["project_title"] == "android one"
|
||||||
# A precedent says its reason once: before/after are state only (#5131).
|
# A precedent says its reason once: before/after are state only.
|
||||||
assert second["precedents"][0]["reason"] == "the source app"
|
assert second["precedents"][0]["reason"] == "the source app"
|
||||||
assert "reason" not in second["precedents"][0]["after"]
|
assert "reason" not in second["precedents"][0]["after"]
|
||||||
|
|
||||||
@@ -392,7 +392,7 @@ async def test_the_matrix_hides_what_the_caller_cannot_read(family):
|
|||||||
assert all(i["note_id"] != family["note"] for i in matrix["ideas"])
|
assert all(i["note_id"] != family["note"] for i in matrix["ideas"])
|
||||||
|
|
||||||
|
|
||||||
# --- the shape ledger as evidence (step 5) -------------------------------------------
|
# --- the shape ledger as evidence ----------------------------------------------------
|
||||||
|
|
||||||
REPO = "git.example/android-two"
|
REPO = "git.example/android-two"
|
||||||
KOTLIN_BODY = (
|
KOTLIN_BODY = (
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
"""Real-Postgres checks for family canon's schema (milestone 463 step 1).
|
"""Real-Postgres checks for family canon's schema.
|
||||||
|
|
||||||
Two kinds of claim live here, and both need a database:
|
Two kinds of claim live here, and both need a database:
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
"""The promotion engine against real Postgres (milestone 463 step 3).
|
"""The promotion engine against real Postgres.
|
||||||
|
|
||||||
What the unit lane can't show: a promotion opens the right ledger rows and
|
What the unit lane can't show: a promotion opens the right ledger rows and
|
||||||
no others, a veto changes nothing but the log, an undo puts back exactly the
|
no others, a veto changes nothing but the log, an undo puts back exactly the
|
||||||
@@ -279,9 +279,9 @@ async def test_a_repeat_with_no_shared_platform_is_silent(family):
|
|||||||
|
|
||||||
|
|
||||||
async def test_a_repeat_across_kinds_is_silent(family):
|
async def test_a_repeat_across_kinds_is_silent(family):
|
||||||
"""A snippet whose only match is a NOTE is not a repeat (#5130): a dated
|
"""A snippet whose only match is a NOTE is not a repeat: a dated
|
||||||
release log scored 0.83 against a signed-APK CI snippet on shared
|
release log can score above the bar against a signed-APK CI snippet on
|
||||||
vocabulary and was opened as a candidate. The stub hands back the
|
shared vocabulary alone, and would open as a candidate. The stub hands back the
|
||||||
cross-kind hit directly, so this pins the trigger's own check, not the
|
cross-kind hit directly, so this pins the trigger's own check, not the
|
||||||
search filter in front of it."""
|
search filter in front of it."""
|
||||||
async with async_session() as s:
|
async with async_session() as s:
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
"""A family idea reaches every project on its platform, and no other
|
"""A family idea reaches every project on its platform, and no other.
|
||||||
(milestone 463 step 6).
|
|
||||||
|
|
||||||
WHY THIS IS AN INTEGRATION TEST — the lesson-reach reasoning (#3730) holds
|
WHY THIS IS AN INTEGRATION TEST — the lesson-reach reasoning holds
|
||||||
here too: the reach is one `OR` inside the search's project filter, and only
|
here too: the reach is one `OR` inside the search's project filter, and only
|
||||||
the ROWS that come back prove it. Every note embeds identically to the query,
|
the ROWS that come back prove it. Every note embeds identically to the query,
|
||||||
so scoping is the only thing that can separate them. The embedder is stubbed;
|
so scoping is the only thing that can separate them. The embedder is stubbed;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
"""Real-Postgres integration tests for the forge keyring (#2778).
|
"""Real-Postgres integration tests for the forge keyring.
|
||||||
|
|
||||||
Runs only in the CI integration lane (real Postgres, schema built by
|
Runs only in the CI integration lane (real Postgres, schema built by
|
||||||
`alembic upgrade head`, which includes migration 0078's forge_connections
|
`alembic upgrade head`, which includes migration 0078's forge_connections
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
"""Real-Postgres tests for "recently touched" in the enter_project handshake (#4045).
|
"""Real-Postgres tests for "recently touched" in the enter_project handshake.
|
||||||
|
|
||||||
What a mock cannot show: that a work-log moves its task up the list even
|
What a mock cannot show: that a work-log moves its task up the list even
|
||||||
though logging never bumps the task's updated_at, and that a milestone whose
|
though logging never bumps the task's updated_at, and that a milestone whose
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
"""Real-Postgres integration tests for project inception (milestone 297).
|
"""Real-Postgres integration tests for project inception.
|
||||||
|
|
||||||
What mocks can't prove: a decision's effects land through the real services
|
What mocks can't prove: a decision's effects land through the real services
|
||||||
(the design system points, the standard Systems seed once), the record is
|
(the design system points, the standard Systems seed once), the record is
|
||||||
written last, a bad target applies nothing.
|
written last, a bad target applies nothing.
|
||||||
|
|
||||||
Rules are not part of inception since milestone 414: a rule in a rulebook is
|
Rules are not part of inception: a rule in a rulebook is
|
||||||
global and applies to every project, so there is nothing to subscribe to.
|
global and applies to every project, so there is nothing to subscribe to.
|
||||||
"""
|
"""
|
||||||
import pytest
|
import pytest
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
"""A lesson is reachable from a project it was not written on (step 3).
|
"""A lesson is reachable from a project it was not written on.
|
||||||
|
|
||||||
WHY THIS IS AN INTEGRATION TEST
|
WHY THIS IS AN INTEGRATION TEST
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
"""Real-Postgres tests for finding a plan by meaning (milestone 415, steps 3 and 4).
|
"""Real-Postgres tests for finding a plan by meaning.
|
||||||
|
|
||||||
A project's roadmap written as milestones was invisible to recall: `search`
|
A project's roadmap is written as milestones, and `search` reaches them, so
|
||||||
covered notes, tasks and rules, so "is there already a plan for this?" had no
|
"is there already a plan for this?" has a tool. What a mock cannot show is the join scoping the vectors to a project and
|
||||||
tool. What a mock cannot show is the join scoping the vectors to a project and
|
|
||||||
to what the caller may read, so these seed real milestones with hand-made
|
to what the caller may read, so these seed real milestones with hand-made
|
||||||
vectors and stub only the embedder.
|
vectors and stub only the embedder.
|
||||||
"""
|
"""
|
||||||
@@ -84,7 +83,7 @@ async def test_a_project_the_caller_cannot_read_returns_nothing(roadmap):
|
|||||||
assert await _found(roadmap["stranger"]) == []
|
assert await _found(roadmap["stranger"]) == []
|
||||||
|
|
||||||
|
|
||||||
# ── the plan gate (step 4): start_planning finds the plan before making another ──
|
# ── the plan gate: start_planning finds the plan before making another ──
|
||||||
|
|
||||||
LONG = "Resolve works and editions against the metadata providers. " * 5
|
LONG = "Resolve works and editions against the metadata providers. " * 5
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
"""Real-Postgres tests for an install's moment mappings (milestone 458 step 2).
|
"""Real-Postgres tests for an install's moment mappings.
|
||||||
|
|
||||||
What these pin is what the in-session correction promises the operator: a
|
What these pin is what the in-session correction promises the operator: a
|
||||||
mapping made is in force on the next call, a default switched off stays off,
|
mapping made is in force on the next call, a default switched off stays off,
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ def _vec(*nonzero_first):
|
|||||||
|
|
||||||
|
|
||||||
def _emb(note_id, user_id, chunk_index, vec):
|
def _emb(note_id, user_id, chunk_index, vec):
|
||||||
"""A chunk row at the current chunker version (#280, migration 0077)."""
|
"""A chunk row at the current chunker version."""
|
||||||
from scribe.services.embeddings import CHUNKER_VERSION, EMBEDDING_MODEL
|
from scribe.services.embeddings import CHUNKER_VERSION, EMBEDDING_MODEL
|
||||||
|
|
||||||
return NoteEmbedding(
|
return NoteEmbedding(
|
||||||
@@ -63,7 +63,7 @@ async def seeded():
|
|||||||
# query vector will be [1,0,0,...]; near ~ identical (sim≈1.0),
|
# query vector will be [1,0,0,...]; near ~ identical (sim≈1.0),
|
||||||
# far is orthogonal (sim≈0.0 -> filtered by the default threshold).
|
# far is orthogonal (sim≈0.0 -> filtered by the default threshold).
|
||||||
# near gets a SECOND, weaker chunk (sim≈0.6) — the collapse to
|
# near gets a SECOND, weaker chunk (sim≈0.6) — the collapse to
|
||||||
# best-chunk-per-note (#280) is under test: near must come back once,
|
# best-chunk-per-note is under test: near must come back once,
|
||||||
# at its best chunk's score, not twice.
|
# at its best chunk's score, not twice.
|
||||||
s.add(_emb(near.id, user.id, 0, _vec(1.0)))
|
s.add(_emb(near.id, user.id, 0, _vec(1.0)))
|
||||||
s.add(_emb(near.id, user.id, 1, _vec(0.6, 0.8)))
|
s.add(_emb(near.id, user.id, 1, _vec(0.6, 0.8)))
|
||||||
@@ -94,7 +94,7 @@ async def test_semantic_search_ranks_and_thresholds_via_pgvector(seeded):
|
|||||||
assert near_id in ids
|
assert near_id in ids
|
||||||
assert far_id not in ids
|
assert far_id not in ids
|
||||||
assert ids[0] == near_id
|
assert ids[0] == near_id
|
||||||
# Chunk collapse (#280): near has TWO chunk rows above the floor (sim≈1.0
|
# Chunk collapse: near has TWO chunk rows above the floor (sim≈1.0
|
||||||
# and ≈0.6) and must appear exactly once, at its best chunk's score.
|
# and ≈0.6) and must appear exactly once, at its best chunk's score.
|
||||||
assert ids.count(near_id) == 1
|
assert ids.count(near_id) == 1
|
||||||
top_score = results[0][0]
|
top_score = results[0][0]
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
"""Real-Postgres tests for task placement (milestone 409 step 1).
|
"""Real-Postgres tests for task placement.
|
||||||
|
|
||||||
What a mock cannot show: that step order is creation order rather than update
|
What a mock cannot show: that step order is creation order rather than update
|
||||||
order, that position and progress are computed over the steps the CALLER may
|
order, that position and progress are computed over the steps the CALLER may
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
"""Real-Postgres checks for platform membership (milestone 463 step 2).
|
"""Real-Postgres checks for platform membership.
|
||||||
|
|
||||||
The one invariant: detection only ever ADDS, and only where nobody has
|
The one invariant: detection only ever ADDS, and only where nobody has
|
||||||
answered. A refresh that overwrote a "no" would put a project back into a
|
answered. A refresh that overwrote a "no" would put a project back into a
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
"""Real-Postgres proof that a batch create cannot be interfered with (#4016).
|
"""Real-Postgres proof that a batch create cannot be interfered with.
|
||||||
|
|
||||||
What mocks cannot show: that the ids a placeholder is rewritten to are the ids
|
What mocks cannot show: that the ids a placeholder is rewritten to are the ids
|
||||||
the rows actually got, that two batches running at the same time each cite
|
the rows actually got, that two batches running at the same time each cite
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"""Real-Postgres tests for moment proposals and judgments (milestone 458 step 7).
|
"""Real-Postgres tests for moment proposals and judgments.
|
||||||
|
|
||||||
What the step promises, against the real tables:
|
What the feature promises, against the real tables:
|
||||||
- the pass reads only rules nobody has answered for, and any answer — a
|
- the pass reads only rules nobody has answered for, and any answer — a
|
||||||
proposal, a mount, "no moment fits" — takes a rule off that list;
|
proposal, a mount, "no moment fits" — takes a rule off that list;
|
||||||
- a proposal mounts nothing; a confirm mounts, a reject is kept, and a judged
|
- a proposal mounts nothing; a confirm mounts, a reject is kept, and a judged
|
||||||
@@ -8,7 +8,7 @@ What the step promises, against the real tables:
|
|||||||
- an edit that takes a moment off a rule is a rejection the signal respects;
|
- an edit that takes a moment off a rule is a rejection the signal respects;
|
||||||
- the signal counts SESSIONS, not opens, and asks once the bar is crossed;
|
- the signal counts SESSIONS, not opens, and asks once the bar is crossed;
|
||||||
- only the owner can propose, judge, or feed the signal;
|
- only the owner can propose, judge, or feed the signal;
|
||||||
- the misfire (step 7b): only a mount can misfire, reports count DAYS, the
|
- the misfire: only a mount can misfire, reports count DAYS, the
|
||||||
bar makes an unmount proposal, reject takes it off, confirm keeps it and
|
bar makes an unmount proposal, reject takes it off, confirm keeps it and
|
||||||
stops the asking, and a re-mount starts the count again.
|
stops the asking, and a re-mount starts the count again.
|
||||||
"""
|
"""
|
||||||
@@ -196,7 +196,7 @@ async def test_the_open_resolves_acts_through_the_installs_mappings(world):
|
|||||||
assert (await _row(done.id, "work.deliver")).source == "signal"
|
assert (await _row(done.id, "work.deliver")).source == "signal"
|
||||||
|
|
||||||
|
|
||||||
# ── The misfire (step 7b) ────────────────────────────────────────────────────
|
# ── The misfire ──────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
"""Real-Postgres tests for moving a rule between homes (milestone 414, step 3).
|
"""Real-Postgres tests for moving a rule between homes.
|
||||||
|
|
||||||
A rule's home is its reach: a rulebook topic makes it global, a project makes
|
A rule's home is its reach: a rulebook topic makes it global, a project makes
|
||||||
it that project's. The alternative to a move — recreate the rule in the other
|
it that project's. The alternative to a move — recreate the rule in the other
|
||||||
@@ -84,7 +84,7 @@ async def test_a_project_rule_becomes_global_and_keeps_everything(homes):
|
|||||||
|
|
||||||
|
|
||||||
async def test_a_move_writes_no_version(homes):
|
async def test_a_move_writes_no_version(homes):
|
||||||
"""A version records what a rule SAID (milestone 323, decision 4). A move
|
"""A version records what a rule SAID. A move
|
||||||
changes where it binds, not a word of it."""
|
changes where it binds, not a word of it."""
|
||||||
before = len(await rv_svc.list_versions(homes["rule"]))
|
before = len(await rv_svc.list_versions(homes["rule"]))
|
||||||
await rulebooks_svc.move_rule(homes["rule"], homes["owner"], topic_id=homes["topic"])
|
await rulebooks_svc.move_rule(homes["rule"], homes["owner"], topic_id=homes["topic"])
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
"""Real-Postgres tests for a rule's CHECK — the write half (milestone 312).
|
"""Real-Postgres tests for a rule's CHECK — the write half.
|
||||||
|
|
||||||
What mocks cannot prove, and what the staleness sweep depends on:
|
What mocks cannot prove, and what the staleness sweep depends on:
|
||||||
|
|
||||||
@@ -132,7 +132,7 @@ async def test_editing_anything_else_leaves_the_stamp_alone(constraint):
|
|||||||
assert row.why.startswith("act_runner picks the shell")
|
assert row.why.startswith("act_runner picks the shell")
|
||||||
|
|
||||||
|
|
||||||
# ── the sweep itself (step 3) ──────────────────────────────────────────
|
# ── the sweep itself ───────────────────────────────────────────────────
|
||||||
|
|
||||||
@pytest_asyncio.fixture
|
@pytest_asyncio.fixture
|
||||||
async def rulebook_of_three():
|
async def rulebook_of_three():
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
"""Real-Postgres crowd tests: an in-scope record is found however many nearer
|
"""Real-Postgres crowd tests: an in-scope record is found however many nearer
|
||||||
records sit outside the scope (#4961; the rule search's is #4958's, in
|
records sit outside the scope (the rule search's crowd test is in
|
||||||
test_integration_rule_scope).
|
test_integration_rule_scope).
|
||||||
|
|
||||||
Ordered straight off a `*_embeddings` table, the planner can walk the HNSW
|
Ordered straight off a `*_embeddings` table, the planner can walk the HNSW
|
||||||
index, which takes ~`hnsw.ef_search` (40) nearest chunks from every owner and
|
index, which takes ~`hnsw.ef_search` (40) nearest chunks from every owner and
|
||||||
project and only then applies the scope. Each test here puts 80 out-of-scope
|
project and only then applies the scope. Each test here puts 80 out-of-scope
|
||||||
records nearer the query than the reader's one in-scope record, so the old
|
records nearer the query than the reader's one in-scope record, so a query
|
||||||
shape could not reach it when the index served the order. What a test cannot
|
that scopes after the index walk cannot reach it when the index serves the
|
||||||
force is the plan — the shape guard in test_search_scope_shape is what fails
|
order. What a test cannot force is the plan — the shape guard in
|
||||||
on the old query whatever Postgres picks.
|
test_search_scope_shape is what fails on that query whatever Postgres picks.
|
||||||
|
|
||||||
Rows are inserted directly with hand-made vectors and the embedder is stubbed,
|
Rows are inserted directly with hand-made vectors and the embedder is stubbed,
|
||||||
so the scope alone decides what comes back.
|
so the scope alone decides what comes back.
|
||||||
@@ -57,7 +57,7 @@ def _chunk(model, key: str, record_id: int, vec: list[float], **extra):
|
|||||||
async def _found(search, user_id: int, **scope) -> set[int]:
|
async def _found(search, user_id: int, **scope) -> set[int]:
|
||||||
"""The ids a search finds. Every search fails open, so a query that raised
|
"""The ids a search finds. Every search fails open, so a query that raised
|
||||||
reads as an empty result — the swallowed traceback is captured and named
|
reads as an empty result — the swallowed traceback is captured and named
|
||||||
in the failure instead (#4958)."""
|
in the failure instead."""
|
||||||
raised: list[str] = []
|
raised: list[str] = []
|
||||||
with patch("scribe.services.embeddings.get_embedding",
|
with patch("scribe.services.embeddings.get_embedding",
|
||||||
AsyncMock(return_value=QUERY_VEC)), \
|
AsyncMock(return_value=QUERY_VEC)), \
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
"""Real-Postgres integration test for the snippet location reverse lookup (#2083).
|
"""Real-Postgres integration test for the snippet location reverse lookup.
|
||||||
|
|
||||||
Runs only in the CI integration lane (real Postgres, schema built by
|
Runs only in the CI integration lane (real Postgres, schema built by
|
||||||
`alembic upgrade head`, which includes migration 0070's `notes.data` + GIN index).
|
`alembic upgrade head`, which includes migration 0070's `notes.data` + GIN index).
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"""Real-Postgres test that the CHECK actually accepts 'spike' (0091).
|
"""Real-Postgres test that the CHECK actually accepts 'spike' (0091).
|
||||||
|
|
||||||
Rule 36 exists because the value and the constraint can drift apart: the
|
The value and the constraint can drift apart: the
|
||||||
code starts writing a new kind while the database still refuses it, and
|
code starts writing a new kind while the database still refuses it, and
|
||||||
nothing catches it until a write fails in front of someone. A mock cannot
|
nothing catches it until a write fails in front of someone. A mock cannot
|
||||||
show that — it has no CHECK — so the constraint gets its own real-DB test,
|
show that — it has no CHECK — so the constraint gets its own real-DB test,
|
||||||
@@ -68,19 +68,18 @@ async def test_an_unknown_kind_is_still_refused(owner_id):
|
|||||||
|
|
||||||
Without this, every assertion above would pass just as happily against a
|
Without this, every assertion above would pass just as happily against a
|
||||||
table whose CHECK had been dropped and never re-added — which is exactly
|
table whose CHECK had been dropped and never re-added — which is exactly
|
||||||
the failure rule 36 is written against.
|
the drift this file is written against.
|
||||||
"""
|
"""
|
||||||
with pytest.raises(IntegrityError):
|
with pytest.raises(IntegrityError):
|
||||||
await _write(owner_id, "investigation")
|
await _write(owner_id, "investigation")
|
||||||
|
|
||||||
|
|
||||||
async def test_a_kind_can_be_corrected_after_the_fact(owner_id):
|
async def test_a_kind_can_be_corrected_after_the_fact(owner_id):
|
||||||
"""The write-once bug, asserted against a real column (#3129).
|
"""A kind is not write-once, asserted against a real column.
|
||||||
|
|
||||||
The read-back is the whole test. A version that only asserted the update
|
The read-back is the whole test. A version that only asserted the update
|
||||||
call succeeded would have passed against the broken code — the route
|
call succeeded would pass against a route that returns 200 while dropping
|
||||||
returned 200 while dropping the field, which is exactly how this survived
|
the field, which is a failure nothing else reports.
|
||||||
long enough to be found by hand.
|
|
||||||
"""
|
"""
|
||||||
from scribe.services import notes as notes_svc
|
from scribe.services import notes as notes_svc
|
||||||
|
|
||||||
|
|||||||
@@ -3,14 +3,14 @@
|
|||||||
The facet predicate is written twice by necessity — as SQL for rows the
|
The facet predicate is written twice by necessity — as SQL for rows the
|
||||||
database hands back, and as Python for candidates the vector search has
|
database hands back, and as Python for candidates the vector search has
|
||||||
already fetched — plus a third time as the `is_task` pre-filter that narrows
|
already fetched — plus a third time as the `is_task` pre-filter that narrows
|
||||||
the candidate set before it exists. Those three used to be hand-written and
|
the candidate set before it exists. Hand-written, those three
|
||||||
agreed only by luck: adding `issue` to the SQL arm alone would have set the
|
agree only by luck: adding `issue` to the SQL arm alone would set the
|
||||||
pre-filter to is_task=False, handed the Python arm a candidate set with no
|
pre-filter to is_task=False, hand the Python arm a candidate set with no
|
||||||
tasks in it, and returned an empty semantic half for the Issues facet forever
|
tasks in it, and return an empty semantic half for the Issues facet forever
|
||||||
with nothing red anywhere (#3128).
|
with nothing red anywhere.
|
||||||
|
|
||||||
They are now generated from one table. These tests pin the property that made
|
So they are generated from one table, and these tests pin the property that
|
||||||
the trap possible, so it cannot come back by a different route.
|
makes the trap possible, so it cannot come back by a different route.
|
||||||
"""
|
"""
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
@@ -104,8 +104,7 @@ def test_the_live_task_kinds_are_all_facets():
|
|||||||
|
|
||||||
def test_non_task_facets_are_the_note_types_and_only_those():
|
def test_non_task_facets_are_the_note_types_and_only_those():
|
||||||
"""Spelled out rather than derived, so adding a kind to `_FACETS` has to
|
"""Spelled out rather than derived, so adding a kind to `_FACETS` has to
|
||||||
be a deliberate edit in two places. `lesson` joined in milestone 385 step
|
be a deliberate edit in two places. `lesson` is non-task on purpose: `is_task` IS `status is not None`,
|
||||||
2 (#3729) and is non-task on purpose: `is_task` IS `status is not None`,
|
|
||||||
so a lesson that acquired a status would stop being a lesson."""
|
so a lesson that acquired a status would stop being a lesson."""
|
||||||
assert set(NON_TASK_FACETS) == {"note", "process", "snippet", "lesson"}
|
assert set(NON_TASK_FACETS) == {"note", "process", "snippet", "lesson"}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user