Constraint Management
Intro
A Constraint is an explicit rule or limit the project must respect: budget
ceilings, latency SLOs, team capacity, compliance requirements, dependency
restrictions. Capturing constraints as first-class entities makes them
referenceable from decisions and visible to trade-off analysis.
Overview
Shape
---
apiVersion: processkit.projectious.work/v1
kind: Constraint
metadata:
id: CONST-p99-latency
created: 2026-04-06T00:00:00Z
spec:
name: p99-latency
description: "API p99 latency must stay under 200ms under normal load."
kind: slo # budget | slo | regulatory | capacity | dependency | policy | other
severity: hard # hard | soft | advisory
measurement: "p99 of request duration over 5-minute windows"
target: "< 200ms"
source: "Customer SLA, signed 2026-01-15"
active: true
---
Workflow
- Pick
CONST-<short-name>.
- Set
kind — budget, SLO, regulatory, capacity, dependency, policy, or other.
- Set
severity: hard (cannot be violated), soft (flagged but overridable),
advisory (informational).
- Describe the
measurement (how you know if it's met) and the target.
- Record the
source — where the constraint came from (contract, regulation,
owner decision).
Using constraints
- DecisionRecords link via
spec.related_constraints when a decision was
shaped by a constraint.
- WorkItems add
labels.constraint when the work exists because of a constraint.
- Processes reference constraints via Bindings (
type: process-constraint)
for scoped constraints.
Gotchas
Agent-specific failure modes — provider-neutral pause-and-self-check items:
- Constraint without a measurable threshold. "Performance must
be good" is not a Constraint; "p99 latency must be under 200ms
on the checkout endpoint" is. Without a threshold, you can't
know whether the Constraint is satisfied.
- Treating Constraints as suggestions. Constraints are
requirements. Decisions and WorkItems should explicitly reference
the relevant CONSTRAINT-ID and confirm compliance, not hand-wave.
If a Constraint is only sometimes true, it's a guideline, not a
Constraint.
- Forgetting the source / owner of the Constraint. Where did
this Constraint come from — legal, finance, oncall, the user's
preference? The source matters because lifting it requires going
back to the source. Always set
source / owner fields.
- Creating Constraints that contradict each other. Two
Constraints saying "ship as fast as possible" and "no production
changes after 5pm" can both be valid, but the conflict must be
noted explicitly so decisions can choose between them. Silent
conflicts produce inconsistent behavior.
- Hand-waving "complies with X" without referencing the
CONSTRAINT-ID. When a workitem or decision satisfies a
Constraint, link the CONSTRAINT-ID explicitly. "We follow GDPR"
with no link is unverifiable.
- Confusing Constraints with Decisions. A Constraint is a
fixed rule the project respects ("budget ≤ $50k"); a Decision is
a choice someone made ("we picked Postgres over MySQL"). If
someone could change it tomorrow without external pressure, it's
a Decision.
- Constraints without expiry or review cadence. Some
Constraints are temporary ("hiring freeze through Q3"). Set a
review date so the Constraint doesn't become permanent by
default.
Full reference
Fields
| Field |
Type |
Notes |
name |
string |
kebab-case identifier |
description |
string |
One sentence |
kind |
enum |
budget / slo / regulatory / capacity / dependency / policy / other |
severity |
enum |
hard / soft / advisory |
measurement |
string |
How the constraint is measured |
target |
string |
The threshold or boundary |
source |
string |
Where the constraint comes from |
active |
bool |
false = no longer in effect |
violations |
list |
Log-style list of known violations (optional, prefer LogEntries) |
Constraint violations
When a hard constraint is violated, write a constraint.violated LogEntry
rather than editing the Constraint file. Repeated violations may motivate a
DecisionRecord to relax the constraint or address the underlying cause.
Retiring a constraint
Set active: false and log constraint.retired. Do not delete — historical
decisions may reference the constraint as part of their rationale.
1---2name: constraint-management-23description: Manage Constraint entities — rules and limits the project must respect (budget, latency SLO, team size, compliance). Use when recording a rule, limit, or boundary that affects decisions — budget ceiling, latency SLO, regulatory requirement, team bandwidth.4---56# Constraint Management78## Intro910A Constraint is an explicit rule or limit the project must respect: budget11ceilings, latency SLOs, team capacity, compliance requirements, dependency12restrictions. Capturing constraints as first-class entities makes them13referenceable from decisions and visible to trade-off analysis.1415## Overview1617### Shape1819```yaml20---21apiVersion: processkit.projectious.work/v122kind: Constraint23metadata:24 id: CONST-p99-latency25 created: 2026-04-06T00:00:00Z26spec:27 name: p99-latency28 description: "API p99 latency must stay under 200ms under normal load."29 kind: slo # budget | slo | regulatory | capacity | dependency | policy | other30 severity: hard # hard | soft | advisory31 measurement: "p99 of request duration over 5-minute windows"32 target: "< 200ms"33 source: "Customer SLA, signed 2026-01-15"34 active: true35---36```3738### Workflow39401. Pick `CONST-<short-name>`.412. Set `kind` — budget, SLO, regulatory, capacity, dependency, policy, or other.423. Set `severity`: `hard` (cannot be violated), `soft` (flagged but overridable),43 `advisory` (informational).444. Describe the `measurement` (how you know if it's met) and the `target`.455. Record the `source` — where the constraint came from (contract, regulation,46 owner decision).4748### Using constraints4950- DecisionRecords link via `spec.related_constraints` when a decision was51 shaped by a constraint.52- WorkItems add `labels.constraint` when the work exists because of a constraint.53- Processes reference constraints via Bindings (`type: process-constraint`)54 for scoped constraints.5556## Gotchas5758Agent-specific failure modes — provider-neutral pause-and-self-check items:5960- **Constraint without a measurable threshold.** "Performance must61 be good" is not a Constraint; "p99 latency must be under 200ms62 on the checkout endpoint" is. Without a threshold, you can't63 know whether the Constraint is satisfied.64- **Treating Constraints as suggestions.** Constraints are65 requirements. Decisions and WorkItems should explicitly reference66 the relevant CONSTRAINT-ID and confirm compliance, not hand-wave.67 If a Constraint is only sometimes true, it's a guideline, not a68 Constraint.69- **Forgetting the source / owner of the Constraint.** Where did70 this Constraint come from — legal, finance, oncall, the user's71 preference? The source matters because lifting it requires going72 back to the source. Always set `source` / `owner` fields.73- **Creating Constraints that contradict each other.** Two74 Constraints saying "ship as fast as possible" and "no production75 changes after 5pm" can both be valid, but the conflict must be76 noted explicitly so decisions can choose between them. Silent77 conflicts produce inconsistent behavior.78- **Hand-waving "complies with X" without referencing the79 CONSTRAINT-ID.** When a workitem or decision satisfies a80 Constraint, link the CONSTRAINT-ID explicitly. "We follow GDPR"81 with no link is unverifiable.82- **Confusing Constraints with Decisions.** A Constraint is a83 fixed rule the project respects ("budget ≤ $50k"); a Decision is84 a choice someone made ("we picked Postgres over MySQL"). If85 someone could change it tomorrow without external pressure, it's86 a Decision.87- **Constraints without expiry or review cadence.** Some88 Constraints are temporary ("hiring freeze through Q3"). Set a89 review date so the Constraint doesn't become permanent by90 default.9192## Full reference9394### Fields9596| Field | Type | Notes |97|---------------|-------------|-----------------------------------------------------------|98| `name` | string | kebab-case identifier |99| `description` | string | One sentence |100| `kind` | enum | `budget` / `slo` / `regulatory` / `capacity` / `dependency` / `policy` / `other` |101| `severity` | enum | `hard` / `soft` / `advisory` |102| `measurement` | string | How the constraint is measured |103| `target` | string | The threshold or boundary |104| `source` | string | Where the constraint comes from |105| `active` | bool | `false` = no longer in effect |106| `violations` | list | Log-style list of known violations (optional, prefer LogEntries) |107108### Constraint violations109110When a hard constraint is violated, write a `constraint.violated` LogEntry111rather than editing the Constraint file. Repeated violations may motivate a112DecisionRecord to relax the constraint or address the underlying cause.113114### Retiring a constraint115116Set `active: false` and log `constraint.retired`. Do not delete — historical117decisions may reference the constraint as part of their rationale.