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
29 changes: 1 addition & 28 deletions packages/loopover-miner/lib/deny-hooks.d.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1 @@
export type DenyRule = {
/** Tool-name glob (`*` = any within a segment, `**` across segments) or an exact tool name. */
matcher: string;
/** Optional glob tested against every path-shaped string in the tool-call input. */
pathPattern?: string;
/** Optional substrings that must ALL appear in one string-shaped input field (e.g. a shell command). */
inputIncludesAll?: string[];
/** Optional pattern that must match a whole whitespace-separated token (quotes stripped) of one
* string-shaped input field — for flag-shaped needles where a substring test would false-positive
* on an unrelated longer flag (e.g. `-f` vs. `--follow-tags`). */
inputTokenPattern?: RegExp;
/** Human-readable reason surfaced when this rule blocks a call. */
reason: string;
};

export type DenyVerdict = {
allowed: boolean;
blockedBy?: DenyRule;
};

export type ProposedToolCall = {
name: string;
input: Record<string, unknown>;
};

export const DEFAULT_DENY_RULES: DenyRule[];

export function evaluateDenyHooks(toolCall: ProposedToolCall, rules?: DenyRule[]): DenyVerdict;
export { DEFAULT_DENY_RULES, evaluateDenyHooks, type DenyRule, type DenyVerdict, type ProposedToolCall, } from "@loopover/engine";
7 changes: 4 additions & 3 deletions packages/loopover-miner/lib/deny-hooks.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions packages/loopover-miner/lib/deny-hooks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// PreToolUse-style deny-hook primitives (#2295). Now a thin re-export of the engine's pure, deterministic deny
// evaluator: the whole implementation moved into `@loopover/engine` (packages/loopover-engine/src/miner/
// deny-hooks.ts) by #5667 so the review stack and the miner share one copy. No behavior change — the evaluator is
// pure (no IO, no globals, no Date/random). Types (DenyRule/DenyVerdict/ProposedToolCall) come from the same
// engine module so the miner package's public contract stays identical after the TypeScript migration.

export {
DEFAULT_DENY_RULES,
evaluateDenyHooks,
type DenyRule,
type DenyVerdict,
type ProposedToolCall,
} from "@loopover/engine";
99 changes: 59 additions & 40 deletions packages/loopover-miner/lib/pr-outcome.d.ts
Original file line number Diff line number Diff line change
@@ -1,41 +1,60 @@
import type { AppendEventInput, LedgerEntry } from "./event-ledger.js";

export const MINER_PR_OUTCOME_EVENT: "pr_outcome";
export const MINER_PR_OUTCOME_DECISIONS: readonly ["merged", "closed"];

export type MinerPrOutcomeDecision = "merged" | "closed";

export interface NormalizedPrOutcomePayload {
prNumber: number;
decision: MinerPrOutcomeDecision;
closedAt: string | null;
reason: string | null;
}

export interface PrOutcomeInput {
repoFullName?: unknown;
prNumber?: unknown;
decision?: unknown;
closedAt?: unknown;
reason?: unknown;
}

export interface RecordPrOutcomeOptions {
/** Optional at the type level so a caller can pass an unusable ledger to exercise the fail-closed guard; the
* writer throws `invalid_event_ledger` at runtime when this is absent or lacks `appendEvent`. Reuses the
* real EventLedger#appendEvent signature so a genuine EventLedger (not just a same-shaped stub) type-checks. */
eventLedger?: { appendEvent(event: AppendEventInput): LedgerEntry };
}

export interface PrOutcomeLedgerReader {
readEvents(filter?: { since?: number; repoFullName?: string }): unknown[];
}

export function normalizePrOutcomePayload(payload: unknown): NormalizedPrOutcomePayload | null;

export function recordPrOutcomeSnapshot(input: PrOutcomeInput, options?: RecordPrOutcomeOptions): unknown;

export function readPrOutcomes(
eventLedger: PrOutcomeLedgerReader,
filter?: { since?: number; repoFullName?: string },
): Map<string, NormalizedPrOutcomePayload & { repoFullName: string }>;
/** Event-ledger vocabulary for a miner-local PR outcome. */
export declare const MINER_PR_OUTCOME_EVENT: "pr_outcome";
/** The terminal decisions a miner records for one of its own PRs. */
export declare const MINER_PR_OUTCOME_DECISIONS: readonly ["merged", "closed"];
export type MinerPrOutcomeDecision = (typeof MINER_PR_OUTCOME_DECISIONS)[number];
export type NormalizedPrOutcomePayload = {
prNumber: number;
decision: MinerPrOutcomeDecision;
closedAt: string | null;
reason: string | null;
};
export type PrOutcomeInput = {
repoFullName?: unknown;
prNumber?: unknown;
decision?: unknown;
closedAt?: unknown;
reason?: unknown;
};
export type RecordPrOutcomeOptions = {
/** Optional at the type level so a caller can pass an unusable ledger to exercise the fail-closed guard; the
* writer throws `invalid_event_ledger` at runtime when this is absent or lacks `appendEvent`. Reuses the
* real EventLedger#appendEvent signature so a genuine EventLedger (not just a same-shaped stub) type-checks. */
eventLedger?: {
appendEvent(event: AppendEventInput): LedgerEntry;
};
};
export type PrOutcomeLedgerReader = {
readEvents(filter?: {
since?: number;
repoFullName?: string;
}): unknown[];
};
/**
* Validate + normalize a PR-outcome payload; returns `null` on any malformed shape (mirrors manage-status.js's
* `normalizeManageUpdatePayload`, so a bad row can neither be written nor read back). A `closed` decision may carry
* a reason bucket drawn from {@link REJECTION_REASONS} (shared with the rejection-state-machine sibling); a `merged`
* decision — or an unrecognized reason — normalizes the reason to `null` (a merged PR has no rejection reason).
*/
export declare function normalizePrOutcomePayload(payload: unknown): NormalizedPrOutcomePayload | null;
/**
* Thin writer over an INJECTED event ledger (same dependency-injection shape as manage-poll.js's
* `recordManagePollSnapshot`, so it's unit-testable without a real ledger file). Appends one
* {@link MINER_PR_OUTCOME_EVENT} scoped to the repo and returns the appended entry. Fail-soft on a malformed
* snapshot: a missing repo or an invalid payload returns `null` rather than throwing (an unusable ledger is the
* only hard error, since that is a programmer wiring mistake).
*/
export declare function recordPrOutcomeSnapshot(input: PrOutcomeInput, options?: RecordPrOutcomeOptions): unknown;
/**
* Reconstruct the latest outcome per repo/PR from the ledger's ascending append-only event stream (mirrors
* manage-status.js's `indexLatestManageUpdates`). Reads via the injected ledger's `readEvents(filter)` and reduces
* the pure result — a later event for the same repo/PR supersedes an earlier one. Returns a `Map` keyed by
* `repoFullName:prNumber`.
*/
export declare function readPrOutcomes(eventLedger: PrOutcomeLedgerReader | null | undefined, filter?: {
since?: number;
repoFullName?: string;
}): Map<string, NormalizedPrOutcomePayload & {
repoFullName: string;
}>;
114 changes: 61 additions & 53 deletions packages/loopover-miner/lib/pr-outcome.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading