Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Unreleased

- Routing eval (GW-049): optional `contribution_mode` on outcomes, additive eval `ground_truth.routing`, reconstructed routing corpus kept out of frozen headline accuracy, `false_build_occupied` stays 0 for definitive ownership.
- Local watch registry (GW-048): `gitworthy watch add|list|show|recheck|remove` and MCP `watch_*`. Fingerprint recheck reports exact deltas. No auto-create from WATCH routes and no GitHub writes.
- Contribution routing v2 (GW-043–047): `worth_check` can attach a `routing` decision; `gitworthy portfolio` / MCP `portfolio` ranks issue+PR opportunities by contribution mode with separate `dispatch_state`; `gitworthy prs` / MCP `pr_scan` is a bounded two-stage PR inventory. Verdict policy is unchanged. Hermes `contribution_profile` examples stay in docs, not global defaults. Org portfolio fans out PR scans to at most 5 hunt repos (inventory ≤25, enrich ≤5). Advisory `failed_checks` do not demote BUILD.
- Agent Plugins v1.0.0 packaging: `plugin.json`, `mcp.json`, canonical `skills/gitworthy/SKILL.md`, CI sync check (`pnpm agent-plugins:check`).
Expand Down
1 change: 1 addition & 0 deletions docs/EVALS.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Full detail: [`../eval/README.md`](../eval/README.md), [`../eval/METRICS.md`](..
| **frozen** | Offline fixture replay | Yes |
| **live** | Public GitHub/npm/git | Advisory |
| **private** | Local captures (gitignored) | No |
| **reconstructed routing** | In-process `routeContribution` fixtures | Advisory; never mixed into frozen headline accuracy |

```sh
pnpm eval:frozen
Expand Down
8 changes: 8 additions & 0 deletions eval/reconstructed/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Reconstructed routing eval

This partition is **not** snapshot-backed frozen eval.

- Cases live in `src/core/routing-eval-cases.ts`.
- Headline accuracy (`mode_top1_accuracy`) uses only `partition: snapshot` cases.
- Reconstructed / research cases never mix into frozen-suite accuracy.
- `false_build_occupied` must stay `0` for definitive-ownership fixtures.
66 changes: 66 additions & 0 deletions schemas/gitworthy-eval-case-catalog.v1.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,72 @@
"type": "string",
"minLength": 1
}
},
"routing": {
"type": "object",
"properties": {
"primary_mode": {
"type": "string",
"enum": [
"BUILD",
"REVIEW",
"SALVAGE",
"REPRODUCE",
"EVAL",
"DOC",
"WATCH",
"PASS"
]
},
"acceptable_modes": {
"default": [],
"type": "array",
"items": {
"type": "string",
"enum": [
"BUILD",
"REVIEW",
"SALVAGE",
"REPRODUCE",
"EVAL",
"DOC",
"WATCH",
"PASS"
]
}
},
"forbidden_modes": {
"default": [],
"type": "array",
"items": {
"type": "string",
"enum": [
"BUILD",
"REVIEW",
"SALVAGE",
"REPRODUCE",
"EVAL",
"DOC",
"WATCH",
"PASS"
]
}
},
"build_contention": {
"type": "string",
"enum": [
"GREEN",
"YELLOW",
"RED"
]
}
},
"required": [
"primary_mode",
"acceptable_modes",
"forbidden_modes"
],
"additionalProperties": false
}
},
"required": [
Expand Down
66 changes: 66 additions & 0 deletions schemas/gitworthy-eval-case.v1.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,72 @@
"type": "string",
"minLength": 1
}
},
"routing": {
"type": "object",
"properties": {
"primary_mode": {
"type": "string",
"enum": [
"BUILD",
"REVIEW",
"SALVAGE",
"REPRODUCE",
"EVAL",
"DOC",
"WATCH",
"PASS"
]
},
"acceptable_modes": {
"default": [],
"type": "array",
"items": {
"type": "string",
"enum": [
"BUILD",
"REVIEW",
"SALVAGE",
"REPRODUCE",
"EVAL",
"DOC",
"WATCH",
"PASS"
]
}
},
"forbidden_modes": {
"default": [],
"type": "array",
"items": {
"type": "string",
"enum": [
"BUILD",
"REVIEW",
"SALVAGE",
"REPRODUCE",
"EVAL",
"DOC",
"WATCH",
"PASS"
]
}
},
"build_contention": {
"type": "string",
"enum": [
"GREEN",
"YELLOW",
"RED"
]
}
},
"required": [
"primary_mode",
"acceptable_modes",
"forbidden_modes"
],
"additionalProperties": false
}
},
"required": [
Expand Down
25 changes: 25 additions & 0 deletions schemas/gitworthy-outcome-event.v1.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,31 @@
"pr_url": {
"type": "string",
"format": "uri"
},
"contribution_mode": {
"type": "string",
"enum": [
"BUILD",
"REVIEW",
"SALVAGE",
"REPRODUCE",
"EVAL",
"DOC",
"WATCH",
"PASS"
]
},
"investigation_class": {
"type": "string",
"enum": [
"repro",
"ci_triage",
"history",
"review",
"salvage",
"docs",
"eval"
]
}
},
"required": [
Expand Down
112 changes: 112 additions & 0 deletions schemas/gitworthy-routing-eval-metrics.v1.schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"routing_cases": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
},
"snapshot_cases": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
},
"reconstructed_cases": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
},
"mode_top1_accuracy": {
"anyOf": [
{
"type": "number",
"minimum": 0,
"maximum": 1
},
{
"type": "null"
}
]
},
"acceptable_mode_accuracy": {
"anyOf": [
{
"type": "number",
"minimum": 0,
"maximum": 1
},
{
"type": "null"
}
]
},
"false_build_occupied": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
},
"false_build_blocked": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
},
"false_pass_actionable": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
},
"counts_by_mode": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
}
},
"counts_by_contention": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
}
},
"counts_by_confidence": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
}
},
"headline_excludes_reconstructed": {
"type": "boolean",
"const": true
}
},
"required": [
"routing_cases",
"snapshot_cases",
"reconstructed_cases",
"mode_top1_accuracy",
"acceptable_mode_accuracy",
"false_build_occupied",
"false_build_blocked",
"false_pass_actionable",
"counts_by_mode",
"counts_by_contention",
"counts_by_confidence",
"headline_excludes_reconstructed"
],
"additionalProperties": false
}
2 changes: 2 additions & 0 deletions scripts/generate-schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { PortfolioItemSchema } from '../src/contracts/portfolio.js';
import { PrScanResultSchema } from '../src/contracts/pr-scan.js';
import { OpportunityTargetSchema } from '../src/contracts/opportunities.js';
import { ContributionProfileSchema } from '../src/contracts/contribution-profile.js';
import { RoutingEvalMetricsSchema } from '../src/contracts/routing-eval.js';
import {
TrackOCovariatesRecordSchema,
TrackOContingencyTableSchema,
Expand Down Expand Up @@ -61,6 +62,7 @@ const docs: Array<{ file: string; schema: z.ZodType }> = [
{ file: 'gitworthy-pr-scan.v1.schema.json', schema: PrScanResultSchema },
{ file: 'gitworthy-portfolio-item.v1.schema.json', schema: PortfolioItemSchema },
{ file: 'gitworthy-contribution-profile.v1.schema.json', schema: ContributionProfileSchema },
{ file: 'gitworthy-routing-eval-metrics.v1.schema.json', schema: RoutingEvalMetricsSchema },
{ file: 'gitworthy-track-o-join-key.v1.schema.json', schema: TrackOJoinKeySchema },
{ file: 'gitworthy-track-o-covariates.v1.schema.json', schema: TrackOCovariatesRecordSchema },
{ file: 'gitworthy-track-o-contingency.v1.schema.json', schema: TrackOContingencyTableSchema }
Expand Down
9 changes: 8 additions & 1 deletion src/contracts/eval.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { z } from 'zod';
import { DispositionSchema, SCHEMA_VERSION, SchemaVersionSchema, VerdictSchema } from './common.js';
import { BuildContentionSchema, ContributionModeSchema } from './routing.js';

/** Case/adjudication contract shared by frozen, live, and private eval suites (GW-021). */
export const EVAL_CASE_VERSION = 1 as const;
Expand Down Expand Up @@ -35,7 +36,13 @@ export const EvalGroundTruthSchema = z.object({
required_findings: z.array(z.string().min(1)).default([]),
forbidden_findings: z.array(z.string().min(1)).default([]),
required_signals: z.array(z.string().min(1)).default([]),
forbidden_signals: z.array(z.string().min(1)).default([])
forbidden_signals: z.array(z.string().min(1)).default([]),
routing: z.object({
primary_mode: ContributionModeSchema,
acceptable_modes: z.array(ContributionModeSchema).default([]),
forbidden_modes: z.array(ContributionModeSchema).default([]),
build_contention: BuildContentionSchema.optional()
}).strict().optional()
}).strict();

export const EvalCaseClassificationSchema = z.enum([
Expand Down
14 changes: 13 additions & 1 deletion src/contracts/outcomes.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { z } from 'zod';
import { ContributionModeSchema } from './routing.js';

/** Outcome event schema for the local durable store (Track O T1 labels map onto these events). */
export const OutcomeEventNameSchema = z.enum([
Expand Down Expand Up @@ -46,7 +47,18 @@ export const OutcomeEventSchema = z.object({
/** True when the contribution proceeded despite a soft SKIP (Track O anti-SKIP policy). */
acted_against_skip: z.boolean().optional(),
/** PR URL once known; join key companion to decision_id. */
pr_url: z.string().url().optional()
pr_url: z.string().url().optional(),
/** Optional routing annotation. Legacy outcomes without this still parse. */
contribution_mode: ContributionModeSchema.optional(),
investigation_class: z.enum([
'repro',
'ci_triage',
'history',
'review',
'salvage',
'docs',
'eval'
]).optional()
}).strict().superRefine((value, ctx) => {
if (value.close_reason !== undefined && value.event !== 'closed_unmerged') {
ctx.addIssue({
Expand Down
Loading
Loading