Implement typed task watchdog proof outcomes

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-06-24 21:49:32 +00:00
1 parent 189fc9b881
commit b7d72340d5
11 files changed
+638 -42

No files matched your search

@@ -0,0 +1,65 @@
CREATE TABLE IF NOT EXISTS "issue_watchdog_proof_outcomes" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"company_id" uuid NOT NULL,
"watchdog_id" uuid NOT NULL,
"source_issue_id" uuid NOT NULL,
"watchdog_issue_id" uuid,
"target_issue_id" uuid,
"outcome" text NOT NULL,
"method" text NOT NULL,
"observed_at" timestamp with time zone DEFAULT now() NOT NULL,
"result_classification" text NOT NULL,
"redacted_details" jsonb DEFAULT '{}'::jsonb NOT NULL,
"stop_fingerprint" text NOT NULL,
"proof_obligation_fingerprint" text NOT NULL,
"created_by_run_id" uuid,
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
"updated_at" timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT "issue_watchdog_proof_outcomes_outcome_chk"
CHECK ("outcome" IN ('accepted', 'restored', 'deferred', 'failed', 'dismissed'))
);
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "issue_watchdog_proof_outcomes" ADD CONSTRAINT "issue_watchdog_proof_outcomes_company_id_companies_id_fk" FOREIGN KEY ("company_id") REFERENCES "public"."companies"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "issue_watchdog_proof_outcomes" ADD CONSTRAINT "issue_watchdog_proof_outcomes_watchdog_id_issue_watchdogs_id_fk" FOREIGN KEY ("watchdog_id") REFERENCES "public"."issue_watchdogs"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "issue_watchdog_proof_outcomes" ADD CONSTRAINT "issue_watchdog_proof_outcomes_source_issue_id_issues_id_fk" FOREIGN KEY ("source_issue_id") REFERENCES "public"."issues"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "issue_watchdog_proof_outcomes" ADD CONSTRAINT "issue_watchdog_proof_outcomes_watchdog_issue_id_issues_id_fk" FOREIGN KEY ("watchdog_issue_id") REFERENCES "public"."issues"("id") ON DELETE set null ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "issue_watchdog_proof_outcomes" ADD CONSTRAINT "issue_watchdog_proof_outcomes_target_issue_id_issues_id_fk" FOREIGN KEY ("target_issue_id") REFERENCES "public"."issues"("id") ON DELETE set null ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "issue_watchdog_proof_outcomes" ADD CONSTRAINT "issue_watchdog_proof_outcomes_created_by_run_id_heartbeat_runs_id_fk" FOREIGN KEY ("created_by_run_id") REFERENCES "public"."heartbeat_runs"("id") ON DELETE set null ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
CREATE INDEX IF NOT EXISTS "issue_watchdog_proof_outcomes_company_watchdog_observed_idx"
ON "issue_watchdog_proof_outcomes" USING btree ("company_id","watchdog_id","observed_at");
--> statement-breakpoint
CREATE INDEX IF NOT EXISTS "issue_watchdog_proof_outcomes_company_source_idx"
ON "issue_watchdog_proof_outcomes" USING btree ("company_id","source_issue_id");
--> statement-breakpoint
CREATE UNIQUE INDEX IF NOT EXISTS "issue_watchdog_proof_outcomes_unique_proof_uq"
ON "issue_watchdog_proof_outcomes" USING btree ("company_id","watchdog_id","stop_fingerprint","proof_obligation_fingerprint");
@@ -778,6 +778,13 @@
"when": 1781902400000,
"tag": "0110_document_company_cascade",
"breakpoints": true
},
{
"idx": 111,
"version": "7",
"when": 1782340000000,
"tag": "0111_task_watchdog_proof_outcomes",
"breakpoints": true
}
]
}
+1
View File
@@ -33,6 +33,7 @@ export { projectGoals } from "./project_goals.js";
export { goals } from "./goals.js";
export { issues } from "./issues.js";
export { issueWatchdogs } from "./issue_watchdogs.js";
export { issueWatchdogProofOutcomes } from "./issue_watchdog_proof_outcomes.js";
export { issuePlanDecompositions } from "./issue_plan_decompositions.js";
export { issueRecoveryActions } from "./issue_recovery_actions.js";
export { issueReferenceMentions } from "./issue_reference_mentions.js";
@@ -0,0 +1,49 @@
import { sql } from "drizzle-orm";
import { check, index, jsonb, pgTable, text, timestamp, uniqueIndex, uuid } from "drizzle-orm/pg-core";
import { companies } from "./companies.js";
import { heartbeatRuns } from "./heartbeat_runs.js";
import { issues } from "./issues.js";
import { issueWatchdogs } from "./issue_watchdogs.js";
export const issueWatchdogProofOutcomes = pgTable(
"issue_watchdog_proof_outcomes",
{
id: uuid("id").primaryKey().defaultRandom(),
companyId: uuid("company_id").notNull().references(() => companies.id, { onDelete: "cascade" }),
watchdogId: uuid("watchdog_id").notNull().references(() => issueWatchdogs.id, { onDelete: "cascade" }),
sourceIssueId: uuid("source_issue_id").notNull().references(() => issues.id, { onDelete: "cascade" }),
watchdogIssueId: uuid("watchdog_issue_id").references(() => issues.id, { onDelete: "set null" }),
targetIssueId: uuid("target_issue_id").references(() => issues.id, { onDelete: "set null" }),
outcome: text("outcome").notNull(),
method: text("method").notNull(),
observedAt: timestamp("observed_at", { withTimezone: true }).notNull().defaultNow(),
resultClassification: text("result_classification").notNull(),
redactedDetails: jsonb("redacted_details").$type<Record<string, unknown>>().notNull().default({}),
stopFingerprint: text("stop_fingerprint").notNull(),
proofObligationFingerprint: text("proof_obligation_fingerprint").notNull(),
createdByRunId: uuid("created_by_run_id").references(() => heartbeatRuns.id, { onDelete: "set null" }),
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
},
(table) => ({
companyWatchdogObservedIdx: index("issue_watchdog_proof_outcomes_company_watchdog_observed_idx").on(
table.companyId,
table.watchdogId,
table.observedAt,
),
companySourceIdx: index("issue_watchdog_proof_outcomes_company_source_idx").on(
table.companyId,
table.sourceIssueId,
),
uniqueProofIdx: uniqueIndex("issue_watchdog_proof_outcomes_unique_proof_uq").on(
table.companyId,
table.watchdogId,
table.stopFingerprint,
table.proofObligationFingerprint,
),
outcomeCheck: check(
"issue_watchdog_proof_outcomes_outcome_chk",
sql`${table.outcome} IN ('accepted', 'restored', 'deferred', 'failed', 'dismissed')`,
),
}),
);
+8
View File
@@ -271,6 +271,14 @@ export type PluginIssueOriginKind = `plugin:${string}`;
export type IssueOriginKind = BuiltInIssueOriginKind | PluginIssueOriginKind;
export const ISSUE_WATCHDOG_DISCOVERY_KINDS = ["product_bug", "platform_bug"] as const;
export type IssueWatchdogDiscoveryKind = (typeof ISSUE_WATCHDOG_DISCOVERY_KINDS)[number];
export const ISSUE_WATCHDOG_PROOF_OUTCOMES = [
"accepted",
"restored",
"deferred",
"failed",
"dismissed",
] as const;
export type IssueWatchdogProofOutcome = (typeof ISSUE_WATCHDOG_PROOF_OUTCOMES)[number];
export const ISSUE_SURFACE_VISIBILITIES = ["default", "plugin_operation"] as const;
export type IssueSurfaceVisibility = (typeof ISSUE_SURFACE_VISIBILITIES)[number];
+2
View File
@@ -74,6 +74,7 @@ export {
ISSUE_ORIGIN_KINDS,
TASK_WATCHDOG_PRODUCT_BUG_ORIGIN_KIND,
ISSUE_WATCHDOG_DISCOVERY_KINDS,
ISSUE_WATCHDOG_PROOF_OUTCOMES,
ISSUE_SURFACE_VISIBILITIES,
ISSUE_RECOVERY_ACTION_KINDS,
ISSUE_RECOVERY_ACTION_STATUSES,
@@ -208,6 +209,7 @@ export {
type PluginIssueOriginKind,
type IssueOriginKind,
type IssueWatchdogDiscoveryKind,
type IssueWatchdogProofOutcome,
type IssueSurfaceVisibility,
type IssueRecoveryActionKind,
type IssueRecoveryActionStatus,
+17
View File
@@ -25,6 +25,7 @@ import type {
IssueThreadInteractionKind,
IssueThreadInteractionStatus,
IssueStatus,
IssueWatchdogProofOutcome,
} from "../constants.js";
import type { Goal } from "./goal.js";
import type { Project, ProjectWorkspace } from "./project.js";
@@ -503,6 +504,21 @@ export interface IssueExecutionDecision {
export type IssueWatchdogStatus = "active" | "disabled";
export interface IssueWatchdogProofOutcomeSummary {
id: string;
outcome: IssueWatchdogProofOutcome;
targetIssueId: string | null;
method: string;
observedAt: Date;
resultClassification: string;
redactedDetails: Record<string, unknown>;
stopFingerprint: string;
proofObligationFingerprint: string;
createdByRunId: string | null;
createdAt: Date;
updatedAt: Date;
}
export interface IssueWatchdogSummary {
id: string;
companyId: string;
@@ -515,6 +531,7 @@ export interface IssueWatchdogSummary {
lastReviewedFingerprint: string | null;
lastTriggeredAt: Date | null;
lastCompletedAt: Date | null;
latestProofOutcome?: IssueWatchdogProofOutcomeSummary | null;
triggerCount: number;
createdAt: Date;
updatedAt: Date;