create-pmos 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +30 -0
  3. package/bin/create-pmos.js +103 -0
  4. package/package.json +26 -0
  5. package/payload/AGENTS.md +83 -0
  6. package/payload/KIT-VERSION +3 -0
  7. package/payload/README.md +56 -0
  8. package/payload/okf/core/concepts/agent-harness.md +83 -0
  9. package/payload/okf/core/concepts/control-plane.md +61 -0
  10. package/payload/okf/core/concepts/design-loop.md +117 -0
  11. package/payload/okf/core/concepts/eval-driven-pm.md +71 -0
  12. package/payload/okf/core/concepts/index.md +17 -0
  13. package/payload/okf/core/concepts/log.md +6 -0
  14. package/payload/okf/core/concepts/okf-governance.md +159 -0
  15. package/payload/okf/core/concepts/okr-anti-optimism.md +54 -0
  16. package/payload/okf/core/concepts/okr-tree.md +67 -0
  17. package/payload/okf/core/concepts/output-eval.md +81 -0
  18. package/payload/okf/core/concepts/pm-identity.md +68 -0
  19. package/payload/okf/core/concepts/product-slug-convention.md +64 -0
  20. package/payload/okf/core/concepts/sdlc-loop.md +69 -0
  21. package/payload/okf/core/concepts/self-refining-harness.md +77 -0
  22. package/payload/okf/core/concepts/watermelon-flag.md +66 -0
  23. package/payload/okf/core/templates/design-brief-template.md +84 -0
  24. package/payload/okf/core/templates/eval-rubric-template.md +95 -0
  25. package/payload/okf/core/templates/index.md +8 -0
  26. package/payload/okf/core/templates/log.md +9 -0
  27. package/payload/okf/core/templates/prd-template.md +75 -0
  28. package/payload/okf/product/.gitkeep +0 -0
  29. package/payload/planning/evals/agent-run-eval-rubric.md +46 -0
  30. package/payload/planning/evals/check_rubrics.py +108 -0
  31. package/payload/planning/evals/eval-calibration.md +4 -0
  32. package/payload/planning/okrs/.gitkeep +0 -0
  33. package/payload/planning/prd/.gitkeep +0 -0
  34. package/payload/scripts/gate-initiative.sh +56 -0
  35. package/payload/scripts/kit-update.sh +16 -0
  36. package/payload/scripts/metrics.py +99 -0
  37. package/payload/skills/SKILL-FORMAT.md +89 -0
  38. package/payload/skills/eval-rubric.skill +122 -0
  39. package/payload/skills/evaluator.skill +82 -0
  40. package/payload/skills/ingest-repo.skill +117 -0
  41. package/payload/skills/okr.skill +68 -0
  42. package/payload/skills/prd.skill +80 -0
  43. package/payload/state/acceptances.jsonl +0 -0
  44. package/payload/state/discoveries.md +2 -0
  45. package/payload/state/evals.jsonl +0 -0
  46. package/payload/state/initiatives/.gitkeep +0 -0
  47. package/payload/state/runs.jsonl +0 -0
  48. package/payload/templates/agent-run-eval-rubric.md +46 -0
  49. package/payload/templates/pmos-gate.yml +29 -0
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env bash
2
+ # PMOS portable kit — file-backed Initiative Gate (D54). Fail-closed enforcement of the loop,
3
+ # same contract as the hosted gate but reading pmos/state/ instead of a database. A PR is
4
+ # "anchored" only when:
5
+ # 1. the branch is initiative/<id> (or the PR body declares 'Initiative: <id>'), and
6
+ # 2. pmos/state/initiatives/<id>.md EXISTS in the checkout, and
7
+ # 3. its prd_path is set and that file exists, and
8
+ # 4. its rubric_path is set and that file exists.
9
+ # Escape hatch (explicit, logged): the `no-initiative` label skips the gate.
10
+ # Inputs via env: HEAD_REF, PR_BODY, PR_LABELS. Optional: KIT_ROOT (default: pmos).
11
+ set -euo pipefail
12
+
13
+ KIT_ROOT="${KIT_ROOT:-pmos}"
14
+ fail() { echo "::error::initiative-gate: $*"; echo "❌ initiative gate FAILED — $*"; exit 1; }
15
+ note() { echo "::notice::initiative-gate: $*"; echo "ℹ️ $*"; }
16
+
17
+ # ---- escape hatch (genuine chores) — exact label, space-bounded ------------
18
+ case " ${PR_LABELS:-} " in
19
+ *" no-initiative "*) note "PR labelled 'no-initiative' — gate skipped (sanctioned chore path)."; exit 0 ;;
20
+ esac
21
+
22
+ # ---- fail closed if the state layer is missing ------------------------------
23
+ [ -d "$KIT_ROOT/state/initiatives" ] || fail "$KIT_ROOT/state/initiatives/ not found — the kit state layer is required and the gate fails closed (a hard gate must not be silently disableable)."
24
+
25
+ # ---- derive the initiative id ----------------------------------------------
26
+ id=""
27
+ case "${HEAD_REF:-}" in
28
+ initiative/*) id="${HEAD_REF#initiative/}" ;;
29
+ esac
30
+ if [ -z "$id" ]; then
31
+ # `|| true`: a no-match grep exits 1, which under set -e would abort BEFORE the fail() guidance
32
+ # below ever prints (silent exit 1 on the most common failure path).
33
+ id="$(printf '%s' "${PR_BODY:-}" | { grep -ioE 'Initiative:[[:space:]]*[A-Za-z0-9._-]+' || true; } | head -1 | sed -E 's/.*:[[:space:]]*//')"
34
+ fi
35
+ [ -n "$id" ] || fail "Not anchored. Name the branch 'initiative/<id>' or add 'Initiative: <id>' to the PR body, or label the PR 'no-initiative' for a genuine chore. See $KIT_ROOT/AGENTS.md."
36
+
37
+ # ---- validate the id (also guards the path interpolation below) -------------
38
+ printf '%s' "$id" | grep -qE '^[a-z0-9][a-z0-9._-]*$' || fail "Initiative id '$id' is malformed (expected ^[a-z0-9][a-z0-9._-]*$)."
39
+
40
+ # ---- read the initiative file ------------------------------------------------
41
+ init_file="$KIT_ROOT/state/initiatives/$id.md"
42
+ [ -f "$init_file" ] || fail "No initiative file at $init_file. Create it first — an initiative must exist before its PR. This is the loop rule the gate enforces."
43
+
44
+ frontval() { # frontval <key> — first 'key: value' line in the file, value trimmed.
45
+ # `|| true`: an absent key must fall through to the explicit fail() below, not abort silently.
46
+ { grep -m1 -E "^$1:[[:space:]]*" "$init_file" || true; } | sed -E "s/^$1:[[:space:]]*//" | tr -d '\r' | sed -E 's/[[:space:]]+$//'
47
+ }
48
+ prd="$(frontval prd_path)"
49
+ rubric="$(frontval rubric_path)"
50
+
51
+ [ -n "$prd" ] || fail "initiative '$id' has no prd_path in $init_file. Author a PRD and set prd_path (eval-first: PRD + rubric before build)."
52
+ [ -f "$prd" ] || fail "prd_path '$prd' (from $init_file) does not exist in the repo."
53
+ [ -n "$rubric" ] || fail "initiative '$id' has no rubric_path in $init_file. Author an eval rubric and set rubric_path."
54
+ [ -f "$rubric" ] || fail "rubric_path '$rubric' (from $init_file) does not exist in the repo."
55
+
56
+ echo "✅ initiative gate PASSED — '$id' is anchored: $init_file exists, PRD ($prd) and rubric ($rubric) present."
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env bash
2
+ # PMOS portable kit — kernel update (D54). Runs FROM the vendored kit inside a target repo:
3
+ #
4
+ # pmos/scripts/kit-update.sh <path-to-pmos-checkout>
5
+ #
6
+ # Re-vendors ONLY the kernel (skills/, okf/core/, scripts/, check_rubrics.py, AGENTS.md, README.md,
7
+ # templates/) from the given PMOS checkout, stamps KIT-VERSION, and never touches state/,
8
+ # planning/ (beyond check_rubrics.py), or okf/product/. Updates flow one-way, PMOS -> kit.
9
+ # Review the resulting diff as a normal PR.
10
+ set -euo pipefail
11
+
12
+ [ -n "${1:-}" ] || { echo "usage: kit-update.sh <path-to-pmos-checkout>" >&2; exit 1; }
13
+ SRC="$1"
14
+ KIT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
15
+ [ -x "$SRC/kit/build-kit.sh" ] || { echo "kit-update: ERROR — $SRC is not a PMOS checkout (no kit/build-kit.sh)" >&2; exit 1; }
16
+ exec "$SRC/kit/build-kit.sh" --update "$KIT"
@@ -0,0 +1,99 @@
1
+ #!/usr/bin/env python3
2
+ """PMOS portable kit — balanced metrics over the file-mode state layer (D54, D39).
3
+
4
+ Reads pmos/state/{runs,evals,acceptances}.jsonl and prints:
5
+ B1 north star — human corrections per ACCEPTED run (lower is better; D10, counted over
6
+ accepted runs only so leniency can't deflate it)
7
+ B2 throughput — accepted runs (guards against winning B1 by doing less)
8
+ -- eval pass rate — share of evals with verdict PASS / PASS-WITH-FINDINGS
9
+ B4 calibration — evaluator verdict vs PM label, joined by run_id: raw agreement, TPR, TNR,
10
+ Cohen's kappa (the D40 classifier method, computed locally)
11
+ -- Goodhart tripwire — fires when eval_pass_rate >= 0.8 while avg corrections >= 1.5 (the
12
+ pass-happy-judge signal; anti-optimism: read the red first)
13
+
14
+ No network, no secrets. Exit 0 always (a reporting tool, not a gate). Anti-optimism: reds print first.
15
+ """
16
+ import json, os, sys
17
+
18
+ KIT = os.environ.get("KIT_ROOT") or os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
19
+ STATE = os.path.join(KIT, "state")
20
+
21
+
22
+ def load(name):
23
+ path = os.path.join(STATE, name)
24
+ rows = []
25
+ if os.path.exists(path):
26
+ for i, line in enumerate(open(path, encoding="utf-8"), 1):
27
+ line = line.strip()
28
+ if not line:
29
+ continue
30
+ try:
31
+ rows.append(json.loads(line))
32
+ except json.JSONDecodeError:
33
+ print(f"⚠ {name}:{i} is not valid JSON — skipped (append-only files must hold one JSON object per line)")
34
+ return rows
35
+
36
+
37
+ runs = load("runs.jsonl")
38
+ evals = load("evals.jsonl")
39
+ acc = load("acceptances.jsonl")
40
+
41
+ accepted = [a for a in acc if a.get("accepted") is True]
42
+ corrections_by_run = {r.get("run_id"): int(r.get("human_corrections") or 0) for r in runs}
43
+ acc_corr = [corrections_by_run.get(a.get("run_id"), 0) for a in accepted]
44
+
45
+ passing = ("PASS", "PASS-WITH-FINDINGS")
46
+ n_pass = sum(1 for e in evals if str(e.get("verdict", "")).upper() in passing)
47
+ pass_rate = (n_pass / len(evals)) if evals else None
48
+
49
+ # --- B4: verdict-vs-PM-label confusion matrix, joined by run_id (D40) ---
50
+ label_by_run = {a.get("run_id"): str(a.get("pm_label", "")).lower() for a in acc if a.get("pm_label")}
51
+ tp = tn = fp = fn = 0
52
+ for e in evals:
53
+ lab = label_by_run.get(e.get("run_id"))
54
+ if lab not in ("pass", "fail"):
55
+ continue
56
+ pred_pass = str(e.get("verdict", "")).upper() in passing
57
+ if pred_pass and lab == "pass":
58
+ tp += 1
59
+ elif pred_pass and lab == "fail":
60
+ fp += 1
61
+ elif not pred_pass and lab == "fail":
62
+ tn += 1
63
+ else:
64
+ fn += 1
65
+ n = tp + tn + fp + fn
66
+
67
+
68
+ def kappa():
69
+ if n == 0:
70
+ return None
71
+ po = (tp + tn) / n
72
+ pe = (((tp + fp) * (tp + fn)) + ((fn + tn) * (fp + tn))) / (n * n)
73
+ return None if pe == 1 else (po - pe) / (1 - pe)
74
+
75
+
76
+ avg_corr = (sum(corrections_by_run.values()) / len(corrections_by_run)) if corrections_by_run else None
77
+ tripwire = pass_rate is not None and avg_corr is not None and pass_rate >= 0.8 and avg_corr >= 1.5
78
+
79
+ print(f"PMOS kit metrics — {len(runs)} run(s), {len(evals)} eval(s), {len(acc)} acceptance record(s)\n")
80
+ if tripwire:
81
+ print("🔴 GOODHART TRIPWIRE FIRED — evaluator passes >=80% while humans average >=1.5 corrections/run.")
82
+ print(" The north star is being gamed; treat the Review Gate as NOT calibrated (D40).\n")
83
+ if not accepted:
84
+ print("🔴 B1 north star: UNMEASURABLE — no accepted runs yet (record acceptances to pmos/state/acceptances.jsonl).")
85
+ else:
86
+ ns = sum(acc_corr) / len(accepted)
87
+ print(f"B1 north star: {ns:.2f} human corrections per accepted run (over {len(accepted)} accepted run(s); lower is better)")
88
+ print(f"B2 throughput: {len(accepted)} accepted run(s)")
89
+ print(f" eval pass rate: {'n/a — no evals yet' if pass_rate is None else f'{pass_rate:.0%} ({n_pass}/{len(evals)})'}")
90
+ k = kappa()
91
+ if n == 0:
92
+ print("🔴 B4 calibration: UNMEASURABLE — no eval joined to a PM-labelled acceptance yet; the Review Gate is uncalibrated.")
93
+ else:
94
+ tpr = tp / (tp + fn) if (tp + fn) else None
95
+ tnr = tn / (tn + fp) if (tn + fp) else None
96
+ print(f"B4 calibration (n={n}): raw agreement {(tp + tn) / n:.0%}, "
97
+ f"TPR {'n/a' if tpr is None else f'{tpr:.0%}'}, "
98
+ f"TNR {'n/a — no PM fails seen (leniency blind spot)' if tnr is None else f'{tnr:.0%}'}, "
99
+ f"kappa {'undefined' if k is None else f'{k:.2f}'} (target >= 0.60 — verdict ADVISORY below it, D40)")
@@ -0,0 +1,89 @@
1
+ # SKILL-FORMAT.md — Required Format for PMOS Skills
2
+
3
+ This document defines the **required** structure for every `.skill` file in PMOS. It is the
4
+ authority that all seed skills (`prd`, `eval-rubric`, `okr`, `strategic-brief`, `source-to-concept`)
5
+ and every future skill must conform to.
6
+
7
+ ## Why a fixed format
8
+
9
+ Skills are how PMOS gives an agent procedural competence on demand without flooding its context.
10
+ The format exists to make that economical: cheap to keep many skills available, expensive to load
11
+ only the one in use. The mechanism is **three-level progressive disclosure**.
12
+
13
+ ## The three levels
14
+
15
+ ### Level 1 — Frontmatter (always loaded)
16
+
17
+ YAML frontmatter containing **only `name` and `description`**. This is pre-loaded for **all** skills
18
+ at agent startup, so it must stay small — it is the *trigger signal* the agent uses to decide
19
+ whether the skill is relevant.
20
+
21
+ ```yaml
22
+ ---
23
+ name: prd
24
+ description: Write a Product Requirements Document for an initiative. Use when an initiative needs a spec before build work begins.
25
+ ---
26
+ ```
27
+
28
+ Rules:
29
+ - `name` — lowercase, matches the filename stem (`prd` → `prd.skill`). **Required.**
30
+ - `description` — one or two sentences. State **what** the skill does and **when** to use it.
31
+ This is the only text the agent sees for an unloaded skill, so the "when" is what makes it fire.
32
+ **Required.**
33
+ - `maturity_mode` — **optional**. Present **only** on skills that are not yet active (e.g. `bootstrap`);
34
+ omit it entirely on active skills. It lives at L1 because "is this skill executable yet?" is an
35
+ execution-gating signal a loader/CI must be able to read without parsing the body. Values: `bootstrap`
36
+ (specified, non-executable) → graduates to active (key removed) by a PM decision in `DECISIONS.md`.
37
+ - **Optional Phase-B registry metadata (D49)** — a skill may also carry `version`, `owner`, `risk`,
38
+ `category`, and `scope`. These are **optional**, producer-defined registry fields that
39
+ [`gen_skills_seed.sh`](/supabase/seed/gen_skills_seed.sh) sources into the `skills` table so the skill
40
+ library can group/version/scope skills. A skill with only `name` + `description` is still fully
41
+ conformant (e.g. `build-skills/evaluator.skill`); carry the registry keys on durable `skills/core/`
42
+ entries for consistency with their siblings.
43
+ - **No other L1 keys.** Beyond the required `name` + `description`, the optional `maturity_mode`, and the
44
+ optional Phase-B registry keys above, procedural detail does not belong in L1 — it lives in the body.
45
+
46
+ ### Level 2 — SKILL.md body (loaded when relevant)
47
+
48
+ The body below the frontmatter holds the **full procedural detail**: steps, heuristics, required
49
+ fields, gate criteria, examples. The agent reads this only after Level 1 has signalled relevance.
50
+
51
+ This is where the actual "how to do the task" lives. Write it at optimal altitude — concrete
52
+ heuristics that guide judgment, not a brittle decision tree and not a vague mandate.
53
+
54
+ ### Level 3 — Linked sub-files (loaded on demand)
55
+
56
+ Rare sub-cases, long reference tables, or edge-case procedures live in **separate files**,
57
+ referenced **by filename** from the Level 2 body. The agent reads them only when the body points it
58
+ there for the specific case in hand.
59
+
60
+ Example reference from a body: *"For multi-product PRDs, follow `prd-multiproduct.md`."*
61
+
62
+ Use Level 3 to keep Level 2 focused. If a section applies to <20% of runs, it is a Level 3
63
+ candidate.
64
+
65
+ ## File naming
66
+
67
+ - Skill files use the `.skill` extension: `prd.skill`, `eval-rubric.skill`.
68
+ - Level 3 sub-files are plain `.md` and live alongside the skill or in a named subfolder.
69
+
70
+ ## Skill namespaces
71
+
72
+ - `/skills/core/` — seed skills, canonical across PMOS.
73
+ - `/skills/domains/` — domain-specific variants (P1).
74
+ - `/skills/pm/<pm_slug>/` — PM-specific variants (e.g. `/skills/pm/wawan/`).
75
+ - `/build-skills/` — skills for the coding agents that build PMOS itself (distinct from PM skills).
76
+
77
+ ## Conformance checklist
78
+
79
+ A skill is well-formed when:
80
+
81
+ 1. Level 1 frontmatter has `name` + `description` (both required), plus optionally `maturity_mode` (on
82
+ non-active skills) and the Phase-B registry keys `version`/`owner`/`risk`/`category`/`scope` (D49);
83
+ no other L1 keys.
84
+ 2. `name` matches the filename stem.
85
+ 3. `description` states both what the skill does and when to use it.
86
+ 4. The body (Level 2) carries the full procedure and is self-sufficient for the common case.
87
+ 5. Edge cases are pushed to Level 3 sub-files and referenced by filename.
88
+
89
+ All five seed skills are authored against this checklist.
@@ -0,0 +1,122 @@
1
+ ---
2
+ name: eval-rubric
3
+ description: Author an evaluation rubric for an initiative — the measurable definition of "good" used to judge agent output. Use before any build starts; the eval is written first, paired with the PRD.
4
+ version: 1.0.0
5
+ owner: wawan
6
+ risk: low
7
+ category: eval
8
+ scope: read:okf, write:planning/evals
9
+ ---
10
+
11
+ # eval-rubric — Author an Evaluation Rubric
12
+
13
+ This skill produces an eval rubric instance for one initiative. In eval-driven PM the rubric **is the
14
+ spec made measurable** ([eval-driven-pm](/okf/core/concepts/eval-driven-pm.md)): it is authored
15
+ *before* the build, alongside the [PRD](/skills/core/prd.skill), and it defines how output will pass
16
+ through the [three-tier gate](/okf/core/concepts/output-eval.md).
17
+
18
+ > **Format note:** three-level progressive disclosure
19
+ > ([SKILL-FORMAT](/skills/core/SKILL-FORMAT.md)). Level 1 frontmatter above is the trigger and
20
+ > carries only `name` + `description`. Note: the *rubric instances* this skill produces carry their
21
+ > own frontmatter (including `eval_type`, below) — that is the rubric's frontmatter, not this skill
22
+ > file's.
23
+
24
+ ## The three-tier gate vocabulary
25
+
26
+ A rubric is written with the gate it serves in mind. Name the tiers explicitly; they are not
27
+ interchangeable:
28
+
29
+ - **Quality Gate** — *deterministic, automated.* Compile, lint, unit tests. Toolchain-enforced
30
+ pass/fail. No human judgment. A rubric's Quality-Gate criteria must be machine-checkable.
31
+ - **Review Gate** — *probabilistic, adversarial.* Does the output satisfy the rubric's criteria?
32
+ Applied by a separate evaluator agent or by the PM as critic. This is where the weighted dimensions
33
+ below are scored. Treat its verdict as **uncalibrated** until validated
34
+ ([evaluator leniency](/okf/core/concepts/output-eval.md)).
35
+ - **Acceptance Gate** — *subjective, strategic.* Is this the **right** thing? Human PM only. **This
36
+ is NOT a re-check of the rubric.** The PM's role at the end of every agent run **is** the
37
+ Acceptance Gate — a strategic-fit decision, not a re-scoring of dimensions.
38
+
39
+ Make this explicit in every rubric: state which criteria belong to which gate, and state that the
40
+ Acceptance Gate is the PM's and is not graded by the rubric.
41
+
42
+ ## Required frontmatter on the rubric instance
43
+
44
+ Every rubric document carries, at minimum:
45
+
46
+ - `type: Rubric` (or as the bundle/planning convention requires)
47
+ - **`eval_type: capability | regression`** —
48
+ - `capability` — tests whether the agent can do something new / harder. Used to push the frontier.
49
+ - `regression` — guards an already-passing capability against backsliding. Saturated capability
50
+ rubrics retire into the regression suite.
51
+ - `initiative_id`, `product_slug`, `pm_slug`, parent `KR`.
52
+
53
+ ## Grading rules
54
+
55
+ 1. **Outcome-only grading.** Criteria check **what the agent produced**, not the path it took. **Do
56
+ not grade tool call sequences**, intermediate reasoning, or how many steps were taken. A correct
57
+ outcome by an unexpected route still passes.
58
+ 2. **Weighted dimensions with partial credit.** Each rubric dimension gets a **weight**. Each is
59
+ scored (not just pass/fail), the weighted scores are **summed to a total**, and the total is
60
+ compared against a **pass threshold**. **Partial credit is required** — a rubric that is
61
+ all-or-nothing per dimension is malformed. See
62
+ [eval-rubric-template](/okf/core/templates/eval-rubric-template.md) for the scoring math.
63
+ 3. **Pre-commit the threshold.** The pass threshold is set when the rubric is written, before output
64
+ exists — not tuned afterward to match what came back.
65
+
66
+ ### Worked shape
67
+
68
+ | Dimension | Weight | Score (0–1) | Weighted |
69
+ |-----------|-------:|------------:|---------:|
70
+ | Correctness | 0.40 | … | … |
71
+ | Completeness vs PRD | 0.30 | … | … |
72
+ | Conformance (format/spec) | 0.20 | … | … |
73
+ | Clarity | 0.10 | … | … |
74
+ | **Total** | **1.00** | | **vs threshold** |
75
+
76
+ ## Sprint contract (pre-run contract)
77
+
78
+ Before any work begins, the generator and evaluator **agree on done-criteria** — this is the
79
+ contract stage of the [SDLC loop](/okf/core/concepts/sdlc-loop.md). A rubric is incomplete without
80
+ one.
81
+
82
+ **Format:**
83
+
84
+ ```
85
+ initiative_id: <id>
86
+ run_id: <id>
87
+ done_criteria:
88
+ 1. <testable criterion>
89
+ 2. <testable criterion>
90
+ ...
91
+ test_method:
92
+ 1. <how criterion 1 is verified>
93
+ 2. <how criterion 2 is verified>
94
+ ...
95
+ PM_approved: true | false
96
+ ```
97
+
98
+ - **P0 (manual):** write the contract to a temp file and get explicit **PM approval** before work
99
+ starts. `PM_approved` must be `true` to proceed.
100
+ - **P1+:** the contract is stored in `agent_runs.pre_run_contract`.
101
+
102
+ The contract and the rubric are consistent by construction: every `done_criterion` maps to rubric
103
+ dimensions, and `test_method` states the gate (Quality/Review) that checks it.
104
+
105
+ ## Output and placement
106
+
107
+ - Rubric instances are **operational** — they live under `/planning/evals/`, not in the OKF bundle.
108
+ - Filename: slugged to the initiative, e.g. `p0-eval-rubric.md`.
109
+
110
+ ## Quality bar
111
+
112
+ Before handoff: `eval_type` set; every dimension weighted; weights sum to 1.0; partial credit
113
+ possible; threshold pre-committed; gate assignment stated per criterion; Acceptance Gate marked as
114
+ PM-owned and not rubric-graded; sprint contract present with `PM_approved`.
115
+
116
+ ## Level 3 sub-cases
117
+
118
+ - Calibrating a leniency-prone evaluator against
119
+ [eval-calibration.md](/planning/evals/eval-calibration.md): see `eval-calibration-procedure.md`
120
+ (author on first need).
121
+ - Rubrics for non-code deliverables (docs, strategy): see `eval-rubric-nontext.md`
122
+ (author on first need).
@@ -0,0 +1,82 @@
1
+ ---
2
+ name: evaluator
3
+ description: Adversarially evaluate an agent run's output against its rubric and persist the verdict (the self-hosted Review Gate). Use after any build run, before the PM Acceptance Gate.
4
+ ---
5
+
6
+ # evaluator — The Self-Hosted Review Gate
7
+
8
+ This skill is PMOS's **Review Gate** made a first-class, repeatable capability (P4). It formalizes the
9
+ adversarial independent evaluator run by hand through P1–P3: judge what an agent run produced against a
10
+ rubric, write a structured verdict to the `evals` table, and surface it on the radar/board. It runs in
11
+ **Claude Code** (heavy judgment), not an Edge Function ([D34](/DECISIONS.md)).
12
+
13
+ > **Format:** three-level progressive disclosure ([SKILL-FORMAT](/skills/core/SKILL-FORMAT.md)). Level 1
14
+ > frontmatter above is the trigger. This Level 2 body is the full procedure.
15
+
16
+ ## Non-negotiable stance
17
+
18
+ - **Independent.** Evaluate in a fresh context, separate from the builder. Never rubber-stamp.
19
+ - **Adversarial / default-to-refute.** For each claimed property, try to *refute* it. Assume a defect
20
+ exists until you've looked. The builder's self-eval is **lenient** by default
21
+ ([evaluator leniency](/okf/core/concepts/output-eval.md), [D20](/DECISIONS.md)) — your job is to catch
22
+ what it overstated.
23
+ - **Outcome-only ([D14](/DECISIONS.md)).** Grade what the run *produced* — the artifact, the diff, the
24
+ live behavior — **not** the tool-call sequence or the path taken. A right answer reached "the wrong
25
+ way" still passes; a wrong answer reached tidily still fails.
26
+ - **Self-preference bias — distrust your own praise.** You are a **Claude evaluator judging
27
+ Claude-built work**, so you carry a built-in bias to over-reward outputs in your own family's style
28
+ ([D40](/DECISIONS.md)). Counter it: **default to skeptical**, and when a pass feels easy or you are
29
+ uncertain, **say so explicitly** and flag the run for the cross-family spot-check / minority-veto jury
30
+ ([calibration-method](/planning/evals/calibration-method.md)). Do not let stylistic familiarity read as
31
+ quality.
32
+ - **Advisory, not final.** Your verdict informs; it does not decide. The human PM **Acceptance Gate**
33
+ ([D12](/DECISIONS.md)) is the final authority, and this gate is **uncalibrated** until it clears the
34
+ calibration threshold. Calibration is now measured like a classifier — **Cohen's kappa ≥ 0.60 against
35
+ PM labels** (TPR/TNR, not a streak) per [D40](/DECISIONS.md), which **supersedes** D20's "3 consecutive
36
+ agreements" standard. Say in the verdict that the gate is advisory until that kappa threshold is met.
37
+
38
+ ## Procedure
39
+
40
+ 1. **Read [AGENTS.md](/AGENTS.md)** and the run's `pre_run_contract` (the agreed done-criteria).
41
+ 2. **Get the rubric** — `get_eval_rubric` (or the `rubric_path`). If none fits, use the reusable
42
+ [agent-run rubric](/planning/evals/agent-run-eval-rubric.md). Note its weighted dimensions + pass
43
+ threshold ([D15](/DECISIONS.md)).
44
+ 3. **Read the actual output** — the committed diff, the migration/function/UI, and where possible the
45
+ **live behavior** (run the query, hit the endpoint, read the CI result). Verify, don't trust the
46
+ summary. The highest-value findings come from checking claims against reality. Three probes catch the
47
+ defect classes builder self-eval reliably misses (from `eval-calibration.md`):
48
+ - **Does the gate actually gate?** Check the enforcement's own teeth — a *required*-check /
49
+ branch-protection / applied config, not just the script logic. A gate that isn't a required check
50
+ doesn't gate. *(workflow-enforcement-gate.)*
51
+ - **Does defensive code HIDE a failure?** A blank/empty/`allSettled`/error-swallowing fallback that
52
+ renders green instead of surfacing red is a false-confidence defect. *(p2-monitoring blank north-star
53
+ tile / radar-blanking throw.)*
54
+ - **Documented ≠ in-effect.** A criterion written down but not actually applied live (a raised TTL, a
55
+ revoked grant) is a FAIL. *(p1-mcp-connect JWT-TTL.)*
56
+ 4. **Grade each contract criterion reference-guided BINARY pass/fail** — not vibes. The **reference** is
57
+ the run's `pre_run_contract` ([D16](/DECISIONS.md)): for each `done_criteria` item, did the produced
58
+ outcome satisfy it, judged against its `test_method` and **outcome-only** (D14)? Emit a crisp PASS or
59
+ FAIL per criterion (no "mostly met"). These binary verdicts are what feed the PM-label confusion matrix
60
+ (D40); be conservative — an unverified criterion is a FAIL, not a pass.
61
+ 5. **Score each weighted dimension** 0..1 with a one-line justification grounded in what you observed.
62
+ Compute the weighted total (partial credit, D15) and compare to the pass threshold. The dimension score
63
+ is the numeric aggregate; the per-criterion binary grades above are the honest pass/fail backbone.
64
+ 6. **Enumerate defects** — each with `severity` (critical / must-fix / should-fix / low / nit), the
65
+ specific file+line or behavior, why it's a problem, and a concrete fix. Lead with the single most
66
+ important finding.
67
+ 7. **Decide a verdict**: `PASS` / `PASS-WITH-FINDINGS` / `FAIL`. PASS-WITH-FINDINGS is correct when the
68
+ work is acceptable but carries non-blocking defects.
69
+ 8. **Persist it** — `save_eval({ initiative_id, run_id, rubric_path, score, verdict, dimensions })`,
70
+ where `dimensions` is `{ <name>: { score, weight, note } }`. This is what makes the gate self-hosting
71
+ — the verdict lands in `evals` and surfaces on `v_eval_gate_status` (radar/board).
72
+ 9. **Hand to the PM.** The Acceptance Gate is theirs, and the PM records the ground-truth `pm_label` to
73
+ `acceptances` — paired against your verdict by `v_calibration` to compute the kappa that calibrates this
74
+ gate ([D40](/DECISIONS.md), [calibration-method](/planning/evals/calibration-method.md)). If the PM
75
+ overrides your verdict, that override is logged to
76
+ [eval-calibration.md](/planning/evals/eval-calibration.md) and the calibration loop patches this skill.
77
+
78
+ ## Output shape
79
+
80
+ A short report: **most important finding first**, then VERDICT (score vs threshold), the numbered
81
+ defects, and the per-dimension scores — followed by the `save_eval` call. Be concrete; cite specifics;
82
+ if it is genuinely solid, say so — but only after a real refutation attempt.
@@ -0,0 +1,117 @@
1
+ ---
2
+ name: ingest-repo
3
+ description: Scan an existing product repository read-only and emit a DRAFT OKF reference layer (architecture, per-table, capability ledger, integrations, conventions, ADR seeds) + register the repo, so a build agent starts warm. Use when a PM brings a product that already ships and has a repo. Never writes the tenant repo; never emits secrets.
4
+ version: 1.0.0
5
+ owner: wawan
6
+ risk: medium
7
+ category: onboarding
8
+ scope: read:tenant-repo, write:tenant-okf-drafts, write:product_repos
9
+ ---
10
+
11
+ # ingest-repo — Warm-start an existing product from its code
12
+
13
+ This skill is the **existing-repo on-ramp**: a PM arrives with a product that already ships and already
14
+ has a repo, and PMOS needs knowledge of it so a build agent doesn't cold-start on every run (re-deriving
15
+ the stack, assuming wrong, producing work the PM must heavily correct — the north-star cost). It is the
16
+ **inverse of [analyze-product-infra](/build-skills/analyze-product-infra.skill)** (which goes PRD →
17
+ what the product *needs*): ingest-repo goes **code → what the product *is***. It emits a **draft** OKF
18
+ reference layer + a repo registration and then **stops for PM approval**.
19
+
20
+ > **Format:** three-level progressive disclosure ([SKILL-FORMAT](/skills/core/SKILL-FORMAT.md)). L1
21
+ > frontmatter above is the trigger; this L2 body is the full procedure.
22
+ > **Where it runs:** in **Claude Code**, in the tenant's own conversation, read-only — never a
23
+ > server-side scanner ([D51](/okf/products/pmos/adr/d51-scan-location.md); heavy reasoning runs in Code
24
+ > per [D09](/okf/products/pmos/adr/d09-skills-execute-in-claude-code.md)).
25
+
26
+ ## Non-negotiable stance
27
+
28
+ - **Read-only, at control altitude ([D01](/okf/products/pmos/adr/d01-control-plane.md)).** Zero writes
29
+ to the tenant repo — no files, no branches, no commits. If `git status` is not clean after the run,
30
+ that is a defect.
31
+ - **No secrets, ever ([D08](/okf/products/pmos/adr/d08-never-log-request-headers.md)).** Read only env
32
+ var *names* (`.env.example`, config keys). **Secret-scan the repo content AND git history** (real
33
+ repos leak keys in committed code/history); if a secret value is found, **never** place it in a doc,
34
+ a log, or the registry — note only that a leak exists and where, by path, so the PM can rotate it.
35
+ - **Default-to-refute on capability** (the [design-reconcile](/skills/core/design-reconcile.skill)
36
+ stance applied to code): a control/route is **watermelon** until a concrete backend read/write path
37
+ is found in the code. Unbacked controls land in **§D**, not invented as capability.
38
+ - **Everything is a DRAFT ([D37](/okf/products/pmos/adr/d37-tenant-okf-db-native.md)/[D12](/okf/products/pmos/adr/d12-three-tier-eval-gate.md)).**
39
+ `save_okf_doc(... status:'draft')`. The agent proposes; the **PM approves in-app**. Retrieval note:
40
+ a PM's own build agent *can* read its own tenant drafts (get_okf_concepts returns owner-scoped drafts,
41
+ the ratified 2026-07-02 draft-visible-to-own-agent stance), so warm-start works immediately; approval
42
+ governs promotion/trust, not visibility to the owner's own agent.
43
+ - **Tenant-only.** `save_okf_doc` rejects `pmos`; this never writes the PMOS-self git bundle.
44
+ - **Idempotent.** Re-running upserts docs (on `id`) and reconciles the registry (on `product_slug`) —
45
+ no duplicates.
46
+
47
+ ## Procedure
48
+
49
+ 1. **Read [AGENTS.md](/AGENTS.md)** and confirm the target `product_slug` (owner-scoped; one product).
50
+ 2. **Read-only scan** of the tenant repo, gathering *cited* evidence (every claim will carry the repo
51
+ path it came from):
52
+ - **Stack & app surface** — manifests/lockfiles (`package.json`, `pyproject.toml`, `go.mod`, …),
53
+ framework config, entrypoints.
54
+ - **Architecture** — directory tree, entrypoints, module boundaries.
55
+ - **Data model** — migrations / schema / ORM models: one asset per table/model (columns + RLS/perm
56
+ shape where expressed).
57
+ - **Capability map** — trace **routes ↔ handlers ↔ queries**: which UI control/route reaches which
58
+ backend read/write. This is the raw material for the ledger.
59
+ - **Integrations** — config + SDK imports + `.env.example` **names only** (maps, transcription,
60
+ push, payments, storage, …).
61
+ - **Decisions & conventions** — README / ADRs / CHANGELOG / commit history (existing decisions);
62
+ CI config, lint rules, observed patterns (conventions).
63
+ 3. **Secret-scan** repo content + git history (e.g. high-entropy strings, known key prefixes). Emit
64
+ **no** value; record only "possible secret at `<path>`" for the PM.
65
+ 4. **Emit the reference layer** — via `save_okf_doc(..., status:'draft', product_slug:<slug>)`,
66
+ namespaced `products/<slug>/...`, **each body carrying situating context + the exact repo path(s)**
67
+ it was derived from (the [source-to-concept](/skills/core/source-to-concept.skill) rule + the
68
+ analyze-product-infra cited-line bar, applied to code). Minimum six kinds:
69
+
70
+ | Doc | OKF `type` | id (under `products/<slug>/`) | derived from |
71
+ |---|---|---|---|
72
+ | Architecture / stack overview | `Concept` | `concepts/architecture` | manifests + tree + entrypoints |
73
+ | Per-table/model schema (one each) | `Reference` | `data-model/<table>` | migrations / ORM models |
74
+ | **Capability ledger** | `Reference` | `references/capability-ledger` | routes ↔ handlers ↔ queries |
75
+ | Integration map | `Reference` | `references/integrations` | config + SDK imports + .env.example names |
76
+ | Conventions | `Concept` | `concepts/conventions` | CI/lint config + observed patterns |
77
+ | ADR seed(s) | `ADR` | `adr/<slug>-<n>-<topic>` | README / ADRs / commit history |
78
+
79
+ 5. **Bootstrap the per-tenant capability ledger** (the artifact
80
+ [design-reconcile](/skills/core/design-reconcile.skill) consumes, [D50](/okf/products/pmos/adr/d50-design-loop-product-scoped.md)
81
+ pattern — generic method, per-tenant instance). Classify **every** user-facing control/route into
82
+ exactly one bucket; each §A/§B entry **names the concrete read/write path** in the code:
83
+ - **§A — read-backed:** maps to a real backend read (query/endpoint) — cite it.
84
+ - **§B — write-backed:** maps to a real backend write (mutation/endpoint) — cite it.
85
+ - **§C — data-exists-unsurfaced:** the data exists but no control surfaces it (opt-in opportunity).
86
+ - **§D — no-backing (watermelon):** a control with no backend path found — flagged, not invented.
87
+ 6. **Register the repo** — `register_product_repo({ product_slug, repo:'owner/name',
88
+ app_surface:<observed>, backend_model:<observed>, status:'active', irs_ref:<repo-profile doc id>,
89
+ webhook_secret_ref: <name-or-null> })`. Fields are **observed** here (not IRS-derived); pass **no
90
+ secret value**. Add an "observed, not IRS-derived" provenance note.
91
+ 7. **STOP for PM approval.** Present the drafted layer + the ledger's §D watermelon list + any secret
92
+ findings. The PM approves docs in-app; you do not self-approve. Log the run + friction.
93
+
94
+ ## Guardrails
95
+
96
+ - **Provenance is a hard gate.** An emitted doc with an un-sourced assertion is a defect — the
97
+ evaluator's provenance dimension hunts for exactly this ([rubric](/planning/evals/ingest-repo-eval-rubric.md)).
98
+ - **Large/polyglot monorepos:** flag scope to the PM and do a per-package pass; do **not** emit a
99
+ shallow single profile.
100
+ - **`register_product_repo` semantics:** designed for provisioning output — here `app_surface`/
101
+ `backend_model` are *observed*, a usage-only difference (no schema change); note it.
102
+ - **B5 measurability:** the value thesis is "warm start → fewer corrections"; the first post-ingest
103
+ build run should retrieve these concepts (B5 > 0 for the tenant, via
104
+ [v_knowledge_reuse](/okf/products/pmos/references/metrics/v_knowledge_reuse.md) — now written by
105
+ get_okf_concepts FETCH). That real correction-delta, not the doc count, is the win.
106
+
107
+ ## Level 3 — references
108
+
109
+ - The write path + PM gate: [okf-author](/build-skills/okf-author.skill) Mode B, [D37](/okf/products/pmos/adr/d37-tenant-okf-db-native.md).
110
+ - The ledger method: [design-loop concept](/okf/core/concepts/design-loop.md),
111
+ [design-reconcile](/skills/core/design-reconcile.skill), [watermelon-flag](/okf/core/concepts/watermelon-flag.md).
112
+ - Extraction discipline: [source-to-concept](/skills/core/source-to-concept.skill).
113
+ - Scan location: [D51](/okf/products/pmos/adr/d51-scan-location.md). Registry:
114
+ [register_product_repo](/okf/products/pmos/references/mcp-tools/register_product_repo.md),
115
+ [product_repos](/okf/products/pmos/data-model/product_repos.md).
116
+ - Sibling on-ramps: [analyze-product-infra](/build-skills/analyze-product-infra.skill),
117
+ [product-onboarding playbook](/okf/core/playbooks/product-onboarding.md).
@@ -0,0 +1,68 @@
1
+ ---
2
+ name: okr
3
+ description: Draft or revise an OKR set for a planning period — objectives with measurable key results that initiatives ladder up to. Use when setting quarterly strategy or re-anchoring drifting work.
4
+ version: 1.0.0
5
+ owner: wawan
6
+ risk: low
7
+ category: planning
8
+ scope: read:okf, write:planning/okrs
9
+ ---
10
+
11
+ # okr — Draft or Revise an OKR Set
12
+
13
+ This skill produces an OKR instance for a planning period: a small set of objectives, each with
14
+ measurable key results, structured as a tree that initiatives and agent runs ladder up to. It
15
+ operationalizes the [okr-tree](/okf/core/concepts/okr-tree.md) concept.
16
+
17
+ > **Format note:** three-level progressive disclosure
18
+ > ([SKILL-FORMAT](/skills/core/SKILL-FORMAT.md)). Level 1 above is the trigger; this body is the
19
+ > procedure; rare variants go to Level 3 sub-files.
20
+
21
+ ## When to use vs. not
22
+
23
+ - **Use** to set strategy for a planning period, or to re-anchor an initiative that has drifted from
24
+ its parent KR.
25
+ - **Do not use** to spec a single piece of work — that is the [PRD skill](/skills/core/prd.skill).
26
+ OKRs sit one level above initiatives.
27
+
28
+ ## Procedure
29
+
30
+ 1. **Objectives: qualitative and few.** 2–4 objectives for the period. Each is directional and
31
+ inspirational, carries no number itself, and states a "what we want to be true."
32
+ 2. **Key results: measurable outcomes.** 2–5 KRs per objective. Each is a **change in the world**,
33
+ not a count of work done — "reduce human correction rate to < 0.5", not "ship 5 features". KRs
34
+ that measure output invite the [watermelon flag](/okf/core/concepts/watermelon-flag.md).
35
+ 3. **Ladder to the north star.** Every KR should move, directly or indirectly, the north-star metric
36
+ — **human correction rate per agent run** (lower is better). If a KR ladders to nothing, cut it.
37
+ 4. **Baseline and target.** Each KR states current baseline, target, and the measurement source.
38
+ "From X to Y, measured by Z."
39
+ 5. **Leave room for initiatives.** OKRs are parents; do not pre-assign every initiative. The tree is
40
+ filled in as work is chosen.
41
+ 6. **Set the review cadence.** State when KRs are checked and that reporting follows
42
+ [anti-optimism](/okf/core/concepts/okr-anti-optimism.md): report the red, separate confidence
43
+ from status.
44
+
45
+ ## Required content
46
+
47
+ - **Period & identity** — planning period, `product_slug`, `pm_slug`.
48
+ - **Objectives** — numbered, qualitative.
49
+ - **Key results** — per objective: baseline → target, measurement source, confidence.
50
+ - **North-star linkage** — how the set ladders to human correction rate.
51
+ - **Cadence** — review rhythm and reporting stance.
52
+
53
+ ## Output and placement
54
+
55
+ - OKR instances are **operational** — under `/planning/okrs/`, not in the OKF bundle.
56
+ - Filename: period-slugged, e.g. `okrs-q3-2026.md`.
57
+
58
+ ## Quality bar
59
+
60
+ Before handoff: objectives are qualitative; KRs are outcomes with baseline+target+source; every KR
61
+ ladders toward the north star; reporting stance is anti-optimist; no initiative is smuggled in as a
62
+ KR.
63
+
64
+ ## Level 3 sub-cases
65
+
66
+ - Mid-period KR revision / re-baselining without resetting objectives: see `okr-rebaseline.md`
67
+ (author on first need).
68
+ - Multi-product objective rollups: see `okr-rollup.md` (author on first need).