Documentation
¶
Overview ¶
Package deadend answers one question: has this been tried before?
Every other retrieval path here is pull — an agent asks, and the store answers. This one is push. The agent is about to propose something, and the useful move is to interrupt: *you tried that in March, here is why it did not work, here is who found out.*
The distinction matters more than it looks. `resume` gives an arriving agent the last checkpoint, which covers the approach ruled out yesterday on the project it is already working on. It does nothing for the approach ruled out in March, on a project nobody mentioned, by an agent that no longer exists. That knowledge is in the vault — it just has no way of reaching the moment it would have been useful, because nobody thinks to search for the thing they are about to suggest.
So the corpus is every dead end recorded anywhere in the vault, and the query is the proposal itself. This is also the part of the system that cannot be copied: the mechanism is a morning's work, and the two years of accumulated "we tried that" is not.
What counts as a dead end ¶
Checkpoints carry a Failed list, which is the curated corpus — someone chose to write those down as ruled out. Working notes are messier and matter anyway: an agent killed before it could check in leaves its findings only there, and "the audio team vetoed dropping the second mic" is exactly the kind of thing that dies with the session. Those are admitted when they read as a failure, by an explicit marker rather than by sentiment, because a note wrongly filed as a dead end will stop work that should have happened.
Index ¶
- func FirstShowing(db *sql.DB, sessionID, rel string) (bool, error)
- func MarkDrift(hits []Ruling, dir string)
- func Matches(lexical, semantic float64, embedded bool) bool
- func PossiblySuperseded(scope Scope, when int64, now time.Time) bool
- func Render(proposed string, hits []Ruling) string
- func SemanticSkipped(err error) string
- func Shown(db *sql.DB, sessionID, rel string) (bool, error)
- func Similarity(a, b []float32) (float64, bool)
- func Tags(r Record) string
- func UnplacedToolchain(failed []string) int
- type Action
- type Degree
- type Layer
- type Record
- type Ruling
- func AtPath(db *sql.DB, vaultDir, project, rel string) ([]Ruling, error)
- func Check(vaultDir string, db *sql.DB, p *provider.Provider, ...) ([]Ruling, error)
- func CheckNoting(vaultDir string, db *sql.DB, p *provider.Provider, ...) (hits []Ruling, semanticErr error, err error)
- func Collect(vaultDir string, db *sql.DB, project string) ([]Ruling, error)
- type Scope
- type Source
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func FirstShowing ¶ added in v0.5.2
FirstShowing reports whether this is the first time in session that a ruling was shown for rel, and records that it now has been. One line per file per session: an agent editing reader.go twenty times needs the ruling once, and a line repeated on every edit is read as noise and then not read at all.
A cursor, not a record — losing it shows a ruling once more. An empty session cannot be told apart from any other, so it always counts as a first showing.
func MarkDrift ¶ added in v0.5.1
MarkDrift notes, on each ruling, whether the files it names have changed in the repository at dir since it was recorded. Only the rulings about to be shown are measured: it costs a git call per named file.
func Matches ¶ added in v0.5.0
Matches is the rule both halves of before_you_try apply to a candidate: dead ends here, procedures in internal/procedure, so a proposal is not judged one way against what failed and another against what worked. embedded is whether semantic is a measurement at all. A ruling the embedder never reached, or one whose vector it cannot be compared with, has no second opinion to give, and lexical alone is what the check was before embeddings; it stays that.
func PossiblySuperseded ¶
PossiblySuperseded reports whether a version-bound ruling is old enough that the dependency it names may have moved since. It is a time-based guess, not a check against an actual manifest — Logos has no dependency graph to consult — so it is always surfaced as a caveat, never a silent drop and never a hard "this no longer applies".
func Render ¶
Render writes the interruption.
The wording is doing real work here, and it is not decoration. This output lands in front of a model that is about to propose something, and there are two ways to get it wrong. Too soft — "you may wish to consider" — and it gets skimmed past. Too hard — "this will not work" — and it stops an agent from retrying something that deserves a second look, which is worse, because a dead end recorded a year ago under different constraints is evidence, not a verdict.
So the shape is: state plainly that it was tried, say by whom and when, and hand the decision back. The agent is told to say out loud that it knows, because the visible version of this — "we tried that in March, the drop test failed at 1.2m" — is the difference between a memory that stores and a memory that helps.
func SemanticSkipped ¶ added in v0.4.4
SemanticSkipped is the line that says the check ran on wording alone, or "" when the semantic arm covered everything.
func Shown ¶ added in v0.5.2
Shown reports whether session has already been shown a ruling for rel, without recording anything: the edit hook asks before it does the work of a line, and records only once the line is printed.
func Similarity ¶ added in v0.5.0
Similarity is the cosine of two embeddings, and whether they could be compared at all. A pair of different sizes — the runtime changed under the same model name and the cache still holds the old vectors — has no score, and reporting it as zero made it a confident "unrelated".
func Tags ¶ added in v0.4.5
Tags is the typed vocabulary of one ruling, rendered for a reader: the layer it lives at, how far it travels, how hard the evidence is, what to do about it. Exported because the handoff path needs it too — a ruling that crosses to another tool untagged is the one that gets re-run, and until it was rendered there this vocabulary only ever reached before_you_try.
func UnplacedToolchain ¶ added in v0.4.10
UnplacedToolchain counts the failed entries that name a tool, a package manager or PATH and carry no layer. "brain binary not on PATH" is about the machine that hit it, and in plain prose it reaches an agent on another toolchain reading like a fact about the code, which that agent then spends its reasoning placing. Guessing the layer here would be worse than leaving it out: a wrong "environment" hides a dead end that does apply. So the count only lets the checkpoint receipt ask the writer, who knows. An entry the writer already placed, at any layer, is not second-guessed.
Types ¶
type Action ¶
type Action string
Action is what the person who found this out recommends doing with that knowledge, distinct from Alternative, which is what to do instead.
const ( ActionRetry Action = "retry" // worth trying again — conditions may have changed ActionChangeMethod Action = "change-method" // the goal is fine, this route to it is not ActionNarrowScope Action = "narrow-scope" // works, but only for a smaller case than proposed ActionAbandon Action = "abandon" // the goal itself should be dropped )
type Degree ¶
type Degree string
Degree says how hard the evidence is. "Failed" covers everything from "the spec forbids it" to "it flaked once and nobody chased why", and those deserve different weight from a reader deciding whether to retry.
const ( DegreeContradicted Degree = "contradicted" // demonstrated not to work DegreePartial Degree = "partial" // worked for part of the case, not all of it DegreeInconclusive Degree = "inconclusive" // tried, no clear result either way DegreeUnstable Degree = "unstable" // worked sometimes, not reliably )
type Layer ¶
type Layer string
Layer names where in the stack a dead end lives. It is the first question anyone re-attempting the approach actually needs answered: a ruling about a dependency's behaviour transfers across projects that share the dependency; one about this project's design does not transfer at all.
const ( LayerImplementation Layer = "implementation" LayerDesign Layer = "design" LayerEnvironment Layer = "environment" LayerDependency Layer = "dependency" LayerRequirement Layer = "requirement" // LayerUnclassified is not a fifth peer alongside the five above — it is // what an ordinary, free-prose Failed entry gets, so every checkpoint // written before this schema existed keeps reading exactly as it did. LayerUnclassified Layer = "unclassified" )
type Record ¶
type Record struct {
Route string
Observation string
Layer Layer
Scope Scope
Degree Degree
Action Action
Alternative string
Raw string
// Truncated is set when the source entry ran past recordCap and was cut
// to fit. The cut is visible here rather than silent, per the invariant
// that a lossy operation says so.
Truncated bool
}
Record is one dead end, typed. Route and Observation are required for a record to count as typed at all; Layer/Scope/Degree/Action/Alternative are each optional and simply absent from Render when unset.
Raw is always populated — the on-disk form, exactly as recorded — because a hand-edited or partially-typed entry should still be readable rather than silently losing whatever did not parse.
func ParseRecord ¶
ParseRecord turns one Failed or working-note entry into a typed Record.
The wire format is unchanged — Failed is still `[]string`, and a record is still one bullet, one line — so the shape lives entirely in the text: a line of `key: value` segments joined by " | ", anchored on a `route:` key. Anything else, including every Failed entry ever written before this existed, is not that shape and comes back as free prose with Layer: unclassified — the same record type, so a caller never has to branch on which kind of entry it got.
type Ruling ¶
type Ruling struct {
Text string `json:"text"`
Project string `json:"project"`
Agent string `json:"agent"`
When int64 `json:"when"`
Slug string `json:"slug,omitempty"`
Source Source `json:"source"`
Score float64 `json:"score"`
// Elsewhere is true when this was ruled out on a different project than the
// one being asked about. Still worth saying, and worth flagging: what failed
// on other hardware may not fail here, and presenting it as settled would be
// the same overreach this package exists to prevent.
Elsewhere bool `json:"elsewhere"`
// Record is Text, typed — Layer: unclassified and a Route equal to Text
// itself for every ruling recorded before this schema existed. Kept
// alongside Text rather than replacing it so nothing here has to branch on
// which kind of entry it got.
Record Record `json:"record"`
// Stale marks a version-bound ruling old enough that the dependency it
// names may have moved since — see PossiblySuperseded. Never grounds for
// dropping the ruling, only for saying so.
Stale bool `json:"stale,omitempty"`
// Commit is the repository's HEAD when the checkpoint holding this was
// written. Empty for a working note, which records no repository.
Commit string `json:"commit,omitempty"`
// Drift is set when the files this ruling names have changed since
// Commit — see MarkDrift. Like Stale, a reason to say so, never to drop it.
Drift *gitstate.Drift `json:"drift,omitempty"`
}
A Ruling is something already tried that did not work.
func AtPath ¶ added in v0.5.2
AtPath returns the checkpoint rulings in project, and in its worktree scopes, that name the repository file rel, newest first.
rel is matched as written ("internal/parse/reader.go") and by its base name for a ruling that only said "reader.go". A ruling that spelled out a different directory names a different file and is not returned.
Working notes are not consulted: a note ruled out with `tried --ruled-out` reaches before_you_try and resume, and reading them here would put the notes table on every edit for the rarest kind of ruling.
func Check ¶
func Check(vaultDir string, db *sql.DB, p *provider.Provider, embedModel, proposed, project string, k int) ([]Ruling, error)
Check returns the recorded dead ends bearing on a proposed approach, best match first.
Two ways to match, each needing a little of the other near its floor (see cosineAlone). Lexical containment catches a proposal restating the original almost word for word, which is the common case when an agent has read the project note and is working from the same vocabulary. Embedding similarity catches the opposite case — the same idea in different words — and is what makes this useful across projects, where the vocabulary has no reason to line up. With no embedder available the lexical arm still works, so this degrades rather than disappearing.
func CheckNoting ¶ added in v0.4.4
func CheckNoting(vaultDir string, db *sql.DB, p *provider.Provider, embedModel, proposed, project string, k int) (hits []Ruling, semanticErr error, err error)
CheckNoting is Check, also returning why the semantic arm did not cover the whole corpus, if it did not. Degrading to lexical is fine; doing it silently made a weaker check read exactly like a full one that found nothing.
type Scope ¶
type Scope string
Scope says how far a ruling travels. The distinction Check already draws between "this project" and "elsewhere" is about where a ruling was made; Scope is about where it still applies, which is a different question — a version-bound ruling may no longer hold even on the project that made it.
const ( ScopeLocal Scope = "local" // true of this codebase's particular choices, not the approach in general ScopeVersionBound Scope = "version-bound" // true against a dependency version that can move out from under it ScopeGeneral Scope = "general" // true of the approach itself, not tied to a version or a local choice )