workline

package module
v0.9.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 4, 2026 License: MIT Imports: 1 Imported by: 0

README

workline

A software factory for AI-assisted development: each role — committer, documentalist… — does one job with only the context it needs, tools do the mechanical work, and an AI is called only when a decision needs judgement. Everything keeps working without AI.

Status (2026-09-24): used daily on its author's machine;

332 conformance cases green in CI.
Works Not yet
Committer: checks every commit (global git hook) and every commit of a merge request; Claude rewrites refused messages; secrets and forbidden terms in changes and messages (gitleaks), author identity
Documentalist: finds docs whose sources changed (code, sections, other repositories); cuts cascades; size budgets, duplicates, dead links inside the repository and, when gardening, to other sites (lychee), identifiers gone from the code; docs citing a superseded decision; docs not confirmed for too long; derived blocks; Claude judges suspect and stale docs, opens an issue when the code disagrees with a spec, brings product docs up to date at the release, which waits for them, merges a repeated passage and a card too short, condenses a doc over budget, splits a card holding several concepts (checked by a second model), and its patches are checked style
Product owner (beta): reads the open issues against the code; closes a duplicate, its original quoted, up to a cap a run; proposes closing what the code made obsolete; names an issue's code, sets milestones; refines an issue to ready (Need and Validation drafted for a person) and asks its reporter what is missing; imports a roadmap file as issues; a closing undone puts that act back to a person (ADR-0018). Nightly in DomoticsCore's CI splitting into sub-issues, ordering
Reviewer (beta): reviews a branch before the push (workline review) and, opt-in, each merge request; rules on the comments a change adds (a bug's story, an internal code), then lenses (correctness, edge cases, tests) whose quotes the engine finds again; a finding whose cause lies in the change goes to its author, one outside it to an issue; each important one checked by a judge, the independence said; never approves nor patches (ADR-0020) specs, the developer's loop, inline comments
Gates, routing and handoffs, on a machine or judged on a forge and applied later
Work items (local files or forge issues): the check that moves one to ready the rest of the item's life
Forges: GitHub (comments, a comment edited in place, labels and issues tried live), simulated; GitLab tried on gitlab.com; none, kept in the clone (forge: local, workline issues); any other plugged by a command (cmd:, a Forgejo and Gitea sample) — ADR-0016; findings as SARIF in code scanning (this repository's, from CI) and as GitLab's Code Quality report a fork's merge request on GitLab CI; the Forgejo sample untried on a live instance
Agents: Claude Code, and any command as cmd: Codex, Antigravity, OpenCode built in; the generated model grid

Install

You need git. Each release holds the binary for Linux, macOS and Windows; on Linux or macOS, into ~/.local/bin:

os=$(uname -s | tr A-Z a-z); arch=$(uname -m | sed 's/x86_64/amd64/; s/aarch64/arm64/')
curl -fsSL "https://github.com/JN0V/workline/releases/latest/download/workline_${os}_${arch}.tar.gz" | tar -xz -C ~/.local/bin workline
workline version

Or, with Go 1.21 or later, which puts it in $(go env GOPATH)/bin, usually ~/go/bin (add it to your PATH):

go install github.com/JN0V/workline/cmd/workline@latest

To update, run the same command again, into the same place: the global hooks call the binary where it was when they were installed (command -v workline says where). Then set up this machine:

workline setup    # asks, then does: the global hooks, your agent, the tools the roles use

It asks whether to check every commit (the global hooks, below), which agent judges (none, or Claude Code: below), and installs the tools the roles use — gitleaks for secrets, the claude CLI — each with the command it shows first. Run it again to change your answers; --yes takes the defaults. It ends with workline doctor, which says at any time what is set up and what is missing, each with the command that sets it up.

In a repository, workline init has the committer and the documentalist run before each push, and, with an agent, proposes for each doc the code it describes, for you to review and commit: until a doc names its sources, nothing tells when it goes wrong. --review has the reviewer read each merge request's code too; workline review reads a branch's before you push it.

Check every commit on this machine

workline setup does this when you say yes; by hand:

workline hooks install --global     # git's global core.hooksPath now goes through workline
workline hooks uninstall --global   # gives core.hooksPath back as it was

Each global hook hands over to the one that held core.hooksPath before, or, when there was none for that hook, to the repository's own (.githooks/, .git/hooks/): nothing that ran before stops running. A repository opts out with an empty .workline/off file.

Try it in any repository:

git commit --allow-empty -m "AC-3 fix the thing"
# workline committer: block — rewrite the commit message
#   format subject: the subject must read `type(scope): summary`…

Let an AI rewrite what is refused (optional)

By default no AI is used: a refused message is explained, and you rewrite it. To let an AI rewrite it (workline setup installs Claude Code and does step 2; you still log in once):

  1. Install Claude Code, run claude once and log in (a Claude subscription or an API key). workline calls claude -p with that login: it holds no key of its own.

  2. Tell workline to use it, for all your repositories:

    mkdir -p ~/.config/workline
    echo 'ai: claude' >> ~/.config/workline/config.yaml
    

    On macOS the file is ~/Library/Application Support/workline/config.yaml. A project's own .workline/config.yaml wins over yours, and WORKLINE_AI=none git commit … turns the AI off for one commit.

The same commit now goes through, rewritten:

workline committer: pass — message rewritten
workline: the commit goes on with this message instead of yours:
  │ fix: fix the thing
  │
  │ Refs: AC-3

Claude Code is the only agent built in (cmd:<command> runs any other).

Where it runs

On your machine, on a forge, or both: each place fires its own events, and one routing (routing.default.yaml, changed in .workline/config.yaml) says which roles each event runs. A role behaves the same wherever it runs; only the trigger, the agent at hand and the way proposals are applied differ. Setting it up in CI, on GitHub or GitLab, another forge, or none: docs/ci.md.

flowchart LR
  routing[("one routing<br/>.workline/config.yaml")]
  subgraph machine["Your machine"]
    commit["git commit"] -- commit-msg --> committer1["committer"]
    push["git push"] -- pre-push --> local["the project's pre-push line"]
  end
  subgraph forge["Forge: GitHub or GitLab"]
    mr["merge request"] -- merge-request --> judge["judge job<br/>committer, documentalist<br/>no write token but code scanning's"]
    judge -- proposals --> apply["apply job<br/>no AI key"]
    schedule["schedule<br/>a pipeline you add"] -- schedule --> documentalist["documentalist"]
  end
  machine -- git push --> forge
  routing -.-> committer1
  routing -.-> local
  routing -.-> judge
  routing -.-> documentalist
Event Fired by Roles by default
commit-msg your machine: the global git hook committer
pre-push your machine, before the commits leave it, if the project routes it; no question: the review is on the merge request (a push approval, on the terminal, in the editor or in a dialog, if you ask for it) none by default; workline itself: committer, documentalist
merge-request the forge: GitHub Actions (with workline-fork.yml to comment on a fork's) or GitLab CI template committer, documentalist; the reviewer, opt-in (ADR-0020); workline itself: all three
schedule you, or a scheduled pipeline: the GitHub Actions or GitLab CI template, each task a merge request of its own (ADR-0006) documentalist
release wherever you run workline route release, before your release tool (semantic-release…) tags; a release tool's pull request (release-please…) is held as the release on merge-request: workline cuts no releases (ADR-0017) documentalist (docs due at the release)

So the committer checks your messages as you write them, and again on the merge request for those without the hook; the documentalist runs on the forge. On a forge, one job judges with no write token but code scanning's (SARIF upload) and another applies without an AI key (--no-apply, then workline apply).

The CI templates run workline route (merge-request; schedule for the gardening ones), so a project's routing: reaches its CI too.

Take only a part

workline is one binary with its roles inside, and needs nothing but git (and gh to reach GitHub; GitLab is reached through its API). Any existing pipeline can call one role, and leave the rest:

workline run-role committer --event merge-request --ai none \
  --input range=origin/main..HEAD --json    # exit code: 0 pass, 1 block, 2 human, 3 external
workline run-role documentalist --event schedule --ai none --json
workline gate release --json   # a gate declared in .workline/config.yaml: your scanners' SARIF, with thresholds
  • The exit code carries the verdict; --json gives the findings to whatever reads them.
  • The global hook hands over to the hooks that were there before; nothing stops running.
  • --no-apply and workline apply fit a pipeline that keeps tokens apart.
  • A role is a folder (role.yaml, facets, pre and post in any language): a team can replace one facet (.workline/roles/<role>/), or run its own roles with --roles <dir> (role contract).

Not there yet: an agent other than Claude Code built in (--ai cmd:<command> runs any).

Develop

git clone https://github.com/JN0V/workline && cd workline
go build -o ~/.local/bin/workline ./cmd/workline   # or anywhere on your PATH
go test -count=1 ./...    # unit tests and the conformance suite

-count=1 matters: the conformance suite builds the engine itself, which Go's test cache does not see. The evaluation grades the roles with a real agent on real cases, and costs tokens, so it runs only when asked: WORKLINE_EVAL=claude go test -count=1 -timeout 60m ./tests/evaluation/ (docs/spec/conformance.md, "Evaluation").

Documentation

Overview

Package workline ships the built-in roles and the default routing inside the binary, so the engine works from any repository without a checkout of this one.

Index

Constants

This section is empty.

Variables

View Source
var DefaultRouting []byte

DefaultRouting is the line as shipped (routing.default.yaml).

View Source
var Roles embed.FS

Roles holds the roles/ folder as shipped.

Functions

This section is empty.

Types

This section is empty.

Directories

Path Synopsis
cmd
workline command
Command workline runs the roles of the line.
Command workline runs the roles of the line.
internal
agent
Package agent runs the "propose" step: it gives the role's question to a coding agent and collects its proposals in out/intentions.yaml.
Package agent runs the "propose" step: it gives the role's question to a coding agent and collects its proposals in out/intentions.yaml.
backlog
Package backlog decides what becomes of a role's acts on a project's issues (docs/spec/backlog-acts.md): each is checked against the code and the forge, then done, proposed to a person, or dropped.
Package backlog decides what becomes of a role's acts on a project's issues (docs/spec/backlog-acts.md): each is checked against the code and the forge, then done, proposed to a person, or dropped.
builtin/committer
Package committer holds the deterministic checks of the committer role (roles/committer).
Package committer holds the deterministic checks of the committer role (roles/committer).
builtin/documentalist
Package documentalist holds the deterministic part of the documentalist role (roles/documentalist): which docs became suspect because a source changed, which are only pending because the cascade is cut, the hygiene checks (budgets, duplicates, links, identifiers gone from the code), and the judge of the patches the agent proposes for suspect docs.
Package documentalist holds the deterministic part of the documentalist role (roles/documentalist): which docs became suspect because a source changed, which are only pending because the cascade is cut, the hygiene checks (budgets, duplicates, links, identifiers gone from the code), and the judge of the patches the agent proposes for suspect docs.
builtin/productowner
Package productowner holds the deterministic steps of the product owner role (roles/product-owner): pre lists the open issues with what the engine knows of each; the acts the agent proposes are checked when the engine applies them (internal/backlog).
Package productowner holds the deterministic steps of the product owner role (roles/product-owner): pre lists the open issues with what the engine knows of each; the acts the agent proposes are checked when the engine applies them (internal/backlog).
builtin/reviewer
Package reviewer holds the deterministic steps of the reviewer role (roles/reviewer, ADR-0020): the rules no judgement is needed for, the lenses put to the agent as parts of one question, each finding's quotes found again, whether it lies in the change or outside it, the judge's answers read, and the verdict.
Package reviewer holds the deterministic steps of the reviewer role (roles/reviewer, ADR-0020): the rules no judgement is needed for, the lenses put to the agent as parts of one question, each finding's quotes found again, whether it lies in the change or outside it, the judge's answers read, and the verdict.
doctor
Package doctor says what workline needs on this machine and in a repository, what is missing, and the command that sets each one up, as `flutter doctor` and `brew doctor` do.
Package doctor says what workline needs on this machine and in a repository, what is missing, and the command that sets each one up, as `flutter doctor` and `brew doctor` do.
engine
Package engine runs one role once: check, prepare, propose, judge, apply (docs/spec/role-contract.md, "One run").
Package engine runs one role once: check, prepare, propose, judge, apply (docs/spec/role-contract.md, "One run").
forge
Package forge applies what reaches a forge — comments, labels, issues, merge requests — on GitHub, GitLab, or a simulated forge for the tests.
Package forge applies what reaches a forge — comments, labels, issues, merge requests — on GitHub, GitLab, or a simulated forge for the tests.
gate
Package gate runs a gate: a list of checks, each a command whose result is read against thresholds decided in advance (docs/spec/gates.md).
Package gate runs a gate: a list of checks, each a command whose result is read against thresholds decided in advance (docs/spec/gates.md).
gitrange
Package gitrange reads the range of commits a run is given: `base..head`, a single commit, or `head ^base…` when the commits stand on several commits already pushed — a branch that merged main (internal/hooks).
Package gitrange reads the range of commits a run is given: `base..head`, a single commit, or `head ^base…` when the commits stand on several commits already pushed — a branch that merged main (internal/hooks).
hooks
Package hooks installs workline's git hooks.
Package hooks installs workline's git hooks.
intent
Package intent reads the proposals an agent writes and checks them against the closed catalogue (docs/spec/role-contract.md, "Intentions").
Package intent reads the proposals an agent writes and checks them against the closed catalogue (docs/spec/role-contract.md, "Intentions").
judge
Package judge asks an agent one yes-or-no question on what a role produced, at the best independence available from the agent that produced it (ADR-0005): another provider, another model of it, or the same model in a context of its own.
Package judge asks an agent one yes-or-no question on what a role produced, at the best independence available from the agent that produced it (ADR-0005): another provider, another model of it, or the same model in a context of its own.
line
Package line runs the steps routing names for an event, in order, and the handoffs they ask for (docs/spec/routing.md).
Package line runs the steps routing names for an event, in order, and the handoffs they ask for (docs/spec/routing.md).
pathglob
Package pathglob matches repository paths against patterns where `*` stays within one folder and `**` spans any number of folders.
Package pathglob matches repository paths against patterns where `*` stays within one folder and `**` spans any number of folders.
release
Package release says what a project's releases are, for the roles that hold them (ADR-0017): the branches a release tool opens its pull request from, and the last release, one lookup for every reader.
Package release says what a project's releases are, for the roles that hold them (ADR-0017): the branches a release tool opens its pull request from, and the last release, one lookup for every reader.
report
Package report writes findings in the formats forges read: SARIF 2.1.0, for GitHub code scanning (and GitLab Ultimate), and GitLab's Code Quality report, which every GitLab tier shows on a merge request.
Package report writes findings in the formats forges read: SARIF 2.1.0, for GitHub code scanning (and GitLab Ultimate), and GitLab's Code Quality report, which every GitLab tier shows on a merge request.
review
Package review shows a person what the machine proposes, for them to accept or refuse: a page any browser opens, and a question on the terminal.
Package review shows a person what the machine proposes, for them to accept or refuse: a page any browser opens, and a question on the terminal.
role
Package role loads a role's contract (role.yaml) and the project's settings for it, as described in docs/spec/role-contract.md.
Package role loads a role's contract (role.yaml) and the project's settings for it, as described in docs/spec/role-contract.md.
rolefs
Package rolefs extracts the built-in roles to a cache folder, because their pre and post scripts must exist as executable files to be run.
Package rolefs extracts the built-in roles to a cache folder, because their pre and post scripts must exist as executable files to be run.
routing
Package routing reads which roles and gates run on which event, and which handoffs are allowed (docs/spec/routing.md).
Package routing reads which roles and gates run on which event, and which handoffs are allowed (docs/spec/routing.md).
sample
Package sample is the weekly sample of the docs the documentalist vouched for (ADR-0014, step 4): one in ten of the docs whose `checked` it moved in a week, read whole against their sources at the commit `checked` names, by a judge standing apart from the model that vouched (ADR-0005).
Package sample is the weekly sample of the docs the documentalist vouched for (ADR-0014, step 4): one in ten of the docs whose `checked` it moved in a week, read whole against their sources at the commit `checked` names, by a judge standing apart from the model that vouched (ADR-0005).
setup
Package setup sets workline up on a machine, asking what to enable: the global git hooks, the agent, the tools the roles use.
Package setup sets workline up on a machine, asking what to enable: the global git hooks, the agent, the tools the roles use.
tools
Package tools knows the programs workline calls but does not ship — the optional tools a role `uses`, the agents, the forges' CLIs — and how each one is installed, so a missing one is named with the command that installs it on this machine.
Package tools knows the programs workline calls but does not ship — the optional tools a role `uses`, the agents, the forges' CLIs — and how each one is installed, so a missing one is named with the command that installs it on this machine.
verdict
Package verdict reads and writes the verdict a run ends with.
Package verdict reads and writes the verdict a run ends with.
work
Package work reads and moves work items kept as files in .workline/work/, for projects without a forge (docs/spec/routing.md, "Work starts from a clear need").
Package work reads and moves work items kept as files in .workline/work/, for projects without a forge (docs/spec/routing.md, "Work starts from a clear need").
tests
evaluation/summary command
Summary reads results.tsv and prints, per case, models, effort and judge, how many runs there were, the pass rate (the share of runs earning every point), the mean score and its range, and what a run used: one run says little, since a model answers differently from one run to the next, and a best run hides the others (ADR-0014).
Summary reads results.tsv and prints, per case, models, effort and judge, how many runs there were, the pass rate (the share of runs earning every point), the mean score and its range, and what a run used: one run says little, since a model answers differently from one run to the next, and a best run hides the others (ADR-0014).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL