Projects

A project is one contract: the piece of work you agreed to deliver, and the spec that says what delivering it means.

Apps, pipelines, and databases are things that run. A project is the intent behind them. It holds the spec, it accumulates revisions as that spec changes, and it is where delivery is tracked.

Spec

Every project has a spec: a tree of nodes with a root goal at the top. Each node carries a title and a markdown body. Read it at one of three altitudes:

khotan projects spec <projectId>                    # high: the goal
khotan projects spec <projectId> --altitude medium  # adds phases
khotan projects spec <projectId> --altitude low     # adds items and their mirrored issues

Altitude is how much of the tree you get, not a different document. Use high to see what the project is for, low to see the work beneath it.

The spec is versioned. Every write commits a revision, and a revision records what changed and why:

khotan projects revisions <projectId>          # list revisions
khotan projects revision <projectId> <n>       # one revision, with a diff

The repository writes, the dashboard reads

A project's spec is authored from the repository, through the CLI or /api/v1. The Khotan dashboard shows projects but cannot change them — there is no create button and no spec editor.

This is deliberate. A spec that can be edited in two places drifts, and the version that matters is the one your repository can review, diff, and roll back. Keeping a single write path means the repo is always the truth.

Writes need an API key whose role is owner, admin, or developer. A member key can read but not author.

Changes

Work against a project arrives as an OpenSpec change: a directory under openspec/changes/ holding a proposal, an optional design, a task list, and spec deltas.

openspec
|-- config.yaml                      # names the project this repo delivers
`-- changes
    `-- add-invoice-export
        |-- proposal.md              # why, and what changes
        |-- design.md                # optional; how
        |-- tasks.md                 # the work, as a checklist
        `-- specs
            `-- invoicing
                `-- spec.md          # requirements this change amends

Pushing that directory files it as an issue under the project:

khotan change push add-invoice-export

A change becomes an issue rather than a project of its own, because a project is the contract and a change is one piece of work beneath it. The proposal becomes the issue description, the design and requirements become attached documents, the task list becomes a checklist, and each amended capability becomes a label.

Pushing a change does not rewrite the project spec. Filing the work and changing the contract are separate acts.

Metrics

A spec says what the project is for. Metrics show whether the thing that was built is working: orders processed, hours saved, exceptions caught. The apps a project spans report them over the API — usually once a day, from the cron job they already run — and the project page leads with them.

An app describes what a number means, not how to draw it. Khotan chooses the chart.

Attribute Values What it decides
shape series, breakdown, scatter One value per time bucket; one value per category per bucket; or individual x/y observations
unit count, percent, duration, currency:<ISO 4217>, or a label up to 16 characters How values are formatted. percent is percentage points (45.2 is 45.2%); duration is seconds
goal increase, decrease, neutral Whether a change reads as better or worse. neutral carries no judgement
aggregate sum, average, latest How a range becomes one number: add the values, average them, or take the newest bucket
grain day, hour Bucket size for series and breakdown. A scatter metric has no grain

A scatter metric also names its axes: xLabel, xUnit, yLabel, yUnit.

From those, a summed series draws as bars, an averaged or latest series as a line, a breakdown as a donut beside stacked bars (or the top five categories plus "Other" once there are more than five), and a scatter as a plot with labelled axes. Every summary compares the selected range — 7, 30, or 90 days — with the one before it. A range with no points shows no value, never 0.

Reporting is idempotent

Reports set values; they never add to them. A point is identified by its metric and bucket, by bucket and category for a breakdown, or by the id you give a scatter point. Sending the same report again changes nothing, so a cron job can retry freely, and sending a different value for a bucket corrects it.

A day bucket is a calendar date, YYYY-MM-DD, in the app's own business day — Khotan stores it as given, without converting time zones. An hour bucket is a timestamp with an offset, stored as its UTC hour. Nothing may be more than a day in the future.

A report is validated in full before anything is written: one bad point rejects the whole report, and the error names the metric key and point index. A metric's shape and grain are fixed once it exists; to change them, delete the metric and report it again.

Curation belongs to Khotan

Authors can rename a metric, reorder it, hide it from readers, and mark up to three as headline metrics, which lead the Metrics tab and appear on the project's card. A headline shows a range value and its change, so a scatter metric cannot be one. Reports never override any of that: a renamed metric keeps its name however the app names it next. The name an app reports is only the default until someone renames it.

A project with at least one visible metric opens on the Metrics tab; otherwise it opens on Delivery. Each metric shows when it was last reported, and is marked stale when reports stop — after 48 hours for a day metric, 6 hours for an hour metric, and 7 days for a scatter metric.

Limits

A project holds up to 100 metrics. A report carries up to 50 metrics and 10,000 points, and a breakdown up to 50 categories per bucket. series and breakdown points are kept until the metric is deleted; a scatter metric keeps its newest 5,000 points.

Reporting, curating, and deleting metrics need an owner, admin, or developer key. Every role can read them. See Reporting metrics for a working cron job.

Documentation

A project's Docs tab holds documentation for the people who use what the project delivered: how approvals work, what each role can do, and tutorial videos. Unlike the spec, documentation is written in the dashboard.

Where pages live

Each page is an ordinary context document in the folder Project docs/<project-slug> under Data → Context. Only documents placed directly in that folder appear on the Docs tab. Subfolders are ignored, and moving a page out of the folder removes it from the tab.

Owners, admins, and developers see New page on the Docs tab. It creates an empty page and opens it in the Context editor. Each page on the tab also has an Edit link to the same editor.

Order

Pages appear in title order, and numbers sort by value, so 2 Approvals comes before 10 Troubleshooting. To set an order, start each title with a number.

Version history

Every save in the Context editor records a revision of that page. Select History beside a page to list its revisions and read any earlier one. To restore an earlier revision, use the Context editor.

Download

Share → Download PDF on the Docs tab prints every page into one PDF named <project name> — Documentation. Each page shows its revision and the date it was last updated. Each video is replaced by a caption.

Videos and images

Add media with markdown image syntax. The text in brackets is the caption.

For a video or image uploaded to Files, use the file's id with the khotan-file: scheme. To copy the id, select the file in Data → Files and select ID in the details panel.

![How to approve an invoice](khotan-file:<file-id>)

For a hosted video, paste its YouTube, Vimeo, or Loom URL:

![Approvals walkthrough](https://www.youtube.com/watch?v=dQw4w9WgXcQ)

Files videos stay inside Khotan and are the better choice for anything sensitive. A hosted video sends the reader's IP address to that provider. Other links render as plain links, and raw HTML shows as text.

Who can read and edit

Every member of the organization can read a project's documentation, whatever their role. Only owners, admins, and developers see New page and Edit.

The Context editor itself lets any member edit any context document, including documentation pages. The Docs tab never offers a member an edit control, but it does not stop a member from editing in Context.