@nanocollective/roster 0.1.0-alpha.5 → 0.1.0-alpha.50
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/README.md +70 -84
- package/dist/cli.js +4833 -2752
- package/docs/README.md +9 -6
- package/docs/agents.md +24 -20
- package/docs/architecture.md +13 -5
- package/docs/charters/analyst.md +65 -0
- package/docs/charters/cmo.md +69 -0
- package/docs/charters/community.md +63 -0
- package/docs/charters/cto.md +71 -0
- package/docs/charters/designer.md +65 -0
- package/docs/charters/devops.md +65 -0
- package/docs/charters/pm.md +70 -0
- package/docs/charters/qa.md +65 -0
- package/docs/charters/support.md +60 -0
- package/docs/charters/writer.md +63 -0
- package/docs/commands.md +93 -7
- package/docs/concepts.md +61 -14
- package/docs/cost.md +36 -1
- package/docs/developing.md +16 -21
- package/docs/doctor-codes.md +10 -2
- package/docs/export.md +2 -0
- package/docs/extending.md +2 -2
- package/docs/getting-started.md +128 -78
- package/docs/images/brain.jpg +0 -0
- package/docs/images/org.jpg +0 -0
- package/docs/images/prompt.jpg +0 -0
- package/docs/images/setup-org.jpg +0 -0
- package/docs/images/setup-plan.jpg +0 -0
- package/docs/images/staff.jpg +0 -0
- package/docs/manual-steps.md +94 -123
- package/docs/memory.md +21 -3
- package/docs/org-yaml.md +40 -2
- package/docs/portal.md +165 -48
- package/docs/prompts.md +31 -4
- package/docs/security.md +37 -5
- package/docs/session-workflow.md +63 -17
- package/docs/staff-yaml.md +30 -3
- package/docs/troubleshooting.md +8 -8
- package/docs/upgrading.md +9 -3
- package/docs/writing-a-charter.md +28 -0
- package/package.json +18 -20
- package/templates/brain/.github/workflows/%%STAFF%%-daily.yaml +26 -1
- package/templates/brain/.github/workflows/%%STAFF%%-mention.yaml +41 -7
- package/templates/brain/CHARTER.md +3 -3
- package/templates/brain/README.md +1 -0
- package/templates/brain/log/decisions.md +3 -0
- package/templates/brain/staff.yaml +4 -1
- package/templates/brain/strategy/ideas.md +7 -0
- package/templates/briefs/priorities.md +46 -0
- package/templates/ops/.github/workflows/session.yaml +236 -15
- package/templates/ops/agents.mjs +7 -3
- package/templates/ops/compose.mjs +31 -3
- package/templates/ops/inflight.mjs +157 -0
- package/templates/ops/org/operating.md +43 -4
- package/templates/ops/org/voice.md +9 -0
- package/templates/ops/prompts/_inflight.md +14 -0
- package/templates/ops/prompts/_paths.md +2 -1
- package/templates/ops/prompts/daily.md +37 -9
- package/templates/ops/prompts/mention.md +21 -0
- package/templates/ops/run-record.mjs +146 -0
- package/templates/portal/css/base.css +167 -73
- package/templates/portal/css/brain.css +23 -20
- package/templates/portal/css/diff.css +10 -9
- package/templates/portal/css/graph.css +12 -7
- package/templates/portal/css/health.css +13 -11
- package/templates/portal/css/home.css +93 -0
- package/templates/portal/css/inbox.css +45 -25
- package/templates/portal/css/layout.css +90 -46
- package/templates/portal/css/markdown.css +36 -14
- package/templates/portal/css/runs.css +13 -0
- package/templates/portal/css/setup.css +116 -34
- package/templates/portal/index.html +21 -9
- package/templates/portal/js/api.js +44 -4
- package/templates/portal/js/app.js +94 -9
- package/templates/portal/js/dialog.js +83 -0
- package/templates/portal/js/homesort.js +174 -0
- package/templates/portal/js/icons.js +37 -0
- package/templates/portal/js/inflight.js +18 -0
- package/templates/portal/js/md.js +5 -2
- package/templates/portal/js/mdedit.js +84 -0
- package/templates/portal/js/readiness.js +70 -0
- package/templates/portal/js/refresh.js +10 -2
- package/templates/portal/js/state.js +11 -5
- package/templates/portal/js/views/app.js +24 -7
- package/templates/portal/js/views/brain.js +1 -1
- package/templates/portal/js/views/checklist.js +10 -4
- package/templates/portal/js/views/credential.js +84 -0
- package/templates/portal/js/views/graph.js +1 -1
- package/templates/portal/js/views/health.js +17 -4
- package/templates/portal/js/views/hire.js +593 -0
- package/templates/portal/js/views/home.js +546 -0
- package/templates/portal/js/views/inbox.js +226 -70
- package/templates/portal/js/views/org.js +46 -106
- package/templates/portal/js/views/orgedit.js +234 -0
- package/templates/portal/js/views/paste.js +87 -21
- package/templates/portal/js/views/prompt.js +11 -4
- package/templates/portal/js/views/repos.js +20 -15
- package/templates/portal/js/views/runonce.js +94 -0
- package/templates/portal/js/views/runs.js +170 -0
- package/templates/portal/js/views/setup.js +261 -75
- package/templates/portal/js/views/staff.js +170 -243
- package/templates/portal/js/views/todo.js +62 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/* The agent's credential, stored once for the org.
|
|
2
|
+
*
|
|
3
|
+
* The value goes from this box to the local server in a POST, and from there to gh on its
|
|
4
|
+
* standard input. It is not kept in the page after it is sent, and nothing echoes it back. */
|
|
5
|
+
|
|
6
|
+
import { getCredential, storeCredential } from "../api.js";
|
|
7
|
+
import { el } from "../dom.js";
|
|
8
|
+
|
|
9
|
+
/** @param opts.bare drawn inside a step that already has a title. `onStatus(done)` hears whether one is stored. */
|
|
10
|
+
export function credentialPanel(opts = {}) {
|
|
11
|
+
const box = el("div", { className: opts.bare ? "" : "manual" });
|
|
12
|
+
if (!opts.bare) box.append(el("b", { textContent: "Agent credential" }));
|
|
13
|
+
const body = el("div");
|
|
14
|
+
box.append(body);
|
|
15
|
+
body.append(el("p", { className: "sub", textContent: "Checking…" }));
|
|
16
|
+
|
|
17
|
+
getCredential()
|
|
18
|
+
.then((c) => {
|
|
19
|
+
opts.onStatus?.(Boolean(c.stored ?? c.orgSecret));
|
|
20
|
+
draw(body, c, opts);
|
|
21
|
+
})
|
|
22
|
+
.catch((err) => body.replaceChildren(el("p", { className: "err", textContent: String(err.message || err) })));
|
|
23
|
+
return box;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function draw(body, c, opts = {}) {
|
|
27
|
+
body.replaceChildren();
|
|
28
|
+
|
|
29
|
+
if (!(c.brains ?? []).length) {
|
|
30
|
+
// Inside a step, the step's own hint already says when this opens.
|
|
31
|
+
if (!opts.bare) body.append(el("p", { className: "sub", textContent: "Available after your first hire. You only add it once." }));
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const form = el("div", { className: "credform" });
|
|
36
|
+
const input = el("input", { type: "password", placeholder: "Paste it here", autocomplete: "off", className: "textfield" });
|
|
37
|
+
const go = el("button", { className: "btn primary", textContent: "Save" });
|
|
38
|
+
const out = el("div");
|
|
39
|
+
form.append(
|
|
40
|
+
...(c.howTo ? [el("p", { className: "sub", textContent: "To get one, " + c.howTo })] : []),
|
|
41
|
+
input,
|
|
42
|
+
el("div", { className: "row" }, [go]),
|
|
43
|
+
out,
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
// Stored already, on the org or on every brain repo: say so, and keep replacing it one click away.
|
|
47
|
+
if (c.stored ?? c.orgSecret) {
|
|
48
|
+
const replace = el("button", { className: "ghbtn", textContent: "Replace it" });
|
|
49
|
+
replace.onclick = () => {
|
|
50
|
+
replace.remove();
|
|
51
|
+
form.hidden = false;
|
|
52
|
+
input.focus?.();
|
|
53
|
+
};
|
|
54
|
+
form.hidden = true;
|
|
55
|
+
body.append(el("p", { className: "okline", textContent: "✓ Stored as " + c.name + "." }), replace, form);
|
|
56
|
+
} else {
|
|
57
|
+
body.append(form);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
go.onclick = async () => {
|
|
61
|
+
const value = String(input.value ?? "").trim();
|
|
62
|
+
if (!value) {
|
|
63
|
+
input.focus?.();
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
go.disabled = true;
|
|
67
|
+
go.textContent = "Saving…";
|
|
68
|
+
try {
|
|
69
|
+
const r = await storeCredential(value, false);
|
|
70
|
+
input.value = "";
|
|
71
|
+
if (!r.ok) throw new Error(r.error);
|
|
72
|
+
opts.onStatus?.(true);
|
|
73
|
+
out.replaceChildren(
|
|
74
|
+
...(r.fellBack ? [el("p", { className: "sub", textContent: "Saved on each repo instead: " + r.fellBack })] : []),
|
|
75
|
+
el("p", { className: "okline", textContent: "✓ Saved." }),
|
|
76
|
+
);
|
|
77
|
+
} catch (err) {
|
|
78
|
+
out.replaceChildren(el("p", { className: "err", textContent: String(err.message || err) }));
|
|
79
|
+
} finally {
|
|
80
|
+
go.disabled = false;
|
|
81
|
+
go.textContent = "Save";
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
}
|
|
@@ -53,7 +53,7 @@ function drawGraph(canvas, wrap, s) {
|
|
|
53
53
|
}
|
|
54
54
|
const groups = [...members.keys()].sort((a, b) => members.get(b).length - members.get(a).length);
|
|
55
55
|
|
|
56
|
-
const PALETTE = ["#
|
|
56
|
+
const PALETTE = ["#30d158","#0a84ff","#bf5af2","#ff9f0a","#64d2ff","#ff453a","#ffcc00","#ff375f","#5e5ce6","#ac8e68"];
|
|
57
57
|
const colour = new Map(groups.map((g, i) => [g, PALETTE[i % PALETTE.length]]));
|
|
58
58
|
|
|
59
59
|
// The ring grows with the number of groups so they never crowd, and each group keeps its
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
/* Is the scaffolding still there, has the agent been running, and what does lint say. */
|
|
2
2
|
|
|
3
3
|
import { post } from "../api.js";
|
|
4
|
+
import { askYes } from "../dialog.js";
|
|
4
5
|
import { ago, el, esc, kb } from "../dom.js";
|
|
5
6
|
import { inline } from "../md.js";
|
|
6
7
|
import { render } from "../router.js";
|
|
7
8
|
import { S, staff } from "../state.js";
|
|
8
9
|
import { checklist } from "./checklist.js";
|
|
9
10
|
import { copyAmendBrief } from "./prompt.js";
|
|
11
|
+
import { runOnce } from "./runonce.js";
|
|
10
12
|
|
|
11
13
|
const DAYS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
|
12
14
|
|
|
@@ -81,7 +83,18 @@ export function viewHealth(m) {
|
|
|
81
83
|
doctor, bordered boxes for the prompt audit, cards with two buttons each for lint. Same
|
|
82
84
|
question in all three, so one shape: a heading that carries its own count, a line saying
|
|
83
85
|
what the section is, the findings as rows, and the section's actions at the end. */
|
|
84
|
-
|
|
86
|
+
/* A workflow that has never run is unproven, and the way to prove it is to run it. Here
|
|
87
|
+
because Health is where "unproven" is read; a success re-runs the checks below. */
|
|
88
|
+
let doctor = null;
|
|
89
|
+
m.append(
|
|
90
|
+
runOnce({
|
|
91
|
+
staff: s.handle,
|
|
92
|
+
name: s.name,
|
|
93
|
+
onDone: (ok) => ok && doctor && checklist(doctor.body, { shell: doctor }),
|
|
94
|
+
}),
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
doctor = section(m, "The org, from roster doctor", "doctor");
|
|
85
98
|
checklist(doctor.body, { shell: doctor });
|
|
86
99
|
|
|
87
100
|
/* What is wrong with what this agent is sent. It used to sit in the tree on the Prompt
|
|
@@ -132,7 +145,7 @@ function memoryProblems({ body, actions, say }, s) {
|
|
|
132
145
|
const { row, body: text } = finding(
|
|
133
146
|
p.level === "error" ? "error" : "warning",
|
|
134
147
|
{ html: inline(p.message) },
|
|
135
|
-
[p.rule, p.line ? "INDEX.md:" + p.line : ""],
|
|
148
|
+
[p.rule, p.line ? "INDEX.md:" + p.line : (p.file ?? "")],
|
|
136
149
|
);
|
|
137
150
|
const status = el("span", { className: "meta" });
|
|
138
151
|
const btn = el("button", { className: "ghbtn", textContent: "Ask " + s.handle.toUpperCase() + " to fix" });
|
|
@@ -263,13 +276,13 @@ export async function askToFix(s, problems, btn, status) {
|
|
|
263
276
|
"",
|
|
264
277
|
"| rule | where | what |",
|
|
265
278
|
"|---|---|---|",
|
|
266
|
-
...problems.map((p) => "| `" + p.rule + "` | " + (p.line ? "INDEX.md:" + p.line : "—") + " | " +
|
|
279
|
+
...problems.map((p) => "| `" + p.rule + "` | " + (p.line ? "INDEX.md:" + p.line : (p.file ?? "—")) + " | " +
|
|
267
280
|
String(p.message).replace(/\|/g, "\\|") + " |"),
|
|
268
281
|
"",
|
|
269
282
|
"Fix in your next session and close this.",
|
|
270
283
|
].join("\n");
|
|
271
284
|
|
|
272
|
-
if (!
|
|
285
|
+
if (!(await askYes({ title: "Open an issue in " + s.brain + "?", confirm: "Open it" }))) return;
|
|
273
286
|
btn.disabled = true;
|
|
274
287
|
status.textContent = "opening…";
|
|
275
288
|
status.className = "meta";
|