feat: benchmark credential parity, transcript, honest results + read-tier accuracy (tasks 0032, 0033) #36

Merged
alexion merged 10 commits from task-0032-bench-read-report-persistence into main 2026-07-18 10:28:33 -04:00
3 changed files with 72 additions and 4 deletions
Showing only changes of commit 8653b89612 - Show all commits

View File

@@ -33,9 +33,12 @@ So outside a checkout with the token in the environment, `gitea-axi <command> -R
- `issue` — list, view, create, comment on, edit, close/reopen, pin, and link issues.
- `pr` — create, view, comment on, edit, review, merge, check out, diff, and inspect the checks of pull requests.
- `label` — list, create, edit, and delete labels.
- `search` — full-text search across issues and pull requests.
- `search` — full-text search; it takes a subcommand, so search issues with `search issues "<query>"` and pull requests with `search prs "<query>"` (a bare `search "<query>"` is not valid).
- `setup` — install this skill (`setup`) and, opt-in, the SessionStart dashboard hook (`setup hooks`).
To read one issue's fields, reach straight for `issue view <number>`: it shows labels and state by default, and takes `--fields assignees,milestone,…` for the rest.
You rarely need `issue list` to answer a question about a single issue.
## Discovery
This skill is a pointer, not a command reference — the CLI is the single source of truth for its own interface.

View File

@@ -222,8 +222,11 @@ Show a single issue. Pull request numbers are rejected — use \`pr view\` inste
flags:
--comments Render every comment in full (bodies truncated at 800 chars)
--full Suppress all truncation of the issue body and comment bodies
--fields <a,b,c> Append extra fields: assignees, closedAt, milestone, updatedAt, url
--help Show this help
Labels are shown by default; use --fields to add assignees, milestone, and more.
global flags:
-R, --repo <OWNER/NAME> Override the repository detected from the git origin remote
--login <name> Select a tea login profile by name
@@ -479,19 +482,32 @@ const ISSUE_VIEW_FIELDS: FieldDef<Issue>[] = [
pluck("number"),
pluck("title"),
lowercased("state"),
joined("labels", "labels", "name"),
pluck("author", "user.login"),
relativeTimeField("created", "created_at"),
];
// Appended to the default view fields on request via `--fields`, never replacing
// them. Labels and body are shown by default, so they are not offered here.
const ISSUE_VIEW_EXTRA_FIELDS: Record<string, FieldDef<Issue>> = {
assignees: joined("assignees", "assignees", "login"),
closedAt: relativeTimeField("closedAt", "closed_at"),
milestone: pluck("milestone", "milestone.title"),
updatedAt: relativeTimeField("updatedAt", "updated_at"),
url: pluck("url", "html_url"),
};
interface IssueDetailOptions {
host: string;
full: boolean;
withComments: boolean;
now: Date;
/** Extra fields selected via `--fields`, appended after the defaults. */
extraFields: FieldDef<Issue>[];
}
function buildIssueDetail(issue: Issue, options: IssueDetailOptions): Record<string, unknown> {
const row = extractRow(issue, ISSUE_VIEW_FIELDS, {
const row = extractRow(issue, [...ISSUE_VIEW_FIELDS, ...options.extraFields], {
now: options.now,
host: options.host,
full: options.full,
@@ -539,12 +555,21 @@ async function issueView(deps: CliDeps, args: string[]): Promise<string> {
}
const { flags, positionals } = parseFlags(
args,
{ "--comments": { takesValue: false }, "--full": { takesValue: false } },
{
"--comments": { takesValue: false },
"--full": { takesValue: false },
"--fields": { takesValue: true },
},
"issue view",
);
const number = parsePositionalNumber(positionals, "issue view", "issue");
const full = flags["--full"] === true;
const withComments = flags["--comments"] === true;
const extraFields = selectExtraFields(
flagValue(flags, "--fields"),
ISSUE_VIEW_EXTRA_FIELDS,
"issue view",
);
const context = await resolveRepoContext(deps);
const api = createClient(context);
@@ -557,7 +582,7 @@ async function issueView(deps: CliDeps, args: string[]): Promise<string> {
}
const now = new Date();
const item = buildIssueDetail(issue, { host: context.host, full, withComments, now });
const item = buildIssueDetail(issue, { host: context.host, full, withComments, now, extraFields });
const blocks: DetailBlock[] = [];
if (withComments) {

View File

@@ -47,6 +47,46 @@ describe("issue view", () => {
expect(stdout).toContain("comment_count: 3 — use --comments to see full comments");
});
it("renders the issue's labels comma-joined by default, with no flag", async () => {
server = await startFixtureServer([
{
method: "GET",
path: ISSUE_PATH,
body: issueBody({ labels: [{ name: "bug" }, { name: "regression" }] }),
},
]);
const { stdout, exitCode } = await runCliTest(["issue", "view", "42"], {
env: testModeEnv(server.url),
});
expect(exitCode).toBe(0);
// TOON-quoted because the joined value contains a comma.
expect(stdout).toContain('labels: "bug, regression"');
});
it("appends named extra fields with --fields on top of the default fields", async () => {
server = await startFixtureServer([
{
method: "GET",
path: ISSUE_PATH,
body: issueBody({
assignees: [{ login: "alexion" }],
milestone: { title: "v2.0" },
}),
},
]);
const { stdout, exitCode } = await runCliTest(
["issue", "view", "42", "--fields", "assignees,milestone"],
{ env: testModeEnv(server.url) },
);
expect(exitCode).toBe(0);
// Default fields are still present; the extra fields are appended.
expect(stdout).toContain("state: open");
expect(stdout).toContain("assignees: alexion");
expect(stdout).toContain("milestone: v2.0");
});
it("renders comment_count: 0 when there are no comments", async () => {
server = await startFixtureServer([
{ method: "GET", path: ISSUE_PATH, body: issueBody({ comments: 0 }) },