mirror of
https://github.com/backnotprop/plannotator.git
synced 2026-09-14 14:17:26 +08:00
98113182b5
* feat(guide): reviewer-supplied extra instructions for Guided Review (#1265) Adds a quiet, collapsed-by-default Custom instructions affordance to the guide launch page. The text is APPENDED to the built-in organizer methodology as a clearly delimited section (composeGuideMethodology) and never replaces it; absent or blank instructions produce byte-identical prompts to before. Persisted in a dedicated cookie (plannotator-guide-instructions) so a standing team preference survives sessions without bloating the plannotator.agents blob past the browser's per-cookie limit. Server side, the launch body gains an optional guide-only instructions field (both the Bun and Pi node:http agent-jobs handlers accept and thread it); prompt composition lives in the shared guide-review.ts that vendor.sh already vendors to Pi, so both runtimes compose identically. Text is capped at GUIDE_EXTRA_INSTRUCTIONS_MAX_CHARS (2000) server-side and mirrored by the textarea maxLength. Repair launches deliberately ignore instructions: a repair is a mechanical JSON fix, not a rewrite. Tests pin the regression contract (empty input keeps prior prompt bytes), appended-not-replacing composition, the length cap, repair isolation, and the cookie round-trip via the storage backend seam. * refactor(guide): store standing instructions server-side, not in a cookie Review findings on the cookie approach (silent write failure past the encoded 4KB per-cookie limit for multi-byte text) pointed at the real design problem: the instructions are consumed by the SERVER at launch time, so they belong in the data dir like review-skills.json, where no size ceiling or encoding inflation exists and the preference follows the machine instead of one browser profile. New GET/PUT /api/agents/guide-instructions in both runtimes backed by shared guide-instructions-store (vendored to Pi). Guide launches apply the stored text when the body carries none; the launch page still sends its live textarea value (explicit wins), so a just-typed preference can never race the debounced save. The sidebar surface sends nothing and inherits the stored text server-side. All cookie machinery removed. Also folds in the review fixes: marker-tag-shaped strings in instructions are defanged so first-match nonce recovery cannot be hijacked by pasted examples.
62 lines
2.9 KiB
TypeScript
62 lines
2.9 KiB
TypeScript
/** Hard cap on reviewer-supplied extra guide instructions (#1265): the
|
|
* freeform text appended to the organizer methodology at launch. A hygiene
|
|
* bound on prompt size, not a security boundary (the instructions run on the
|
|
* user's own machine against their own agent). Enforced server-side in
|
|
* composeGuideMethodology and mirrored by the launch textarea's maxLength. */
|
|
export const GUIDE_EXTRA_INSTRUCTIONS_MAX_CHARS = 2000;
|
|
|
|
export interface GuideDiffRef {
|
|
/** Repo-relative path; must match a DiffFile.path in the current review patch. */
|
|
file: string;
|
|
/** 1-2 sentence semantic description of what changed in THIS file, written
|
|
* from the diff hunks alone (no investigation). Required by the JSON schema
|
|
* for schema-enforced engines; optional here so a marker engine that omits
|
|
* it still yields a valid guide — the UI simply renders nothing. */
|
|
summary?: string;
|
|
}
|
|
|
|
export interface GuideSection {
|
|
/** Concept-level title, e.g. "Payment localization module" — never a filename paraphrase. */
|
|
title: string;
|
|
/** Markdown prose: what changed, why it exists, and its key implications.
|
|
* Semantic order (core first, consequences next, glue grouped last) is
|
|
* carried by the array position, not by any label field. */
|
|
overview: string;
|
|
/** File references into the provided changeset. Usually 1..n, but a
|
|
* deliberate prose-only context section (no diffs, real overview text) is
|
|
* a valid model output and is preserved as-is rather than dropped. */
|
|
diffs: GuideDiffRef[];
|
|
}
|
|
|
|
export interface CodeGuideOutput {
|
|
/** From the PR title when a PR is given, otherwise derived from the changes. */
|
|
title: string;
|
|
/** 1-2 sentence framing shown under the title: why this changeset exists. */
|
|
intent: string;
|
|
/** Ordered sections: core first, consequence next, support last. */
|
|
sections: GuideSection[];
|
|
/** Changed files the model didn't place — rendered in a trailing "Everything else" section. */
|
|
unplacedFiles?: string[];
|
|
}
|
|
|
|
/** One row of GET /api/guides — a persisted guide for the current repo
|
|
* (#1112). Loaded through the guide endpoints as the `saved:{id}` pseudo
|
|
* job id. Browser-safe (types only); the store lives in guide-store.ts. */
|
|
export interface SavedGuideListEntry {
|
|
id: string;
|
|
/** Review-target label — "PR #1082" or the branch name. */
|
|
label: string;
|
|
title: string;
|
|
/** Epoch ms when the guide was first persisted. */
|
|
savedAt: number;
|
|
progress: { reviewed: number; total: number };
|
|
/** True when the stored head sha differs from the current head. */
|
|
moved: boolean;
|
|
}
|
|
|
|
/** UI-side guide shape: server output extended with persisted per-section reviewed state.
|
|
* `saved` is set when the guide is persisted on disk (autosaved live job, or a
|
|
* `saved:{id}` load); `moved` is set only on `saved:` loads whose stored head
|
|
* sha differs from the head currently under review. */
|
|
export type CodeGuideData = CodeGuideOutput & { reviewed: boolean[]; saved?: boolean; moved?: boolean };
|