From a RAG CLI to an Execution Harness

In short. Talos began as LOQ-J, a local command-line tool for retrieval over documents. Over thirteen months it became what its README calls "a broader local workspace assistant and execution harness", with a runtime that decides what a model may do. The history is a sequence of decisions, several of them reversals, and the removals say as much as the additions.

LOQ-J to Talos, a timeline In order. LOQ-J v0.1.0, a local retrieval command line. A 172-day gap between commits. Work resumes with 37 architecture files. Renamed Talos with tools, writes and approval. Verifier, contract, trace, permissions and checkpoints. The llama.cpp backend for a required tool choice. No generic shell tool, typed command profiles. Decomposition stopped. A trust audit opens seven findings. The tree is cleaned and the wiki and tickets archived. The v0.10.8 tag, and hours later the install guidance rewritten for an unsigned developer beta. Model qualification of twelve candidates. Ollama removed on the development branch. LOQ-J TO TALOS, NOT TO SCALE LOQ-J v0.1.0 a local retrieval CLI a 172-day gap between commits work resumes 37 architecture files renamed Talos tools, writes, approval verifier, contract, trace permissions, checkpoints llama.cpp backend a required tool choice no generic shell tool typed command profiles decomposition stopped diminishing returns trust audit seven findings opened tree cleaned wiki and tickets archived v0.10.8 tag install guidance rewritten model qualification twelve candidates Ollama removed on the development branch added removed or archived decision or milestone
Figure 1. LOQ-J, the gap with no recorded commits, and the Talos decisions in order.

The starting point

The first commit reads "initial import of LOQ-J v0.1.0". LOQ-J stood for Local-Only Java. It arrived as 57 files, with a picocli command line, Lucene 10 with BM25 and vector search over local documents, a SQLite cache, Ollama for chat and embeddings with qwen3:8b and bge-m3 as defaults, a JavaFX first-run wizard that installed Ollama through winget, and a jpackage target for a Windows installer.

Its default configuration also carried a command allowlist of twenty programs, from git and gradle to powershell, cmd and bash, with a blocklist beside it. No Java code read either list, and both were gone from the default configuration within three days.

The first month added BM25F field boosts, gating for the REPL's own commands, a redactor, a sandbox, a reworked network policy and a service interface for several engines, of which only Ollama worked. That period ended a month after the first commit, and the next commit came 172 days later.

Decision one. Tools first, checks second

Work resumed with a modernization plan that reserved a seam for tools. The next day 37 commits added 37 architecture files, two overlapping sets with 22 distinct file names. Among their decisions were command line first, multi-agent orchestration not the primary driver, and approval as a core runtime concept, "not optional glue added later."

A week after work resumed, the project was renamed Talos, a day after a short-lived rename to Loqs. The same day the model first called tools, read_file, grep and retrieve, then write_file and edit_file, with an approval gate for writes. The rename commit records 802 passing tests.

Cost. For nearly three weeks Talos could write files after approval but without a verifier or a task contract. What followed. Then, in five days, came a static task verifier, a task contract, a local turn trace, declarative allow, ask and deny permissions, and a checkpoint before every approved change. Versions 0.9.1 to 0.9.8 cover those days.

Decision two. An engine that can require a tool call

A few days later a managed llama.cpp backend arrived, after a design written the same day moved the default away from Ollama. The design gives the reason. It found that Ollama's documented native chat shape "does not expose a required tool-choice control", and a turn that must act needs to require a tool call. It also sets a limit that held from then on. Switching engines "is still not a substitute for Talos runtime control."

Cost. Two backends were maintained side by side for five months, and request controls such as required tool choice and sampling settings were built around the llama.cpp path. What followed. Ollama left the default path with 0.10.6. Later the development branch removed it entirely, deleting 4,401 lines. That last step is recorded only as an owner's rule. A llama.cpp engine had been a stub in LOQ-J and was deleted as dead code before it returned as the real backend.

Decision three. No generic shell tool

Two days later the command execution design stated its first rule, "Do not add a generic shell tool.", and cited OWASP's entry on excessive agency. Typed command profiles and a Gradle command tool followed. Later, workspace-declared profiles gained a trust store keyed by a content hash.

Cost. The built-in command set is five Gradle tasks, and anything else needs a declared, pinned profile. What followed. Commands became narrow and named, while the programs they launch still run with the user's permissions. A profile is not a sandbox, and the approval request for a command states that the host network is not isolated.

Decision four. Stop decomposing

Version 0.10.0 was declared a beta candidate, with ArchUnit architecture guards. Five candidates followed in three days, the last four with machine-checkable gate ledgers. A full-screen terminal interface was considered and rejected in favor of inline JLine.

A structural decomposition of the turn executor and the tool loop ended by an explicit decision, recorded as "diminishing returns" and "the risk of over-fragmenting". Cost. The turn executor was about 2,735 lines at the stop. It has grown to 3,444 since and is the second largest main class in the current code.

Decision five. Narrow the claims

The trust track began with an internal audit of the project's own trust claims, which found many of them broader than the code. The first fix was an honesty pass on the documentation, which made the docs state current limits instead of intended ones, under the line "A documented limitation is not an overclaim." Code fixes followed. A full end-to-end audit eight days later found that no hard-fail gate fired. It also opened seven follow-up findings. One of them, rated high, covered fabricated read and command claims that sit outside the mutation guard.

What followed. A guard for the fabricated git-status case landed within a day, and later work broadened it to other recognized command-output shapes. The README still states that the deterministic correction is strongest for file-mutation turns, and that arbitrary command claims and broad read claims are not completely covered.

Decision six. A living wiki, for 22 days

A living wiki was added, with committed pages with evidence frontmatter, a structural lint that ran with the unit tests, a liveness lint against a generated architecture report, and a close gate run by the candidate cut script. It was then archived. The archiving commit reads "clean up docs before release", and the work-cycle README it added says wiki state is "not part of the public repository contract".

Decision seven. Clean the tree and publish

The same day a single commit changed 1,115 files and removed 168,074 lines from the tracked tree. Tickets, reports, research notes, the wiki and 25 numbered architecture documents moved to a local archive, a 1,207-line guidance file left the tracked tree, and four short architecture documents replaced the set. A hygiene test now fails the build if the work-cycle runbooks cite archived tickets or the old wiki gate.

The v0.10.8 tag followed the next day, and the README in the tagged tree still called the Windows public beta signed-only. Hours later a commit on the development branch rewrote the install guidance. According to the current README, the 0.10.8 developer beta is published as GitHub Release assets for Windows x64 and Ubuntu or WSL x64, and the Windows assets are unsigned and need an explicit flag to install. A signed release and a winget package are not live.

Cost. The removed history is still in git and in a local archive, but no longer in the tree a reader browses. What followed. The documents that remain are short, and tests pin their load-bearing claims.

Decision eight. A catalog with evidence per profile

A two-model rule governs live audits, and the release-candidate runbook still requires it when a release claim depends on model behavior. Three experimental profiles for two more models were then added beside the two accepted ones. Over six days a deterministic qualification protocol took twelve open-weight models through preflight, admission or full 72-trial campaigns. Six completed a full campaign, and five new experimental profiles joined the catalog.

Cost. The two accepted profiles still rest on an earlier evidence record. GPT-OSS 20B, one of them, scored in the experimental tier on its own 72-trial run and keeps its accepted label on that earlier record. The raw qualification packets stay local. What followed. Every selectable profile in the catalog must name its evidence, either a qualification packet or an earlier record, and the catalog refuses to load one that does not.

Built, then taken out

ItemBuiltTaken out
Command allowlist in config, never read by codeLOQ-Jwithin three days
JavaFX first-run wizard installing OllamaLOQ-Jreplaced when work resumed, dependency removed later
rag+memory modeLOQ-Jdeprecated, deleted when work resumed
llama.cpp stub engineLOQ-Jdeleted as dead code, then a real backend
XML tool-call protocolTalosretired from prompts a week later, parser kept
Numbered architecture documentsTalosreplaced by four documents in the cleanup
Living wiki gateTalosarchived after 22 days
Ticket systemTalosout of the tree in the cleanup, kept locally for a time, then local batch records
Ollama backendLOQ-Joff the default path with 0.10.6, removed on the development branch

web mode was reserved in LOQ-J, never implemented, and is still registered as an unselectable stub.

Most of these removals made a claim smaller. An allowlist implied a shell. A wiki implied a maintained source of truth. What replaced each one is narrower, typed profiles and a short document set. The model catalog went the other way, wider in membership and narrower in what each entry claims.

The shape in numbers

PointMain Java linesTest Java lines
LOQ-J v0.1.02,765164
Rename to Talos13,2339,008
0.9.024,99031,073
v0.10.8 tag100,201128,929
Current code193,597295,319

Counts are physical lines, blanks and comments included. Test code passed main code by 0.9.0 and has stayed ahead. Commit counts say less than they seem to. Large commits became common after the 0.10.8 tag, and later the messages changed from conventional prefixes to plain sentences, so a quiet month in commits is not a quiet month in work.

What converged

From the first Talos design onward, the recorded decisions put authority in the runtime rather than in the model. The three largest later model decisions, the llama.cpp backend, the required tool choice and the qualification protocol, made the model easier to check rather than easier to trust.

There was no generic shell tool. A command allowlist sat in the very first configuration file and never reached code, and when command execution arrived, its design's first rule was the sentence "Do not add a generic shell tool".

The documents shrank in the cleanup while the code kept growing, and the claims in them got narrower. No release has followed 0.10.8. The latest records end with lines such as "Release readiness remains unestablished."