Skip to content
Closed
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
44 changes: 44 additions & 0 deletions src/signals/miner-goal-spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import type { FocusManifestIssueDiscoveryPolicy } from "./focus-manifest";

/** Values carried over from `.gittensory.yml`'s focus-manifest discovery policy. */
export type MinerGoalSpecIssueDiscoveryPolicy = FocusManifestIssueDiscoveryPolicy;

/**
* Maintainer-authored miner targeting preferences declared in `.gittensory-miner.yml`.
*
* This is intentionally small in the foundation phase: it only captures whether autonomous miner
* work is allowed for the repo at all, which paths are preferred/blocked, which labels are preferred,
* how many concurrent claims a single miner should hold, and whether issue discovery is encouraged.
* Parsing and file discovery land in a follow-up issue.
*/
export type MinerGoalSpec = {
/** Whether autonomous miners may target this repo. Default: true. */
minerEnabled: boolean;
/** Preferred work areas for miner-created changes. Glob list. Default: []. */
wantedPaths: string[];
/** Paths miners should avoid touching. Glob list. Default: []. */
blockedPaths: string[];
/** Labels miners should prefer when selecting or filing work. Default: []. */
preferredLabels: string[];
/** Maximum concurrent claims a miner should hold against this repo. Default: 1. */
maxConcurrentClaims: number;
/** Whether issue discovery work is encouraged for the repo. Default: neutral. */
issueDiscoveryPolicy: MinerGoalSpecIssueDiscoveryPolicy;
};

/**
* Safe defaults for an absent `.gittensory-miner.yml`.
*
* - `minerEnabled: true` keeps public repos targetable unless the owner explicitly opts out.
* - empty path/label lists mean "no additional preference" rather than hidden policy.
* - `maxConcurrentClaims: 1` keeps a miner from claiming multiple issues in the same repo by default.
* - `issueDiscoveryPolicy: neutral` mirrors `.gittensory.yml`'s own default stance.
*/
export const DEFAULT_MINER_GOAL_SPEC: MinerGoalSpec = {
minerEnabled: true,
wantedPaths: [],
blockedPaths: [],
preferredLabels: [],
maxConcurrentClaims: 1,
issueDiscoveryPolicy: "neutral",
};
26 changes: 26 additions & 0 deletions test/unit/miner-goal-spec.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { describe, expect, it } from "vitest";
import { DEFAULT_MINER_GOAL_SPEC, type MinerGoalSpec } from "../../src/signals/miner-goal-spec";

describe("MinerGoalSpec", () => {
it("exports safe defaults matching the declared type contract", () => {
const typed: MinerGoalSpec = DEFAULT_MINER_GOAL_SPEC;
expect(typed).toEqual({
minerEnabled: true,
wantedPaths: [],
blockedPaths: [],
preferredLabels: [],
maxConcurrentClaims: 1,
issueDiscoveryPolicy: "neutral",
});
});

it("documents the default for every field in a co-located comment", async () => {
const source = await import("node:fs/promises").then((fs) => fs.readFile("src/signals/miner-goal-spec.ts", "utf8"));
expect(source).toMatch(/Whether autonomous miners may target this repo\. Default: true\./);
expect(source).toMatch(/Preferred work areas for miner-created changes\. Glob list\. Default: \[\]\./);
expect(source).toMatch(/Paths miners should avoid touching\. Glob list\. Default: \[\]\./);
expect(source).toMatch(/Labels miners should prefer when selecting or filing work\. Default: \[\]\./);
expect(source).toMatch(/Maximum concurrent claims a miner should hold against this repo\. Default: 1\./);
expect(source).toMatch(/Whether issue discovery work is encouraged for the repo\. Default: neutral\./);
});
});
Loading