@nonameolsson/nightjar 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +405 -2
- package/dist/account.d.ts +12 -0
- package/dist/account.js +57 -0
- package/dist/account.js.map +1 -0
- package/dist/adapter-module.d.ts +18 -0
- package/dist/adapter-module.js +83 -0
- package/dist/adapter-module.js.map +1 -0
- package/dist/adapters.d.ts +15 -0
- package/dist/adapters.js +160 -0
- package/dist/adapters.js.map +1 -0
- package/dist/args.d.ts +13 -0
- package/dist/args.js +84 -0
- package/dist/args.js.map +1 -0
- package/dist/ask.d.ts +6 -0
- package/dist/ask.js +27 -0
- package/dist/ask.js.map +1 -0
- package/dist/azure-devops/api.d.ts +34 -0
- package/dist/azure-devops/api.js +98 -0
- package/dist/azure-devops/api.js.map +1 -0
- package/dist/azure-devops/code-host.d.ts +36 -0
- package/dist/azure-devops/code-host.js +185 -0
- package/dist/azure-devops/code-host.js.map +1 -0
- package/dist/azure-devops/fake-azure-devops.d.ts +90 -0
- package/dist/azure-devops/fake-azure-devops.js +728 -0
- package/dist/azure-devops/fake-azure-devops.js.map +1 -0
- package/dist/azure-devops/index.d.ts +8 -0
- package/dist/azure-devops/index.js +11 -0
- package/dist/azure-devops/index.js.map +1 -0
- package/dist/azure-devops/sign-in.d.ts +11 -0
- package/dist/azure-devops/sign-in.js +68 -0
- package/dist/azure-devops/sign-in.js.map +1 -0
- package/dist/azure-devops/text.d.ts +1 -0
- package/dist/azure-devops/text.js +41 -0
- package/dist/azure-devops/text.js.map +1 -0
- package/dist/azure-devops/tracker.d.ts +44 -0
- package/dist/azure-devops/tracker.js +333 -0
- package/dist/azure-devops/tracker.js.map +1 -0
- package/dist/build.d.ts +75 -0
- package/dist/build.js +698 -0
- package/dist/build.js.map +1 -0
- package/dist/check.d.ts +8 -0
- package/dist/check.js +25 -0
- package/dist/check.js.map +1 -0
- package/dist/checks.d.ts +45 -0
- package/dist/checks.js +243 -0
- package/dist/checks.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +11 -0
- package/dist/cli.js.map +1 -0
- package/dist/code-host.d.ts +19 -0
- package/dist/code-host.js +2 -0
- package/dist/code-host.js.map +1 -0
- package/dist/config.d.ts +86 -0
- package/dist/config.js +294 -0
- package/dist/config.js.map +1 -0
- package/dist/contract/case.d.ts +4 -0
- package/dist/contract/case.js +2 -0
- package/dist/contract/case.js.map +1 -0
- package/dist/contract/code-host.d.ts +24 -0
- package/dist/contract/code-host.js +108 -0
- package/dist/contract/code-host.js.map +1 -0
- package/dist/contract/command.d.ts +2 -0
- package/dist/contract/command.js +36 -0
- package/dist/contract/command.js.map +1 -0
- package/dist/contract/feature-writer.d.ts +3 -0
- package/dist/contract/feature-writer.js +101 -0
- package/dist/contract/feature-writer.js.map +1 -0
- package/dist/contract/run.d.ts +18 -0
- package/dist/contract/run.js +89 -0
- package/dist/contract/run.js.map +1 -0
- package/dist/contract/tracker.d.ts +30 -0
- package/dist/contract/tracker.js +250 -0
- package/dist/contract/tracker.js.map +1 -0
- package/dist/create.d.ts +9 -0
- package/dist/create.js +112 -0
- package/dist/create.js.map +1 -0
- package/dist/doctor.d.ts +4 -0
- package/dist/doctor.js +42 -0
- package/dist/doctor.js.map +1 -0
- package/dist/fakes/code-host.d.ts +21 -0
- package/dist/fakes/code-host.js +42 -0
- package/dist/fakes/code-host.js.map +1 -0
- package/dist/fakes/harness.d.ts +7 -0
- package/dist/fakes/harness.js +68 -0
- package/dist/fakes/harness.js.map +1 -0
- package/dist/fakes/machine.d.ts +11 -0
- package/dist/fakes/machine.js +101 -0
- package/dist/fakes/machine.js.map +1 -0
- package/dist/fakes/tracker.d.ts +40 -0
- package/dist/fakes/tracker.js +116 -0
- package/dist/fakes/tracker.js.map +1 -0
- package/dist/feature-file.d.ts +12 -0
- package/dist/feature-file.js +84 -0
- package/dist/feature-file.js.map +1 -0
- package/dist/git.d.ts +9 -0
- package/dist/git.js +12 -0
- package/dist/git.js.map +1 -0
- package/dist/github/api.d.ts +37 -0
- package/dist/github/api.js +66 -0
- package/dist/github/api.js.map +1 -0
- package/dist/github/code-host.d.ts +19 -0
- package/dist/github/code-host.js +105 -0
- package/dist/github/code-host.js.map +1 -0
- package/dist/github/fake-gh.d.ts +17 -0
- package/dist/github/fake-gh.js +51 -0
- package/dist/github/fake-gh.js.map +1 -0
- package/dist/github/fake-github.d.ts +58 -0
- package/dist/github/fake-github.js +285 -0
- package/dist/github/fake-github.js.map +1 -0
- package/dist/github/labels.d.ts +3 -0
- package/dist/github/labels.js +44 -0
- package/dist/github/labels.js.map +1 -0
- package/dist/github/tracker.d.ts +28 -0
- package/dist/github/tracker.js +208 -0
- package/dist/github/tracker.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/init.d.ts +19 -0
- package/dist/init.js +225 -0
- package/dist/init.js.map +1 -0
- package/dist/ledger.d.ts +13 -0
- package/dist/ledger.js +49 -0
- package/dist/ledger.js.map +1 -0
- package/dist/main.d.ts +11 -0
- package/dist/main.js +215 -0
- package/dist/main.js.map +1 -0
- package/dist/person-config.d.ts +9 -0
- package/dist/person-config.js +46 -0
- package/dist/person-config.js.map +1 -0
- package/dist/plan.d.ts +9 -0
- package/dist/plan.js +27 -0
- package/dist/plan.js.map +1 -0
- package/dist/ports.d.ts +16 -0
- package/dist/ports.js +104 -0
- package/dist/ports.js.map +1 -0
- package/dist/prompt.d.ts +166 -0
- package/dist/prompt.js +217 -0
- package/dist/prompt.js.map +1 -0
- package/dist/queue.d.ts +20 -0
- package/dist/queue.js +94 -0
- package/dist/queue.js.map +1 -0
- package/dist/say.d.ts +2 -0
- package/dist/say.js +4 -0
- package/dist/say.js.map +1 -0
- package/dist/serve.d.ts +10 -0
- package/dist/serve.js +85 -0
- package/dist/serve.js.map +1 -0
- package/dist/session.d.ts +39 -0
- package/dist/session.js +144 -0
- package/dist/session.js.map +1 -0
- package/dist/settings.d.ts +10 -0
- package/dist/settings.js +92 -0
- package/dist/settings.js.map +1 -0
- package/dist/signals.d.ts +5 -0
- package/dist/signals.js +13 -0
- package/dist/signals.js.map +1 -0
- package/dist/skills.d.ts +4 -0
- package/dist/skills.js +51 -0
- package/dist/skills.js.map +1 -0
- package/dist/status-shape.d.ts +53 -0
- package/dist/status-shape.js +3 -0
- package/dist/status-shape.js.map +1 -0
- package/dist/status.d.ts +23 -0
- package/dist/status.js +56 -0
- package/dist/status.js.map +1 -0
- package/dist/tracker.d.ts +56 -0
- package/dist/tracker.js +12 -0
- package/dist/tracker.js.map +1 -0
- package/dist/workflow.d.ts +33 -0
- package/dist/workflow.js +53 -0
- package/dist/workflow.js.map +1 -0
- package/dist/worktree.d.ts +44 -0
- package/dist/worktree.js +193 -0
- package/dist/worktree.js.map +1 -0
- package/docs/ticket-contract.md +95 -0
- package/package.json +74 -5
- package/plugin/nightjar-status/.claude-plugin/plugin.json +5 -0
- package/plugin/nightjar-status/hooks/format.ts +48 -0
- package/plugin/nightjar-status/hooks/hooks.json +1 -0
- package/plugin/nightjar-status/hooks/register.ts +51 -0
- package/schema/factory.schema.json +437 -0
- package/skills/nightjar-feature/SKILL.md +73 -0
- package/src/status-shape.ts +44 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// A label that exists is never touched, so a team's own colours and descriptions stay.
|
|
2
|
+
import { firstLine } from '../git.js';
|
|
3
|
+
import { SIGNALS } from '../signals.js';
|
|
4
|
+
import { GitHubApi, GitHubFailure } from './api.js';
|
|
5
|
+
const MEANING = {
|
|
6
|
+
go: 'Nightjar: build this Feature',
|
|
7
|
+
ready: 'Nightjar: this Ticket is ready to be built',
|
|
8
|
+
working: 'Nightjar: working on it now',
|
|
9
|
+
needsInfo: 'Nightjar: needs an answer to go on',
|
|
10
|
+
human: 'Nightjar: a person has to take it from here'
|
|
11
|
+
};
|
|
12
|
+
// What was done for each label name, one line each.
|
|
13
|
+
export async function createSignalLabels(gh, repo, names) {
|
|
14
|
+
const api = new GitHubApi(repo, gh);
|
|
15
|
+
const said = [];
|
|
16
|
+
const seen = new Set();
|
|
17
|
+
for (const signal of SIGNALS) {
|
|
18
|
+
const name = names[signal];
|
|
19
|
+
if (seen.has(name))
|
|
20
|
+
continue;
|
|
21
|
+
seen.add(name);
|
|
22
|
+
const made = await api.raw([
|
|
23
|
+
'-X',
|
|
24
|
+
'POST',
|
|
25
|
+
`repos/${repo}/labels`,
|
|
26
|
+
'-f',
|
|
27
|
+
`name=${name}`,
|
|
28
|
+
'-f',
|
|
29
|
+
`description=${MEANING[signal]}`
|
|
30
|
+
]);
|
|
31
|
+
if (made.ok) {
|
|
32
|
+
said.push(`created the label ${name}`);
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
// a refusal is only "exists already" when the label can be read back
|
|
36
|
+
const there = await api.raw([`repos/${repo}/labels/${encodeURIComponent(name)}`]);
|
|
37
|
+
if (!there.ok) {
|
|
38
|
+
throw new GitHubFailure(`gh could not create the label ${name}: ${firstLine(made.err) || firstLine(made.out)}`);
|
|
39
|
+
}
|
|
40
|
+
said.push(`the label ${name} exists already`);
|
|
41
|
+
}
|
|
42
|
+
return said;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=labels.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"labels.js","sourceRoot":"","sources":["../../src/github/labels.ts"],"names":[],"mappings":"AAAA,uFAAuF;AACvF,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,OAAO,EAAoB,MAAM,eAAe,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,aAAa,EAAiB,MAAM,UAAU,CAAC;AAEnE,MAAM,OAAO,GAAG;IACf,EAAE,EAAE,8BAA8B;IAClC,KAAK,EAAE,4CAA4C;IACnD,OAAO,EAAE,6BAA6B;IACtC,SAAS,EAAE,oCAAoC;IAC/C,KAAK,EAAE,6CAA6C;CAC3C,CAAC;AAEX,oDAAoD;AACpD,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACvC,EAAY,EACZ,IAAY,EACZ,KAAkB;IAElB,MAAM,GAAG,GAAG,IAAI,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACpC,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC9B,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;QAC3B,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,SAAS;QAC7B,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACf,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC;YAC1B,IAAI;YACJ,MAAM;YACN,SAAS,IAAI,SAAS;YACtB,IAAI;YACJ,QAAQ,IAAI,EAAE;YACd,IAAI;YACJ,eAAe,OAAO,CAAC,MAAM,CAAC,EAAE;SAChC,CAAC,CAAC;QACH,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC;YACb,IAAI,CAAC,IAAI,CAAC,qBAAqB,IAAI,EAAE,CAAC,CAAC;YACvC,SAAS;QACV,CAAC;QACD,qEAAqE;QACrE,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC,CAAC,SAAS,IAAI,WAAW,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QAClF,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;YACf,MAAM,IAAI,aAAa,CACtB,iCAAiC,IAAI,KAAK,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CACtF,CAAC;QACH,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,aAAa,IAAI,iBAAiB,CAAC,CAAC;IAC/C,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type Signal, type SignalNames } from '../signals.js';
|
|
2
|
+
import type { Comment, Feature, FeatureWriter, ItemId, ItemText, Standing, Ticket, TicketReference, Tracker } from '../tracker.js';
|
|
3
|
+
import { type GhRunner } from './api.js';
|
|
4
|
+
export declare class GitHubTracker implements Tracker, FeatureWriter {
|
|
5
|
+
readonly repo: string;
|
|
6
|
+
private readonly names;
|
|
7
|
+
private readonly trusted?;
|
|
8
|
+
private readonly api;
|
|
9
|
+
private readonly writers;
|
|
10
|
+
constructor(repo: string, gh: GhRunner, names: SignalNames, trusted?: readonly string[] | undefined);
|
|
11
|
+
private signalsOf;
|
|
12
|
+
me(): Promise<string>;
|
|
13
|
+
assignedFeatures(person: string): Promise<Feature[]>;
|
|
14
|
+
feature(id: ItemId): Promise<Feature>;
|
|
15
|
+
standing(id: ItemId): Promise<Standing>;
|
|
16
|
+
tickets(featureId: ItemId): Promise<Ticket[]>;
|
|
17
|
+
private blockedBy;
|
|
18
|
+
comments(id: ItemId): Promise<Comment[]>;
|
|
19
|
+
private isTrusted;
|
|
20
|
+
addSignal(id: ItemId, signal: Signal): Promise<void>;
|
|
21
|
+
removeSignal(id: ItemId, signal: Signal): Promise<void>;
|
|
22
|
+
comment(id: ItemId, body: string): Promise<void>;
|
|
23
|
+
reference(id: ItemId): TicketReference;
|
|
24
|
+
createFeature({ title, body }: ItemText): Promise<ItemId>;
|
|
25
|
+
createTicket(featureId: ItemId, ticket: ItemText): Promise<ItemId>;
|
|
26
|
+
block(id: ItemId, blocker: ItemId): Promise<void>;
|
|
27
|
+
private databaseId;
|
|
28
|
+
}
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
// GitHub Issues as a Tracker: a Feature is an issue with sub-issues; blocking links are issue dependencies.
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { firstLine } from '../git.js';
|
|
4
|
+
import { SIGNALS } from '../signals.js';
|
|
5
|
+
import { GitHubApi, GitHubFailure, IssueSchema, PAGE } from './api.js';
|
|
6
|
+
const CommentSchema = z.looseObject({
|
|
7
|
+
body: z.string().nullable(),
|
|
8
|
+
user: z.looseObject({ login: z.string() }).nullable(),
|
|
9
|
+
created_at: z.string(),
|
|
10
|
+
author_association: z.string().optional()
|
|
11
|
+
});
|
|
12
|
+
// Stand in for write access when the permission call is refused; a COLLABORATOR may hold only read.
|
|
13
|
+
const TIED = ['OWNER', 'MEMBER', 'COLLABORATOR'];
|
|
14
|
+
const WRITE = ['admin', 'maintain', 'write'];
|
|
15
|
+
// The issue number an id names; GitHub has no other kind of id.
|
|
16
|
+
function issue(id) {
|
|
17
|
+
if (!/^\d+$/.test(id))
|
|
18
|
+
throw new GitHubFailure(`${id} is no GitHub issue number.`);
|
|
19
|
+
return id;
|
|
20
|
+
}
|
|
21
|
+
const toFeature = (raw) => ({
|
|
22
|
+
id: String(raw.number),
|
|
23
|
+
title: raw.title,
|
|
24
|
+
body: raw.body ?? ''
|
|
25
|
+
});
|
|
26
|
+
export class GitHubTracker {
|
|
27
|
+
repo;
|
|
28
|
+
names;
|
|
29
|
+
trusted;
|
|
30
|
+
api;
|
|
31
|
+
writers = new Map();
|
|
32
|
+
constructor(repo, gh, names,
|
|
33
|
+
// factory.json's trusted list; when set it replaces the write-access default
|
|
34
|
+
trusted) {
|
|
35
|
+
this.repo = repo;
|
|
36
|
+
this.names = names;
|
|
37
|
+
this.trusted = trusted;
|
|
38
|
+
this.api = new GitHubApi(repo, gh);
|
|
39
|
+
}
|
|
40
|
+
signalsOf(raw) {
|
|
41
|
+
const labels = raw.labels.map((l) => l.name);
|
|
42
|
+
return SIGNALS.filter((s) => labels.includes(this.names[s]));
|
|
43
|
+
}
|
|
44
|
+
async me() {
|
|
45
|
+
const user = await this.api.parse('read the signed-in user', ['user'], z.looseObject({ login: z.string() }));
|
|
46
|
+
return user.login;
|
|
47
|
+
}
|
|
48
|
+
async assignedFeatures(person) {
|
|
49
|
+
const query = new URLSearchParams({
|
|
50
|
+
state: 'open',
|
|
51
|
+
labels: this.names.go,
|
|
52
|
+
assignee: person,
|
|
53
|
+
sort: 'created',
|
|
54
|
+
direction: 'asc',
|
|
55
|
+
per_page: '100'
|
|
56
|
+
});
|
|
57
|
+
const raw = await this.api.parse('list the assigned issues', [`repos/${this.repo}/issues?${query.toString()}`], z.array(IssueSchema));
|
|
58
|
+
return raw
|
|
59
|
+
.filter((i) => i.pull_request === undefined && (i.sub_issues_summary?.total ?? 0) > 0)
|
|
60
|
+
.map(toFeature);
|
|
61
|
+
}
|
|
62
|
+
async feature(id) {
|
|
63
|
+
const n = issue(id);
|
|
64
|
+
return toFeature(await this.api.parse(`read issue #${n}`, [`repos/${this.repo}/issues/${n}`], IssueSchema));
|
|
65
|
+
}
|
|
66
|
+
async standing(id) {
|
|
67
|
+
const n = issue(id);
|
|
68
|
+
const raw = await this.api.parse(`read issue #${n}`, [`repos/${this.repo}/issues/${n}`], IssueSchema);
|
|
69
|
+
return { assignees: (raw.assignees ?? []).map((a) => a.login), signals: this.signalsOf(raw) };
|
|
70
|
+
}
|
|
71
|
+
async tickets(featureId) {
|
|
72
|
+
const n = issue(featureId);
|
|
73
|
+
const children = await this.api.parse(`list the sub-issues of #${n}`, [`repos/${this.repo}/issues/${n}/sub_issues?${PAGE}`], z.array(IssueSchema));
|
|
74
|
+
const tickets = [];
|
|
75
|
+
for (const child of children) {
|
|
76
|
+
tickets.push({
|
|
77
|
+
id: String(child.number),
|
|
78
|
+
title: child.title,
|
|
79
|
+
body: child.body ?? '',
|
|
80
|
+
open: child.state === 'open',
|
|
81
|
+
signals: this.signalsOf(child),
|
|
82
|
+
blockedBy: await this.blockedBy(String(child.number))
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
return tickets;
|
|
86
|
+
}
|
|
87
|
+
async blockedBy(id) {
|
|
88
|
+
const n = issue(id);
|
|
89
|
+
const raw = await this.api.parse(`list what blocks #${n}`, [`repos/${this.repo}/issues/${n}/dependencies/blocked_by?${PAGE}`], z.array(IssueSchema));
|
|
90
|
+
return raw.map((i) => ({ id: String(i.number), open: i.state === 'open' }));
|
|
91
|
+
}
|
|
92
|
+
async comments(id) {
|
|
93
|
+
const n = issue(id);
|
|
94
|
+
const raw = await this.api.parse(`list the comments on #${n}`, [`repos/${this.repo}/issues/${n}/comments?${PAGE}`], z.array(CommentSchema));
|
|
95
|
+
const comments = [];
|
|
96
|
+
for (const c of raw) {
|
|
97
|
+
const author = c.user?.login ?? '';
|
|
98
|
+
comments.push({
|
|
99
|
+
author,
|
|
100
|
+
body: c.body ?? '',
|
|
101
|
+
at: c.created_at,
|
|
102
|
+
trusted: await this.isTrusted(author, c.author_association)
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
return comments;
|
|
106
|
+
}
|
|
107
|
+
// On the configured list, else may push; the comment's own association answers when a proxy refuses the permission call.
|
|
108
|
+
async isTrusted(login, association) {
|
|
109
|
+
// GitHub logins are case-insensitive
|
|
110
|
+
if (this.trusted !== undefined) {
|
|
111
|
+
return this.trusted.some((t) => t.toLowerCase() === login.toLowerCase());
|
|
112
|
+
}
|
|
113
|
+
const known = this.writers.get(login);
|
|
114
|
+
if (known !== undefined)
|
|
115
|
+
return known;
|
|
116
|
+
const got = await this.api.raw([
|
|
117
|
+
`repos/${this.repo}/collaborators/${encodeURIComponent(login)}/permission`
|
|
118
|
+
]);
|
|
119
|
+
// 404 means no collaborator; reading any other refusal as no access would drop the person's own answers unsaid
|
|
120
|
+
if (!got.ok && !/HTTP 404/.test(got.err)) {
|
|
121
|
+
if (association !== undefined)
|
|
122
|
+
return TIED.includes(association);
|
|
123
|
+
throw new GitHubFailure(`gh could not read the permission of ${login}: ${firstLine(got.err)}`);
|
|
124
|
+
}
|
|
125
|
+
let value = null;
|
|
126
|
+
try {
|
|
127
|
+
value = got.ok ? JSON.parse(got.out) : null;
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
// no JSON reads as no permission
|
|
131
|
+
}
|
|
132
|
+
const parsed = z.looseObject({ permission: z.string() }).safeParse(value);
|
|
133
|
+
const can = parsed.success && WRITE.includes(parsed.data.permission);
|
|
134
|
+
this.writers.set(login, can);
|
|
135
|
+
return can;
|
|
136
|
+
}
|
|
137
|
+
async addSignal(id, signal) {
|
|
138
|
+
const n = issue(id);
|
|
139
|
+
const label = this.names[signal];
|
|
140
|
+
await this.api.call(`label #${n} ${label}`, [
|
|
141
|
+
'-X',
|
|
142
|
+
'POST',
|
|
143
|
+
`repos/${this.repo}/issues/${n}/labels`,
|
|
144
|
+
'-f',
|
|
145
|
+
`labels[]=${label}`
|
|
146
|
+
]);
|
|
147
|
+
}
|
|
148
|
+
async removeSignal(id, signal) {
|
|
149
|
+
const n = issue(id);
|
|
150
|
+
const label = this.names[signal];
|
|
151
|
+
const got = await this.api.raw([
|
|
152
|
+
'-X',
|
|
153
|
+
'DELETE',
|
|
154
|
+
`repos/${this.repo}/issues/${n}/labels/${encodeURIComponent(label)}`
|
|
155
|
+
]);
|
|
156
|
+
if (!got.ok && !/404|Label does not exist/.test(got.err + got.out)) {
|
|
157
|
+
throw new GitHubFailure(`gh could not take ${label} off #${n}: ${firstLine(got.err)}`);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
async comment(id, body) {
|
|
161
|
+
const n = issue(id);
|
|
162
|
+
await this.api.call(`comment on #${n}`, [
|
|
163
|
+
'-X',
|
|
164
|
+
'POST',
|
|
165
|
+
`repos/${this.repo}/issues/${n}/comments`,
|
|
166
|
+
'-f',
|
|
167
|
+
`body=${body}`
|
|
168
|
+
]);
|
|
169
|
+
}
|
|
170
|
+
reference(id) {
|
|
171
|
+
return { id, text: `#${issue(id)}` };
|
|
172
|
+
}
|
|
173
|
+
async createFeature({ title, body }) {
|
|
174
|
+
const made = await this.api.parse(`open the issue ${title}`, ['-X', 'POST', `repos/${this.repo}/issues`, '-f', `title=${title}`, '-f', `body=${body}`], IssueSchema);
|
|
175
|
+
return String(made.number);
|
|
176
|
+
}
|
|
177
|
+
async createTicket(featureId, ticket) {
|
|
178
|
+
const id = await this.createFeature(ticket);
|
|
179
|
+
const n = issue(featureId);
|
|
180
|
+
await this.api.call(`make #${id} a sub-issue of #${n}`, [
|
|
181
|
+
'-X',
|
|
182
|
+
'POST',
|
|
183
|
+
`repos/${this.repo}/issues/${n}/sub_issues`,
|
|
184
|
+
'-F',
|
|
185
|
+
`sub_issue_id=${String(await this.databaseId(id))}`
|
|
186
|
+
]);
|
|
187
|
+
return id;
|
|
188
|
+
}
|
|
189
|
+
async block(id, blocker) {
|
|
190
|
+
const n = issue(id);
|
|
191
|
+
await this.api.call(`mark #${n} blocked by #${issue(blocker)}`, [
|
|
192
|
+
'-X',
|
|
193
|
+
'POST',
|
|
194
|
+
`repos/${this.repo}/issues/${n}/dependencies/blocked_by`,
|
|
195
|
+
'-F',
|
|
196
|
+
`issue_id=${String(await this.databaseId(blocker))}`
|
|
197
|
+
]);
|
|
198
|
+
}
|
|
199
|
+
// GitHub's own id of issue `id`, which the sub-issue and dependency calls take.
|
|
200
|
+
async databaseId(id) {
|
|
201
|
+
const n = issue(id);
|
|
202
|
+
const raw = await this.api.parse(`read issue #${n}`, [`repos/${this.repo}/issues/${n}`], IssueSchema);
|
|
203
|
+
if (raw.id === undefined)
|
|
204
|
+
throw new GitHubFailure(`GitHub gave no id for #${n}.`);
|
|
205
|
+
return raw.id;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
//# sourceMappingURL=tracker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tracker.js","sourceRoot":"","sources":["../../src/github/tracker.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type { Blocker, Comment, ItemId, Feature, FeatureWriter, ItemText, Standing, Ticket, TicketReference, Tracker } from './tracker.js';
|
|
2
|
+
export { canCreate } from './tracker.js';
|
|
3
|
+
export { featureWriterContract } from './contract/feature-writer.js';
|
|
4
|
+
export type { CodeHost, DraftRequest, Pull } from './code-host.js';
|
|
5
|
+
export type { AdapterContext, CodeHostFactory, TrackerFactory } from './adapter-module.js';
|
|
6
|
+
export { DEFAULT_SIGNAL_NAMES, SIGNALS, type Signal, type SignalNames } from './signals.js';
|
|
7
|
+
export { ConfigError, ConfigSchema, configJsonSchema, loadConfig, type Config } from './config.js';
|
|
8
|
+
export { FakeTracker, type FakeItem, type NewItem } from './fakes/tracker.js';
|
|
9
|
+
export { FakeCodeHost, type FakePull } from './fakes/code-host.js';
|
|
10
|
+
export { GitHubTracker } from './github/tracker.js';
|
|
11
|
+
export { GitHubCodeHost } from './github/code-host.js';
|
|
12
|
+
export { GitHubFailure, type GhRunner } from './github/api.js';
|
|
13
|
+
export { AzureBoardsTracker, AzureDevOpsApi, AzureDevOpsFailure, AzureReposCodeHost, openAzureDevOps, type AzureBoardsSettings, type AzureReposSettings, type AzureDevOpsSignIn } from './azure-devops/index.js';
|
|
14
|
+
export type { ContractCase } from './contract/case.js';
|
|
15
|
+
export { trackerContract, type TrackerHarness, type TrackerSubject, type TrackerWorld, type WorldComment, type WorldItem } from './contract/tracker.js';
|
|
16
|
+
export { codeHostContract, type CodeHostHarness, type CodeHostSubject, type PullView } from './contract/code-host.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { canCreate } from './tracker.js';
|
|
2
|
+
export { featureWriterContract } from './contract/feature-writer.js';
|
|
3
|
+
export { DEFAULT_SIGNAL_NAMES, SIGNALS } from './signals.js';
|
|
4
|
+
export { ConfigError, ConfigSchema, configJsonSchema, loadConfig } from './config.js';
|
|
5
|
+
export { FakeTracker } from './fakes/tracker.js';
|
|
6
|
+
export { FakeCodeHost } from './fakes/code-host.js';
|
|
7
|
+
export { GitHubTracker } from './github/tracker.js';
|
|
8
|
+
export { GitHubCodeHost } from './github/code-host.js';
|
|
9
|
+
export { GitHubFailure } from './github/api.js';
|
|
10
|
+
export { AzureBoardsTracker, AzureDevOpsApi, AzureDevOpsFailure, AzureReposCodeHost, openAzureDevOps } from './azure-devops/index.js';
|
|
11
|
+
export { trackerContract } from './contract/tracker.js';
|
|
12
|
+
export { codeHostContract } from './contract/code-host.js';
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAGrE,OAAO,EAAE,oBAAoB,EAAE,OAAO,EAAiC,MAAM,cAAc,CAAC;AAC5F,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,gBAAgB,EAAE,UAAU,EAAe,MAAM,aAAa,CAAC;AACnG,OAAO,EAAE,WAAW,EAA+B,MAAM,oBAAoB,CAAC;AAC9E,OAAO,EAAE,YAAY,EAAiB,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAiB,MAAM,iBAAiB,CAAC;AAC/D,OAAO,EACN,kBAAkB,EAClB,cAAc,EACd,kBAAkB,EAClB,kBAAkB,EAClB,eAAe,EAIf,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACN,eAAe,EAMf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACN,gBAAgB,EAIhB,MAAM,yBAAyB,CAAC"}
|
package/dist/init.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type Ask } from './ask.js';
|
|
2
|
+
import type { AzureDevOpsRequest } from './azure-devops/index.js';
|
|
3
|
+
import { type Env } from './git.js';
|
|
4
|
+
export interface InitOptions {
|
|
5
|
+
readonly root: string;
|
|
6
|
+
readonly env: Env;
|
|
7
|
+
readonly useApiKey: boolean;
|
|
8
|
+
readonly profile?: string;
|
|
9
|
+
readonly ask: Ask;
|
|
10
|
+
readonly request?: AzureDevOpsRequest;
|
|
11
|
+
}
|
|
12
|
+
export declare function runInit(o: InitOptions): Promise<number>;
|
|
13
|
+
export interface InitHost {
|
|
14
|
+
readonly env: Env;
|
|
15
|
+
readonly cwd: string;
|
|
16
|
+
readonly request?: AzureDevOpsRequest;
|
|
17
|
+
readonly ask?: Ask;
|
|
18
|
+
}
|
|
19
|
+
export declare function runInitCommand(argv: readonly string[], host: InitHost): Promise<number>;
|
package/dist/init.js
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
// `nightjar init`: a repo with a factory.json is not asked again, and the check command is always asked for, never guessed.
|
|
2
|
+
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { askOnStdin } from './ask.js';
|
|
5
|
+
import { checkMachine, Refusal } from './checks.js';
|
|
6
|
+
import { CONFIG_FILE, ConfigError, ConfigSchema, loadConfig } from './config.js';
|
|
7
|
+
import { failures, printLines } from './doctor.js';
|
|
8
|
+
import { run } from './git.js';
|
|
9
|
+
import { repoFromRemote } from './github/api.js';
|
|
10
|
+
import { say, why } from './say.js';
|
|
11
|
+
// the published schema, so a repo that is no npm project gets editor completion too
|
|
12
|
+
const SCHEMA_URL = 'https://unpkg.com/@nonameolsson/nightjar/schema/factory.schema.json';
|
|
13
|
+
// the Tracker kinds the schema takes, which the Code host takes too
|
|
14
|
+
const KINDS = ConfigSchema.shape.tracker.options.map((o) => o.shape.type.value);
|
|
15
|
+
// The problem the real schema finds with `key` of a candidate that is otherwise valid, if any.
|
|
16
|
+
function problemWith(schema, candidate, key) {
|
|
17
|
+
const parsed = schema.safeParse(candidate);
|
|
18
|
+
if (parsed.success)
|
|
19
|
+
return null;
|
|
20
|
+
return parsed.error.issues.find((i) => i.path[0] === key)?.message ?? null;
|
|
21
|
+
}
|
|
22
|
+
// Asks until the answer passes; an empty one takes the fallback, if there is one.
|
|
23
|
+
async function answer(ask, question, fallback, accept) {
|
|
24
|
+
for (;;) {
|
|
25
|
+
const got = await ask(fallback === undefined ? `${question}: ` : `${question} [${fallback}]: `);
|
|
26
|
+
if (got === null)
|
|
27
|
+
throw new Refusal(`the input ended before this was answered: ${question}`);
|
|
28
|
+
const text = got.trim() === '' ? (fallback ?? '') : got.trim();
|
|
29
|
+
const problem = accept(text);
|
|
30
|
+
if (problem === null)
|
|
31
|
+
return text;
|
|
32
|
+
console.log(` ${problem}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
// The questions of one section, each checked by the schema's own rule for its field.
|
|
36
|
+
const probing = (ask, schema, base) => ({
|
|
37
|
+
field: (key, question, fallback) => answer(ask, question, fallback, (text) => problemWith(schema, { ...base, [key]: text }, key))
|
|
38
|
+
});
|
|
39
|
+
async function origin(root, env) {
|
|
40
|
+
const got = await run('git', ['remote', 'get-url', 'origin'], root, env);
|
|
41
|
+
return got.ok ? repoFromRemote(got.out) : null;
|
|
42
|
+
}
|
|
43
|
+
const kindOf = (text) => KINDS.includes(text)
|
|
44
|
+
? null
|
|
45
|
+
: `choose ${KINDS.slice(0, -1).join(', ')} or ${KINDS.at(-1) ?? ''}`;
|
|
46
|
+
// One of Tracker and Code host: its type, then what that type needs.
|
|
47
|
+
async function section(o, which, fromOrigin, guess) {
|
|
48
|
+
const { ask } = o;
|
|
49
|
+
const schema = ConfigSchema.shape[which];
|
|
50
|
+
const label = which === 'tracker' ? 'Tracker' : 'Code host';
|
|
51
|
+
const kind = (await answer(ask, `${label}: ${KINDS.join(', ')}`, guess.kind, kindOf));
|
|
52
|
+
if (kind === 'github') {
|
|
53
|
+
const ask1 = probing(ask, schema, { type: 'github' });
|
|
54
|
+
const where = which === 'tracker' ? 'whose issues are the Features' : 'the branch is pushed to';
|
|
55
|
+
const repo = await ask1.field('repo', `GitHub repo ${where}, owner/name`, fromOrigin ?? undefined);
|
|
56
|
+
// origin answers for a repo left out, so it is written only when it is another
|
|
57
|
+
const writes = repo !== fromOrigin;
|
|
58
|
+
return { section: { type: 'github', ...(writes ? { repo } : {}) } };
|
|
59
|
+
}
|
|
60
|
+
if (kind === 'module') {
|
|
61
|
+
const interview = probing(ask, schema, { type: 'module' });
|
|
62
|
+
const path = await interview.field('path', `Module that builds the ${label}, as a path from the repo's root`);
|
|
63
|
+
return { section: { type: 'module', path } };
|
|
64
|
+
}
|
|
65
|
+
const base = {
|
|
66
|
+
type: 'azure-devops',
|
|
67
|
+
organization: 'x',
|
|
68
|
+
project: 'x',
|
|
69
|
+
featureType: 'x',
|
|
70
|
+
repo: 'x'
|
|
71
|
+
};
|
|
72
|
+
const interview = probing(ask, schema, base);
|
|
73
|
+
const organization = await interview.field('organization', 'Azure DevOps organization, as in dev.azure.com/<organization>', guess.organization);
|
|
74
|
+
const project = await interview.field('project', `Project that holds the ${which === 'tracker' ? 'Features' : 'repo'}`, guess.project);
|
|
75
|
+
if (which === 'codeHost') {
|
|
76
|
+
const repo = await interview.field('repo', 'Git repo on Azure Repos, by name');
|
|
77
|
+
return {
|
|
78
|
+
section: { type: 'azure-devops', organization, project, repo },
|
|
79
|
+
organization,
|
|
80
|
+
project
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
const featureType = await interview.field('featureType', 'Work item type that plays the Feature, such as Feature, Epic or Product Backlog Item', 'Feature');
|
|
84
|
+
const ticket = await ask('Work item type of a Ticket, for `nightjar create` (empty to leave out): ');
|
|
85
|
+
if (ticket === null)
|
|
86
|
+
throw new Refusal('the input ended before this was answered: the Ticket type');
|
|
87
|
+
const ticketType = ticket.trim();
|
|
88
|
+
return {
|
|
89
|
+
section: {
|
|
90
|
+
type: 'azure-devops',
|
|
91
|
+
organization,
|
|
92
|
+
project,
|
|
93
|
+
featureType,
|
|
94
|
+
...(ticketType ? { ticketType } : {})
|
|
95
|
+
},
|
|
96
|
+
organization,
|
|
97
|
+
project
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
async function interview(o) {
|
|
101
|
+
const fromOrigin = await origin(o.root, o.env);
|
|
102
|
+
const tracker = await section(o, 'tracker', fromOrigin, { kind: 'github' });
|
|
103
|
+
const kind = tracker.section.type;
|
|
104
|
+
const codeHost = await section(o, 'codeHost', fromOrigin, {
|
|
105
|
+
kind: kind === 'module' ? 'github' : kind,
|
|
106
|
+
...(tracker.organization === undefined ? {} : { organization: tracker.organization }),
|
|
107
|
+
...(tracker.project === undefined ? {} : { project: tracker.project })
|
|
108
|
+
});
|
|
109
|
+
const check = await answer(o.ask, 'Command that checks the work, run after each Ticket (no default)', undefined, (text) => (/\S/.test(text) ? null : 'name the command that checks the work'));
|
|
110
|
+
const listed = await answer(o.ask, 'Commands the agent may run, separated by commas, or none', check, () => null);
|
|
111
|
+
const allowedCommands = listed === 'none'
|
|
112
|
+
? []
|
|
113
|
+
: listed
|
|
114
|
+
.split(',')
|
|
115
|
+
.map((c) => c.trim())
|
|
116
|
+
.filter((c) => c !== '');
|
|
117
|
+
return {
|
|
118
|
+
$schema: SCHEMA_URL,
|
|
119
|
+
tracker: tracker.section,
|
|
120
|
+
codeHost: codeHost.section,
|
|
121
|
+
check,
|
|
122
|
+
allowedCommands
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
function ignoresFactory(root) {
|
|
126
|
+
try {
|
|
127
|
+
return readFileSync(join(root, '.gitignore'), 'utf8')
|
|
128
|
+
.split('\n')
|
|
129
|
+
.some((l) => /^\/?\.factory\/?$/.test(l.trim()));
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
export async function runInit(o) {
|
|
136
|
+
const file = join(o.root, CONFIG_FILE);
|
|
137
|
+
if (existsSync(file)) {
|
|
138
|
+
loadConfig(o.root);
|
|
139
|
+
say(`${CONFIG_FILE} is there already; keeping it`);
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
const config = await interview(o);
|
|
143
|
+
const checked = ConfigSchema.safeParse(config);
|
|
144
|
+
if (!checked.success) {
|
|
145
|
+
throw new ConfigError(checked.error.issues
|
|
146
|
+
.map((i) => `${CONFIG_FILE}: ${i.path.join('.')}: ${i.message}`)
|
|
147
|
+
.join('\n'));
|
|
148
|
+
}
|
|
149
|
+
writeFileSync(file, `${JSON.stringify(config, null, '\t')}\n`);
|
|
150
|
+
say(`wrote ${CONFIG_FILE}`);
|
|
151
|
+
}
|
|
152
|
+
if (!ignoresFactory(o.root))
|
|
153
|
+
say('add `.factory/` to .gitignore: Nightjar keeps its status and logs there');
|
|
154
|
+
const checked = await checkMachine({
|
|
155
|
+
useApiKey: o.useApiKey,
|
|
156
|
+
...(o.profile === undefined ? {} : { profile: o.profile }),
|
|
157
|
+
env: o.env,
|
|
158
|
+
cwd: o.root,
|
|
159
|
+
failFast: false,
|
|
160
|
+
...(o.request === undefined ? {} : { request: o.request })
|
|
161
|
+
});
|
|
162
|
+
printLines(checked.lines);
|
|
163
|
+
let problems = failures(checked.lines);
|
|
164
|
+
if (checked.adapters !== null && checked.trackerOk) {
|
|
165
|
+
try {
|
|
166
|
+
for (const line of await checked.adapters.prepareSignals())
|
|
167
|
+
say(line);
|
|
168
|
+
}
|
|
169
|
+
catch (fault) {
|
|
170
|
+
console.error(` FAIL Signals: ${why(fault)}`);
|
|
171
|
+
problems += 1;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
say('Signal labels not created: the Tracker could not be reached; fix that, then run `nightjar init` again.');
|
|
176
|
+
}
|
|
177
|
+
if (problems > 0) {
|
|
178
|
+
const count = problems === 1 ? '1 problem' : `${String(problems)} problems`;
|
|
179
|
+
console.error(`nightjar: ${count} above; fix it, then run \`nightjar init\` again.`);
|
|
180
|
+
return 2;
|
|
181
|
+
}
|
|
182
|
+
say('ready. Commit factory.json, give a Feature the Go, and run `nightjar doctor` any time.');
|
|
183
|
+
return 0;
|
|
184
|
+
}
|
|
185
|
+
// The `init` command: its arguments, the checkout it is run in, and a refusal said as it is.
|
|
186
|
+
export async function runInitCommand(argv, host) {
|
|
187
|
+
const profileAt = argv.indexOf('--profile');
|
|
188
|
+
const profile = profileAt < 0 ? undefined : argv[profileAt + 1];
|
|
189
|
+
if (profileAt >= 0 && (profile === undefined || profile.startsWith('--'))) {
|
|
190
|
+
console.error('nightjar: --profile needs a value');
|
|
191
|
+
return 2;
|
|
192
|
+
}
|
|
193
|
+
const unknown = argv.find((a, i) => a !== '--use-api-key' && a !== '--profile' && (profileAt < 0 || i !== profileAt + 1));
|
|
194
|
+
if (unknown !== undefined) {
|
|
195
|
+
console.error(`nightjar: unknown argument ${unknown}\n\nusage: nightjar init [--use-api-key] [--profile NAME]`);
|
|
196
|
+
return 2;
|
|
197
|
+
}
|
|
198
|
+
const env = { ...host.env, GIT_TERMINAL_PROMPT: '0' };
|
|
199
|
+
const asker = host.ask === undefined ? askOnStdin() : null;
|
|
200
|
+
try {
|
|
201
|
+
const top = await run('git', ['rev-parse', '--show-toplevel'], host.cwd, env);
|
|
202
|
+
if (!top.ok) {
|
|
203
|
+
console.error('nightjar: not inside a git checkout; run init at the root of the repo.');
|
|
204
|
+
return 2;
|
|
205
|
+
}
|
|
206
|
+
return await runInit({
|
|
207
|
+
root: top.out.trim(),
|
|
208
|
+
env,
|
|
209
|
+
useApiKey: argv.includes('--use-api-key'),
|
|
210
|
+
...(profile === undefined ? {} : { profile }),
|
|
211
|
+
ask: host.ask ?? asker?.ask ?? (() => Promise.resolve(null)),
|
|
212
|
+
...(host.request === undefined ? {} : { request: host.request })
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
catch (fault) {
|
|
216
|
+
if (!(fault instanceof Refusal) && !(fault instanceof ConfigError))
|
|
217
|
+
throw fault;
|
|
218
|
+
console.error(`nightjar: ${fault.message}`);
|
|
219
|
+
return 2;
|
|
220
|
+
}
|
|
221
|
+
finally {
|
|
222
|
+
asker?.close();
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
//# sourceMappingURL=init.js.map
|
package/dist/init.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"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"}
|
package/dist/ledger.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface Entry {
|
|
2
|
+
readonly at: string;
|
|
3
|
+
readonly repo: string;
|
|
4
|
+
readonly feature: string;
|
|
5
|
+
readonly ticket: string | null;
|
|
6
|
+
readonly branch: string;
|
|
7
|
+
readonly step: 'build' | 'fix' | 'review' | 'step';
|
|
8
|
+
readonly session: string;
|
|
9
|
+
readonly costUsd: number;
|
|
10
|
+
readonly outcome: string;
|
|
11
|
+
}
|
|
12
|
+
export declare function record(path: string, entry: Entry): void;
|
|
13
|
+
export declare function spentOn(path: string, now: Date): number;
|