certainty-units
v0.3.0
Published
Certainty scoring for project work items — connects to Linear, Jira, Notion, GitHub Issues
Maintainers
Readme
certainty-units
Free, open-source certainty scoring for project work items. Connects to GitHub Issues, Linear, Jira, Notion (Monday + ClickUp coming). Outputs a static HTML dashboard + Markdown report — zero server required.
npx certainty-units syncTeams that track success by counting effort (points, tickets closed) see how much is moving — certainty-units shows how sure you are about what's moving, and what would make you surer.
Quick start
Fastest path — score any public GitHub repo, no API key needed:
npx certainty-units init
# edit certainty.config.yaml:
# source: github
# github:
# repo: your-org/your-repo
npx certainty-units sync
# Output: cu-report.html (open in any browser)For Linear / Jira / Notion, set the API key env var and run the same command:
LINEAR_API_KEY=lin_api_xxx npx certainty-units syncEvery sync prints instant insights in the terminal:
278 items · avg certainty 56%
high 68 medium 116 low 54 uncertain 40
Since last sync (2026-06-27): avg 54% → 56% ▲ +2 · 12 new items
▼ 45 → 20 ENG-142 Add SSO support
▲ 30 → 80 ENG-98 Migrate billing
Least certain open items:
5% #1099 always_allow permission policy not honored
missing: validation +40, workflow +20, discussion +15What it scores
Each work item gets a Certainty Score (0–100):
| Signal | Max points | How it maps |
|--------|-----------|-------------|
| Validation status | 40 | validated → 40, assumed → 10 |
| Workflow progress | 20 | done → 20, review → 15, in_progress → 10 |
| Discussion | up to 15 | 5 pts per comment — undebated items hide risk |
| Acceptance criteria | 10 | found on the item (see below) |
| CU tier set | 10 | basic / intermediate / advanced |
| Evidence / description | 5 | non-empty description |
Scores map to levels: high (≥80) · medium (≥50) · low (≥20) · uncertain (<20)
Every score is auditable: hover the score bar in the HTML report for the per-signal
breakdown, and cu-data.json (via --json) includes certainty_breakdown per item.
Feed it real signals
The score is only as honest as its inputs, so the adapters read signals your team already produces:
- Acceptance criteria are detected automatically from an
## Acceptance Criteriaheading (or**Acceptance Criteria**, or anAcceptance criteria:line) in the item description, or from a markdown checklist (- [ ] …). In Notion, use anAcceptance Criteriacolumn. - Validation labels override workflow-derived validation. Label an item
validated,assumed, orneeds-clarification(Notion: tags) to record validation explicitly instead of letting "closed" imply "validated". - CU tier labels —
cu:basic,cu:intermediate,cu:advanced— set the tier directly on any tool that has labels.
From score to action
The score is the diagnosis; next is the prescription:
npx certainty-units next # this week's certainty to-do list
npx certainty-units next --create-issues # file each plan as a follow-up issuenext takes your least certain open items and prints concrete, assignable actions
(validate this assumption, write acceptance criteria for that, size this one).
--create-issues files them straight into your repo as checklist issues
(GitHub source, needs a token with write access) and skips items that already
have an open follow-up.
Track movement, not just state
Each sync snapshots per-item scores to .cu-history.json and the next sync reports
what moved: average trend, biggest drops and rises, new items. Commit the file (or
cache it in CI) to keep the trail. Disable with --no-history.
When delivered CU velocity rises while average certainty stays flat or falls, the sync flags certainty debt: output is accelerating faster than validation. This is the number to watch on AI-augmented teams.
Use it as a CI gate
certainty-units sync --fail-below 50 # exit 1 if avg certainty < 50%Put it in front of a sprint kickoff or release train to block on too much uncertainty.
Post to Slack
certainty-units sync --slack-webhook https://hooks.slack.com/services/…Posts the summary and least-certain items to a channel (or set output.slackWebhook
in the config).
Supported sources
| Tool | Status | Auth | |------|--------|------| | GitHub Issues | ✅ | none for public repos, token for private | | Linear | ✅ | API key | | Jira | ✅ | API token | | Notion | ✅ | API key | | Monday.com | 🚧 coming | | | ClickUp | 🚧 coming | |
Config reference
project: My Project
source: github # github | linear | jira | notion
github:
repo: owner/name
token: ${GITHUB_TOKEN} # optional for public repos
# state: all # all | open | closed
# limit: 500 # most recently updated issues to fetch
linear:
apiKey: ${LINEAR_API_KEY} # env var expansion supported
teamId: your-team-id
jira:
host: yourteam.atlassian.net
email: [email protected]
apiToken: ${JIRA_API_TOKEN}
projectKey: MYPROJECT
notion:
apiKey: ${NOTION_API_KEY}
databaseId: your-database-id
output:
html: cu-report.html
markdown: cu-report.md # optional
history: .cu-history.json # optional — score snapshots for deltas
# slackWebhook: https://hooks.slack.com/services/…Field mapping
Every tool uses different status names. Override the defaults:
linear:
apiKey: ${LINEAR_API_KEY}
teamId: abc123
fieldMap:
validation_status:
field: state.type # dot-path into the Linear issue object
map:
completed: validated
started: assumed
cu_tier:
field: estimate
map:
1: basic
3: intermediate
8: advancedAutomate with GitHub Actions
- Copy examples/cu-report.yml to
.github/workflows/in your repo - Add your API key as a repo secret (
LINEAR_API_KEY, or nothing for public GitHub repos) - Enable GitHub Pages → the report publishes every Monday, with week-over-week deltas
License
MIT — free to use, modify, and embed. "Propozel" and "Certainty Units" are trademarks; the license covers the code, not the branding (see NOTICE).
Built on the Certainty Units methodology.
