Stop domain-wheel collecting and age-band years in prompts. Ask until the training gate, then discriminate until convergence, then deliver a range plus a concrete follow-up. Reserve holdout only with four dated events. Co-authored-by: Cursor <cursoragent@cursor.com>
93 lines
2.4 KiB
TypeScript
93 lines
2.4 KiB
TypeScript
/**
|
|
* V9 rectification Case state machine contracts.
|
|
*
|
|
* The server owns the authoritative Case status. The browser and the agent
|
|
* never derive status from message counts, candidate existence or session
|
|
* ordering.
|
|
*/
|
|
|
|
export const RECTIFICATION_CASE_STATUSES = [
|
|
"draft",
|
|
"collecting_evidence",
|
|
"candidate_ready",
|
|
"candidate_accepted",
|
|
"needs_rebaseline",
|
|
"paused",
|
|
"confirmed",
|
|
"closed",
|
|
"abandoned",
|
|
"superseded",
|
|
] as const;
|
|
|
|
export type RectificationCaseStatus =
|
|
(typeof RECTIFICATION_CASE_STATUSES)[number];
|
|
|
|
/** Statuses that may be resumed by the user. */
|
|
export const RESUMABLE_CASE_STATUSES: readonly RectificationCaseStatus[] = [
|
|
"draft",
|
|
"collecting_evidence",
|
|
"candidate_ready",
|
|
"candidate_accepted",
|
|
"needs_rebaseline",
|
|
"paused",
|
|
];
|
|
|
|
/** Statuses that only allow read-only history access. */
|
|
export const TERMINAL_CASE_STATUSES: readonly RectificationCaseStatus[] = [
|
|
"confirmed",
|
|
"closed",
|
|
"abandoned",
|
|
"superseded",
|
|
];
|
|
|
|
const RESUMABLE_SET = new Set<string>(RESUMABLE_CASE_STATUSES);
|
|
const TERMINAL_SET = new Set<string>(TERMINAL_CASE_STATUSES);
|
|
|
|
export function isRectificationCaseStatus(
|
|
value: unknown,
|
|
): value is RectificationCaseStatus {
|
|
return (
|
|
typeof value === "string" &&
|
|
(RESUMABLE_SET.has(value) || TERMINAL_SET.has(value))
|
|
);
|
|
}
|
|
|
|
export function isResumableStatus(
|
|
status: RectificationCaseStatus,
|
|
): boolean {
|
|
return RESUMABLE_SET.has(status);
|
|
}
|
|
|
|
export function isTerminalStatus(status: RectificationCaseStatus): boolean {
|
|
return TERMINAL_SET.has(status);
|
|
}
|
|
|
|
/**
|
|
* Legal terminal transitions. A resumable case may move to any terminal
|
|
* status; terminal statuses are immutable.
|
|
*/
|
|
export function canTransitToTerminal(
|
|
from: RectificationCaseStatus,
|
|
to: RectificationCaseStatus,
|
|
): boolean {
|
|
if (isTerminalStatus(from)) return false;
|
|
return isTerminalStatus(to);
|
|
}
|
|
|
|
/** statuses that reject evidence/turn writes. Terminal cases are read-only. */
|
|
export function evidenceWritesAllowed(
|
|
status: RectificationCaseStatus,
|
|
): boolean {
|
|
return isResumableStatus(status);
|
|
}
|
|
|
|
/**
|
|
* The one-resumable-case-per-user invariant, mirrored from the database
|
|
* partial unique index. The database is the enforcement point; this is the
|
|
* contract the service layer relies on.
|
|
*/
|
|
export const MAX_RESUMABLE_CASES_PER_USER = 1;
|
|
|
|
export const RECTIFICATION_SKILL_NAME = "jyotish-birth-time-rectification";
|
|
export const RECTIFICATION_SKILL_VERSION = "10.0.23";
|