conductor-board 2.3.0 → 2.4.1

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/dist/index.html CHANGED
@@ -6,10 +6,10 @@
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
7
  <meta name="theme-color" content="#0a0a0f" />
8
8
  <title>Agent Conductor — Board</title>
9
- <script type="module" crossorigin src="./assets/index-B-Kwn4YB.js"></script>
9
+ <script type="module" crossorigin src="./assets/index-C18cfwCs.js"></script>
10
10
  <link rel="modulepreload" crossorigin href="./assets/motion-Dmvx5jlk.js">
11
11
  <link rel="modulepreload" crossorigin href="./assets/yaml-NA7d4LV6.js">
12
- <link rel="stylesheet" crossorigin href="./assets/index-a4RLv680.css">
12
+ <link rel="stylesheet" crossorigin href="./assets/index-BlmR5bke.css">
13
13
  </head>
14
14
  <body>
15
15
  <div id="root"></div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "conductor-board",
3
- "version": "2.3.0",
3
+ "version": "2.4.1",
4
4
  "description": "Gated workflows for AI agents — live Kanban board included",
5
5
  "license": "MIT",
6
6
  "author": "mettafive",
package/server/server.js CHANGED
@@ -909,6 +909,73 @@ export function startServer({ statusPath, conductorPath: explicitConductor, port
909
909
  });
910
910
  return;
911
911
  }
912
+ // developer notes / directives on activity cards — the flow-manager feedback loop.
913
+ // Body actions: create {card, cardTitle, step, text, directive, scope}; edit {id, text, directive,
914
+ // scope}; remove {id, action:"remove"}. Edits/removals are logged to the note's audit history,
915
+ // never destroyed — the record stays, the footnote grows ("edited from X to Y").
916
+ if (req.method === "POST" && (m = url.match(/^\/api\/workflow\/([^/]+)\/comment$/))) {
917
+ const wf = findWf(decodeURIComponent(m[1]));
918
+ if (!wf) return json(res, 404, { error: "not found" });
919
+ readBody(req).then((bodyStr) => {
920
+ let body;
921
+ try {
922
+ body = JSON.parse(bodyStr || "{}");
923
+ } catch {
924
+ return json(res, 400, { error: "invalid request body" });
925
+ }
926
+ let status;
927
+ try {
928
+ status = JSON.parse(fs.readFileSync(wf.statusPath, "utf8"));
929
+ } catch {
930
+ return json(res, 500, { error: "could not read status.json" });
931
+ }
932
+ const notes = (status.developer_notes = Array.isArray(status.developer_notes) ? status.developer_notes : []);
933
+ const at = new Date().toISOString();
934
+ const text = typeof body.text === "string" ? body.text.trim() : "";
935
+
936
+ if (body.id) {
937
+ const n = notes.find((x) => x && x.id === body.id);
938
+ if (!n) return json(res, 404, { error: "note not found" });
939
+ n.history = Array.isArray(n.history) ? n.history : [];
940
+ if (body.action === "remove") {
941
+ n.history.push({ at, action: "removed", from: n.text });
942
+ n.status = "removed";
943
+ } else {
944
+ if (n.text !== text)
945
+ n.history.push({ at, action: n.status === "removed" ? "restored" : "edited", from: n.text, to: text });
946
+ n.text = text;
947
+ n.directive = !!body.directive;
948
+ if (typeof body.scope === "string") n.scope = body.scope;
949
+ n.updated_at = at;
950
+ n.status = "open"; // an edit reopens the ask so the next run reconsiders it
951
+ delete n.resolution;
952
+ }
953
+ } else {
954
+ // create
955
+ if (!body.card || !text) return json(res, 400, { error: "card id and text required" });
956
+ notes.push({
957
+ id: `${body.card}:${Date.now()}`,
958
+ at,
959
+ updated_at: at,
960
+ step: body.step || "",
961
+ card: body.card,
962
+ card_title: typeof body.cardTitle === "string" ? body.cardTitle : undefined,
963
+ text,
964
+ directive: !!body.directive,
965
+ scope: typeof body.scope === "string" ? body.scope : undefined,
966
+ status: "open",
967
+ history: [{ at, action: "created", to: text }],
968
+ });
969
+ }
970
+ try {
971
+ fs.writeFileSync(wf.statusPath, JSON.stringify(status, null, 2));
972
+ } catch (e) {
973
+ return json(res, 500, { error: `write failed: ${e.message}` });
974
+ }
975
+ return json(res, 200, { ok: true });
976
+ });
977
+ return;
978
+ }
912
979
  if ((m = url.match(/^\/api\/workflow\/([^/]+)\/history$/))) {
913
980
  const wf = findWf(decodeURIComponent(m[1]));
914
981
  return wf ? json(res, 200, listHistory(wf.historyDir)) : json(res, 404, { error: "not found" });