blacksmith-organization-system 1.6.0 → 1.7.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.
Files changed (83) hide show
  1. package/dist/bos.d.ts +15 -0
  2. package/dist/bos.js +54 -0
  3. package/dist/bos.js.map +1 -1
  4. package/dist/core/omnis.d.ts +29 -4
  5. package/dist/core/omnis.js +93 -18
  6. package/dist/core/omnis.js.map +1 -1
  7. package/dist/core/patterning.d.ts +19 -0
  8. package/dist/core/patterning.js +61 -0
  9. package/dist/core/patterning.js.map +1 -0
  10. package/dist/core/ruling.d.ts +34 -0
  11. package/dist/core/ruling.js +97 -0
  12. package/dist/core/ruling.js.map +1 -0
  13. package/dist/index.d.ts +2 -0
  14. package/dist/index.js +2 -0
  15. package/dist/index.js.map +1 -1
  16. package/dist/models/almanac/load.d.ts +12 -0
  17. package/dist/models/almanac/load.js +38 -0
  18. package/dist/models/almanac/load.js.map +1 -0
  19. package/dist/models/index.d.ts +1 -0
  20. package/dist/models/index.js +1 -0
  21. package/dist/models/index.js.map +1 -1
  22. package/dist/models/workshop/class.d.ts +1 -0
  23. package/dist/models/workshop/class.js +4 -0
  24. package/dist/models/workshop/class.js.map +1 -1
  25. package/dist/models/workshop/locate.js +12 -5
  26. package/dist/models/workshop/locate.js.map +1 -1
  27. package/dist/procedures/index.d.ts +3 -0
  28. package/dist/procedures/index.js +3 -0
  29. package/dist/procedures/index.js.map +1 -1
  30. package/dist/procedures/inspecting/_index.js +2 -0
  31. package/dist/procedures/inspecting/_index.js.map +1 -1
  32. package/dist/procedures/inspecting/read-omnis.d.ts +2 -0
  33. package/dist/procedures/inspecting/read-omnis.js +14 -0
  34. package/dist/procedures/inspecting/read-omnis.js.map +1 -0
  35. package/dist/procedures/inspecting/report.d.ts +6 -0
  36. package/dist/procedures/inspecting/report.js +1 -0
  37. package/dist/procedures/inspecting/report.js.map +1 -1
  38. package/dist/procedures/inspecting/rules.d.ts +1 -0
  39. package/dist/procedures/inspecting/rules.js +10 -0
  40. package/dist/procedures/inspecting/rules.js.map +1 -1
  41. package/dist/procedures/judging/_index.d.ts +4 -0
  42. package/dist/procedures/judging/_index.js +8 -0
  43. package/dist/procedures/judging/_index.js.map +1 -0
  44. package/dist/procedures/judging/context.d.ts +10 -0
  45. package/dist/procedures/judging/context.js +2 -0
  46. package/dist/procedures/judging/context.js.map +1 -0
  47. package/dist/procedures/judging/steps.d.ts +4 -0
  48. package/dist/procedures/judging/steps.js +21 -0
  49. package/dist/procedures/judging/steps.js.map +1 -0
  50. package/dist/procedures/recalling/_index.d.ts +4 -0
  51. package/dist/procedures/recalling/_index.js +8 -0
  52. package/dist/procedures/recalling/_index.js.map +1 -0
  53. package/dist/procedures/recalling/context.d.ts +10 -0
  54. package/dist/procedures/recalling/context.js +2 -0
  55. package/dist/procedures/recalling/context.js.map +1 -0
  56. package/dist/procedures/recalling/steps.d.ts +4 -0
  57. package/dist/procedures/recalling/steps.js +12 -0
  58. package/dist/procedures/recalling/steps.js.map +1 -0
  59. package/dist/procedures/sealing/_index.d.ts +5 -0
  60. package/dist/procedures/sealing/_index.js +11 -0
  61. package/dist/procedures/sealing/_index.js.map +1 -0
  62. package/dist/procedures/sealing/context.d.ts +20 -0
  63. package/dist/procedures/sealing/context.js +4 -0
  64. package/dist/procedures/sealing/context.js.map +1 -0
  65. package/dist/procedures/sealing/steps.d.ts +9 -0
  66. package/dist/procedures/sealing/steps.js +44 -0
  67. package/dist/procedures/sealing/steps.js.map +1 -0
  68. package/dist/tools/_index.js +2 -0
  69. package/dist/tools/_index.js.map +1 -1
  70. package/dist/tools/almanac.d.ts +1 -0
  71. package/dist/tools/almanac.js +56 -0
  72. package/dist/tools/almanac.js.map +1 -0
  73. package/dist/tools/project.js +28 -0
  74. package/dist/tools/project.js.map +1 -1
  75. package/dist/views/almanac.d.ts +5 -0
  76. package/dist/views/almanac.js +59 -0
  77. package/dist/views/almanac.js.map +1 -0
  78. package/dist/views/sealing.d.ts +2 -0
  79. package/dist/views/sealing.js +26 -0
  80. package/dist/views/sealing.js.map +1 -0
  81. package/package.json +4 -1
  82. package/resources/almanac/patterning/bos-core.json +90 -0
  83. package/resources/almanac/rulesets/bos-environment.json +141 -0
@@ -0,0 +1,56 @@
1
+ // bos almanac <tool>: the rules of the environment and the situations met before
2
+ import { tool } from "../core/tool.js";
3
+ import { judgeText, recallText, rulesText } from "../views/almanac.js";
4
+ const dirArg = {
5
+ name: "dir",
6
+ type: "string",
7
+ info: "a path inside the project whose docs/almanac/ comes first (default: current directory)",
8
+ };
9
+ export const almanacTools = [
10
+ tool({
11
+ model: "almanac",
12
+ name: "rules",
13
+ info: "every ruleset of the almanac (the project's docs/almanac/, then the core's), rule by rule",
14
+ args: [dirArg],
15
+ run: (bos, input) => bos.almanac(input.dir),
16
+ render: rulesText,
17
+ }),
18
+ tool({
19
+ model: "almanac",
20
+ name: "judge",
21
+ info: 'does a case break a rule: in words ("Cleo pushes to master") or JSON ({"action":"push"…})',
22
+ args: [
23
+ {
24
+ name: "case",
25
+ type: "string",
26
+ info: "the case, quoted",
27
+ positional: true,
28
+ required: true,
29
+ },
30
+ dirArg,
31
+ ],
32
+ run: (bos, input) => bos.judge(String(input.case), { dir: input.dir }),
33
+ render: judgeText,
34
+ }),
35
+ tool({
36
+ model: "almanac",
37
+ name: "recall",
38
+ info: "the chains of events met before that hold these events, and what usually comes next",
39
+ args: [
40
+ {
41
+ name: "events",
42
+ type: "string",
43
+ info: "events so far, comma-separated: commit,hook:bump-version",
44
+ positional: true,
45
+ required: true,
46
+ },
47
+ dirArg,
48
+ ],
49
+ run: (bos, input) => bos.recall(String(input.events)
50
+ .split(",")
51
+ .map((event) => event.trim())
52
+ .filter(Boolean), { dir: input.dir }),
53
+ render: recallText,
54
+ }),
55
+ ];
56
+ //# sourceMappingURL=almanac.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"almanac.js","sourceRoot":"","sources":["../../src/tools/almanac.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAEvE,MAAM,MAAM,GAAG;IACb,IAAI,EAAE,KAAK;IACX,IAAI,EAAE,QAAiB;IACvB,IAAI,EAAE,wFAAwF;CAC/F,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,IAAI,CAAC;QACH,KAAK,EAAE,SAAS;QAChB,IAAI,EAAE,OAAO;QACb,IAAI,EAAE,2FAA2F;QACjG,IAAI,EAAE,CAAC,MAAM,CAAC;QACd,GAAG,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,GAAyB,CAAC;QACjE,MAAM,EAAE,SAAS;KAClB,CAAC;IACF,IAAI,CAAC;QACH,KAAK,EAAE,SAAS;QAChB,IAAI,EAAE,OAAO;QACb,IAAI,EAAE,2FAA2F;QACjG,IAAI,EAAE;YACJ;gBACE,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,kBAAkB;gBACxB,UAAU,EAAE,IAAI;gBAChB,QAAQ,EAAE,IAAI;aACf;YACD,MAAM;SACP;QACD,GAAG,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,GAAyB,EAAE,CAAC;QAC5F,MAAM,EAAE,SAAS;KAClB,CAAC;IACF,IAAI,CAAC;QACH,KAAK,EAAE,SAAS;QAChB,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,qFAAqF;QAC3F,IAAI,EAAE;YACJ;gBACE,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,0DAA0D;gBAChE,UAAU,EAAE,IAAI;gBAChB,QAAQ,EAAE,IAAI;aACf;YACD,MAAM;SACP;QACD,GAAG,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAClB,GAAG,CAAC,MAAM,CACR,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC;aACjB,KAAK,CAAC,GAAG,CAAC;aACV,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;aAC5B,MAAM,CAAC,OAAO,CAAC,EAClB,EAAE,GAAG,EAAE,KAAK,CAAC,GAAyB,EAAE,CACzC;QACH,MAAM,EAAE,UAAU;KACnB,CAAC;CACH,CAAC"}
@@ -1,6 +1,12 @@
1
1
  // bos project <tool>: the project around the current directory
2
2
  import { tool } from "../core/tool.js";
3
3
  import { creditText } from "../views/crediting.js";
4
+ import { sealText } from "../views/sealing.js";
5
+ const dirArg = {
6
+ name: "dir",
7
+ type: "string",
8
+ info: "a path inside the project (default: current directory)",
9
+ };
4
10
  export const projectTools = [
5
11
  tool({
6
12
  model: "project",
@@ -18,5 +24,27 @@ export const projectTools = [
18
24
  run: (bos, input) => bos.authors({ dir: input.dir, dryRun: Boolean(input.dryRun) }),
19
25
  render: creditText,
20
26
  }),
27
+ tool({
28
+ model: "project",
29
+ name: "omnis",
30
+ info: "the project's halo (.bos/.omnis.toml) now against the sealed one: what was added, changed, removed",
31
+ readOnly: true,
32
+ args: [dirArg],
33
+ run: (bos, input) => bos.omnis({ dir: input.dir }),
34
+ render: sealText,
35
+ }),
36
+ tool({
37
+ model: "project",
38
+ name: "seal",
39
+ info: "write the project's halo into .bos/.omnis.toml (only when something changed)",
40
+ readOnly: false,
41
+ args: [dirArg, { name: "dryRun", type: "boolean", info: "only say what would be written" }],
42
+ run: (bos, input) => bos.omnis({
43
+ dir: input.dir,
44
+ seal: true,
45
+ dryRun: Boolean(input.dryRun),
46
+ }),
47
+ render: sealText,
48
+ }),
21
49
  ];
22
50
  //# sourceMappingURL=project.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"project.js","sourceRoot":"","sources":["../../src/tools/project.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAEnD,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,IAAI,CAAC;QACH,KAAK,EAAE,SAAS;QAChB,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,+FAA+F;QACrG,QAAQ,EAAE,KAAK;QACf,IAAI,EAAE;YACJ;gBACE,IAAI,EAAE,KAAK;gBACX,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,wDAAwD;aAC/D;YACD,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,gCAAgC,EAAE;SAC5E;QACD,GAAG,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAClB,GAAG,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,GAAyB,EAAE,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;QACtF,MAAM,EAAE,UAAU;KACnB,CAAC;CACH,CAAC"}
1
+ {"version":3,"file":"project.js","sourceRoot":"","sources":["../../src/tools/project.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAE/C,MAAM,MAAM,GAAG;IACb,IAAI,EAAE,KAAK;IACX,IAAI,EAAE,QAAiB;IACvB,IAAI,EAAE,wDAAwD;CAC/D,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,IAAI,CAAC;QACH,KAAK,EAAE,SAAS;QAChB,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,+FAA+F;QACrG,QAAQ,EAAE,KAAK;QACf,IAAI,EAAE;YACJ;gBACE,IAAI,EAAE,KAAK;gBACX,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,wDAAwD;aAC/D;YACD,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,gCAAgC,EAAE;SAC5E;QACD,GAAG,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAClB,GAAG,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,GAAyB,EAAE,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;QACtF,MAAM,EAAE,UAAU;KACnB,CAAC;IACF,IAAI,CAAC;QACH,KAAK,EAAE,SAAS;QAChB,IAAI,EAAE,OAAO;QACb,IAAI,EAAE,oGAAoG;QAC1G,QAAQ,EAAE,IAAI;QACd,IAAI,EAAE,CAAC,MAAM,CAAC;QACd,GAAG,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,GAAyB,EAAE,CAAC;QACxE,MAAM,EAAE,QAAQ;KACjB,CAAC;IACF,IAAI,CAAC;QACH,KAAK,EAAE,SAAS;QAChB,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,8EAA8E;QACpF,QAAQ,EAAE,KAAK;QACf,IAAI,EAAE,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,gCAAgC,EAAE,CAAC;QAC3F,GAAG,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAClB,GAAG,CAAC,KAAK,CAAC;YACR,GAAG,EAAE,KAAK,CAAC,GAAyB;YACpC,IAAI,EAAE,IAAI;YACV,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC;SAC9B,CAAC;QACJ,MAAM,EAAE,QAAQ;KACjB,CAAC;CACH,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { Almanac } from "../models/index.ts";
2
+ import type { JudgeContext, RecallContext } from "../procedures/index.ts";
3
+ export declare function judgeText({ judgement }: JudgeContext): string;
4
+ export declare function rulesText(almanac: Almanac): string;
5
+ export declare function recallText({ events, prediction, chains }: RecallContext): string;
@@ -0,0 +1,59 @@
1
+ const VERDICT = {
2
+ allowed: "ALLOWED",
3
+ ask: "ASK FIRST",
4
+ violation: "VIOLATION",
5
+ unknown: "UNKNOWN",
6
+ };
7
+ const fields = (subject) => Object.entries(subject)
8
+ .map(([field, value]) => `${field}=${Array.isArray(value) ? value.join(",") : value}`)
9
+ .join(" ");
10
+ const ruleLine = (rule) => `${rule.ruleset}/${rule.id}: ${rule.statement}${rule.source ? ` (${rule.source})` : ""}`;
11
+ export function judgeText({ judgement }) {
12
+ if (!judgement) {
13
+ return "no judgement";
14
+ }
15
+ const lines = [`${VERDICT[judgement.verdict]} ${fields(judgement.case)}`];
16
+ if (judgement.rule) {
17
+ lines.push(` ${ruleLine(judgement.rule)}`);
18
+ }
19
+ else {
20
+ lines.push(" no rule applies: ask the owner");
21
+ }
22
+ lines.push(...judgement.also.map((rule) => ` also (${rule.verdict}) ${ruleLine(rule)}`));
23
+ return lines.join("\n");
24
+ }
25
+ export function rulesText(almanac) {
26
+ const lines = [`almanac: ${almanac.places.join(", ")}`];
27
+ for (const { ruleset, rules, roles } of almanac.rulesets) {
28
+ lines.push("", `${ruleset}`);
29
+ for (const [role, names] of Object.entries(roles ?? {})) {
30
+ lines.push(` role ${role}: ${names.join(", ")}`);
31
+ }
32
+ for (const rule of rules) {
33
+ lines.push(` ${rule.verdict.padEnd(9)} ${rule.id}: ${rule.statement}`);
34
+ }
35
+ }
36
+ lines.push("", `${almanac.chains.length} chains of events (bos almanac recall <event,event…>)`);
37
+ return lines.join("\n");
38
+ }
39
+ export function recallText({ events, prediction, chains }) {
40
+ const lines = [`after ${events.join(" → ")}`];
41
+ if (prediction?.next.length) {
42
+ lines.push(` next (after ${prediction.after}):`);
43
+ lines.push(...prediction.next.map(({ event, p }) => ` ${(p * 100).toFixed(0).padStart(3)}% ${event}`));
44
+ }
45
+ else {
46
+ lines.push(" nothing known comes next");
47
+ }
48
+ for (const chain of chains) {
49
+ lines.push("", ` ${chain.id}: ${chain.events.join(" → ")}`);
50
+ if (chain.solution) {
51
+ lines.push(` solved: ${chain.solution}`);
52
+ }
53
+ if (chain.seen?.length) {
54
+ lines.push(` seen: ${chain.seen.join("; ")}`);
55
+ }
56
+ }
57
+ return lines.join("\n");
58
+ }
59
+ //# sourceMappingURL=almanac.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"almanac.js","sourceRoot":"","sources":["../../src/views/almanac.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { SealOutcome } from "../procedures/index.ts";
2
+ export declare function sealText(outcome: SealOutcome): string;
@@ -0,0 +1,26 @@
1
+ const when = (unixusat) => new Date(unixusat).toISOString();
2
+ export function sealText(outcome) {
3
+ const lines = [`${outcome.file}: ${outcome.files} files in the halo`];
4
+ if (outcome.sealedAt === null) {
5
+ lines.push(" never sealed (bos project seal writes it)");
6
+ }
7
+ else if (outcome.drift) {
8
+ const { added, changed, removed } = outcome.drift;
9
+ lines.push(` sealed at UNIXUSAT=${outcome.sealedAt} (${when(outcome.sealedAt)})`);
10
+ if (!added.length && !changed.length && !removed) {
11
+ lines.push(" nothing changed since");
12
+ }
13
+ lines.push(...changed.map((path) => ` ~ ${path}`), ...added.map((path) => ` + ${path}`));
14
+ if (removed) {
15
+ lines.push(` - ${removed} gone (only their hashes were kept)`);
16
+ }
17
+ }
18
+ if (outcome.action === "written") {
19
+ lines.push(" sealed now");
20
+ }
21
+ else if (outcome.action === "would-write") {
22
+ lines.push(" would be sealed now");
23
+ }
24
+ return lines.join("\n");
25
+ }
26
+ //# sourceMappingURL=sealing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sealing.js","sourceRoot":"","sources":["../../src/views/sealing.ts"],"names":[],"mappings":"AAGA,MAAM,IAAI,GAAG,CAAC,QAAgB,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;AAEpE,MAAM,UAAU,QAAQ,CAAC,OAAoB;IAC3C,MAAM,KAAK,GAAG,CAAC,GAAG,OAAO,CAAC,IAAI,KAAK,OAAO,CAAC,KAAK,oBAAoB,CAAC,CAAC;IACtE,IAAI,OAAO,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;QAC9B,KAAK,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC;IAC5D,CAAC;SAAM,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QACzB,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC;QAClD,KAAK,CAAC,IAAI,CAAC,wBAAwB,OAAO,CAAC,QAAQ,KAAK,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QACnF,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;YACjD,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;QACxC,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC;QAC3F,IAAI,OAAO,EAAE,CAAC;YACZ,KAAK,CAAC,IAAI,CAAC,OAAO,OAAO,qCAAqC,CAAC,CAAC;QAClE,CAAC;IACH,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QACjC,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC7B,CAAC;SAAM,IAAI,OAAO,CAAC,MAAM,KAAK,aAAa,EAAE,CAAC;QAC5C,KAAK,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;IACtC,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blacksmith-organization-system",
3
- "version": "1.6.0",
3
+ "version": "1.7.0",
4
4
  "description": "Blacksmith Organization System (BOS) core: the workshop as code - build its base, listen to its changes, inspect it as one coherent environment",
5
5
  "keywords": [
6
6
  "bos",
@@ -44,6 +44,7 @@
44
44
  "node": ">=22.18"
45
45
  },
46
46
  "scripts": {
47
+ "start": "task",
47
48
  "bos": "node src/cli.ts",
48
49
  "build": "tsc -p tsconfig.build.json",
49
50
  "typecheck": "tsc --noEmit",
@@ -75,11 +76,13 @@
75
76
  "astro": "^7.4.6",
76
77
  "bulma": "^1.0.4",
77
78
  "chromadb": "^3.5.0",
79
+ "commander": "^15.0.0",
78
80
  "commitizen": "^4.3.2",
79
81
  "composerize": "^1.7.6",
80
82
  "cosmiconfig": "^10.0.1",
81
83
  "decomposerize": "^1.4.4",
82
84
  "dockerode": "^5.0.1",
85
+ "esbuild": "^0.28.2",
83
86
  "husky": "^9.1.7",
84
87
  "inquirer": "^12.11.1",
85
88
  "isomorphic-git": "^1.44.11",
@@ -0,0 +1,90 @@
1
+ {
2
+ "about": "Situations met while forging the core (phase 2), each a chain of events up to its cataclysm, with the solution that got past it.",
3
+ "chains": [
4
+ {
5
+ "id": "lint-fails-on-bumped-package-json",
6
+ "events": ["commit", "hook:bump-version", "push:revision", "checks:lint-failed"],
7
+ "cataclysm": "checks:lint-failed",
8
+ "solution": "The bump wrote package.json with its arrays expanded and biome wanted them on one line: biome formats every package.json expanded (an override), and a test pins it.",
9
+ "seen": ["phase 2: the release of v1.4.x"]
10
+ },
11
+ {
12
+ "id": "draft-snippets-fail-lint",
13
+ "events": ["commit", "hook:bump-version", "file:unformatted-draft", "checks:lint-failed"],
14
+ "cataclysm": "checks:lint-failed",
15
+ "solution": "A draft of the owner is kept as written: its directory is left out of biome (examples/00-draft-snippets).",
16
+ "seen": ["2026-11-06: the draft snippets"]
17
+ },
18
+ {
19
+ "id": "open-pull-request-keeps-old-title",
20
+ "events": [
21
+ "push:revision",
22
+ "workflow:bump-minor",
23
+ "pull-request:open-already",
24
+ "pull-request:stale-title"
25
+ ],
26
+ "cataclysm": "pull-request:stale-title",
27
+ "solution": "The open pull request follows its branch: scripts/workflows/pull-request.sh edits its title and description to the version it releases now.",
28
+ "seen": ["PR #9 (v1.4.9, released v1.4.10)"]
29
+ },
30
+ {
31
+ "id": "secret-scanner-flags-test-fixture",
32
+ "events": [
33
+ "commit:fixture-with-credentials-url",
34
+ "push:revision",
35
+ "pull-request:open",
36
+ "gitguardian:flagged"
37
+ ],
38
+ "cataclysm": "gitguardian:flagged",
39
+ "solution": "Tests build user:token@host URLs from parts, so no literal sits in the source.",
40
+ "seen": ["phase 2: mirrors.sh tests"]
41
+ },
42
+ {
43
+ "id": "mirror-token-refused",
44
+ "events": ["push:development", "mirrors:sync", "mirrors:403"],
45
+ "cataclysm": "mirrors:403",
46
+ "solution": "The owner renews the token in the publish-env environment; the mirrors step continues on error, so the run and the work go on.",
47
+ "seen": ["phase 2: gitlab, bitbucket (run 42139753049 all 200 after)"]
48
+ },
49
+ {
50
+ "id": "push-rejected-after-bot-bump",
51
+ "events": ["push:revision", "workflow:bump-commit", "push:development", "push:rejected"],
52
+ "cataclysm": "push:rejected",
53
+ "solution": "The workflow pushed its bump to development: fetch, merge origin/development (the version merge driver takes the higher), push again. Pull development before every batch.",
54
+ "seen": ["phase 2, several batches", "2026-11-06: PR #11 merged meanwhile"]
55
+ },
56
+ {
57
+ "id": "bot-pull-request-waits-for-approval",
58
+ "events": ["push:revision", "workflow:opens-pull-request", "checks:action-required"],
59
+ "cataclysm": "checks:action-required",
60
+ "solution": "Checks of a pull request opened by github-actions[bot] wait: the owner presses Approve and run, or the next push to revision runs them.",
61
+ "seen": ["PR #11 (run 42140002829)"]
62
+ },
63
+ {
64
+ "id": "commit-header-too-long",
65
+ "events": ["commit", "hook:bump-version", "commitlint:header-too-long"],
66
+ "cataclysm": "commitlint:header-too-long",
67
+ "solution": "Shorten the header to 100 characters. The bump and the staged files stay staged: check git show --stat of the next commit, so nothing of the failed one rides along.",
68
+ "seen": ["2026-11-06: taking in the almanac and Q16 (folded into the next commit, redone)"]
69
+ },
70
+ {
71
+ "id": "npm-installs-the-legacy-release",
72
+ "events": ["npm:install", "npm:latest-is-legacy", "installed:0.4.2"],
73
+ "cataclysm": "installed:0.4.2",
74
+ "solution": "npm's latest is still the legacy 0.4.2 (decision Q7): install blacksmith-organization-system@next, or ask for ^1.0.0.",
75
+ "seen": ["2026-11-06: examples/00-draft-snippets/scrapnotes.md"]
76
+ },
77
+ {
78
+ "id": "workshop-option-on-a-partition-root",
79
+ "events": [
80
+ "library:new-bos",
81
+ "option:workshop-not-named-__WORKSHOP",
82
+ "bootstrap",
83
+ "workshop:second-beside-__WORKSHOP"
84
+ ],
85
+ "cataclysm": "workshop:second-beside-__WORKSHOP",
86
+ "solution": "A --workshop (or { workshop }) not named __WORKSHOP is the directory that holds one, like $WORKSHOP_ROOT.",
87
+ "seen": ["2026-11-06 05:11: the draft snippets on setternet-A62"]
88
+ }
89
+ ]
90
+ }
@@ -0,0 +1,141 @@
1
+ {
2
+ "ruleset": "bos-environment",
3
+ "about": "The rules of every BOS workshop and project, for people and agents alike (the contributors committee). The first rule that applies decides.",
4
+ "rules": [
5
+ {
6
+ "id": "never-skip-hooks",
7
+ "statement": "Checks are never skipped: no --no-verify, no HUSKY=0. Chain a commit after the checks with &&.",
8
+ "when": { "action": ["commit", "push", "merge"], "flags": ["--no-verify", "-n", "HUSKY=0"] },
9
+ "verdict": "violation",
10
+ "source": "AGENTS.md, rule 3"
11
+ },
12
+ {
13
+ "id": "never-commit-on-master",
14
+ "statement": "master is the spine of canon: nobody commits on it; it moves only through a pull request from releasing (or revision, in phase 2).",
15
+ "when": { "action": "commit", "target": ["master", "main"] },
16
+ "verdict": "violation",
17
+ "source": "AGENTS.md, the craft loop"
18
+ },
19
+ {
20
+ "id": "mirrors-never-publish",
21
+ "statement": "A mirror only checks: it never publishes, releases or deploys (Read the Docs, npm, images).",
22
+ "when": { "action": ["publish", "release", "deploy"], "place": ["mirror*"] },
23
+ "verdict": "violation",
24
+ "source": "the owner, phase 2: mirrors"
25
+ },
26
+ {
27
+ "id": "workshop-areas-stay",
28
+ "statement": "The top-level areas of a workshop (.BOS, devarmory, forge, craftbook, archive) are never deleted, moved or restructured.",
29
+ "when": {
30
+ "action": ["delete", "remove", "move", "restructure", "rm"],
31
+ "target": [".BOS", "devarmory", "forge", "craftbook", "archive"]
32
+ },
33
+ "verdict": "violation",
34
+ "source": "__WORKSHOP/AGENTS.md, rule 4"
35
+ },
36
+ {
37
+ "id": "never-reveal-secrets",
38
+ "statement": "Secrets are never printed or shown: no cat .env, no tokens or keys in output, logs or commits.",
39
+ "when": {
40
+ "action": ["print", "cat", "show", "echo", "reveal", "commit", "log"],
41
+ "target": [".env", "*token*", "secret*", "*.pem", "id_rsa*", "id_ed25519*", "password*"]
42
+ },
43
+ "verdict": "violation",
44
+ "source": "the owner, phase 2: security"
45
+ },
46
+ {
47
+ "id": "never-revert-the-owner",
48
+ "statement": "Anything in the working tree an agent did not make is the owner's: it is intended, never reverted or overwritten.",
49
+ "when": {
50
+ "action": ["revert", "overwrite", "discard", "reset"],
51
+ "target": ["owner*", "Sarverott*"]
52
+ },
53
+ "verdict": "violation",
54
+ "source": "AGENTS.md, rule 2"
55
+ },
56
+ {
57
+ "id": "other-repositories-get-notes",
58
+ "statement": "Work for another repository is written down in forge/NOTES-for-repositories.md; the other repository is never edited.",
59
+ "when": {
60
+ "role": "agent",
61
+ "action": ["edit", "commit", "change", "write"],
62
+ "target": ["other*", "another*"]
63
+ },
64
+ "verdict": "violation",
65
+ "source": "AGENTS.md, where things go"
66
+ },
67
+ {
68
+ "id": "tests-in-temporary-workshops",
69
+ "statement": "Tests build their own temporary workshops; never the home ~/__WORKSHOP.",
70
+ "when": { "action": "test", "place": ["~/__WORKSHOP*", "/home/*/__WORKSHOP*"] },
71
+ "verdict": "violation",
72
+ "source": "AGENTS.md, rule 8"
73
+ },
74
+ {
75
+ "id": "home-workshop-only-when-asked",
76
+ "statement": "BOS is tried and demonstrated on the development workshop (.env WORKSHOP_ROOT); the home ~/__WORKSHOP only when the owner asks.",
77
+ "when": {
78
+ "action": ["run", "bootstrap", "try", "demonstrate", "write"],
79
+ "place": ["~/__WORKSHOP*", "/home/*/__WORKSHOP*"]
80
+ },
81
+ "verdict": "ask",
82
+ "source": "AGENTS.md, the development workshop"
83
+ },
84
+ {
85
+ "id": "agents-open-no-pull-request",
86
+ "statement": "An agent opens no pull request: it pushes development to revision, and the workflow opens revision → master.",
87
+ "when": {
88
+ "role": "agent",
89
+ "action": ["open", "create"],
90
+ "target": ["PR", "pull-request", "pull"]
91
+ },
92
+ "verdict": "violation",
93
+ "source": "AGENTS.md, the routine"
94
+ },
95
+ {
96
+ "id": "agents-push-their-branches",
97
+ "statement": "An agent pushes development, its own dev/<name> and revision without asking.",
98
+ "when": { "role": "agent", "action": "push", "target": ["development", "revision", "dev/*"] },
99
+ "verdict": "allowed",
100
+ "source": "AGENTS.md, rule 10"
101
+ },
102
+ {
103
+ "id": "protected-branches-ask",
104
+ "statement": "master, testing and releasing are pushed only with the owner's OK, and the reason.",
105
+ "when": { "action": "push", "target": ["master", "main", "testing", "releasing"] },
106
+ "verdict": "ask",
107
+ "source": "AGENTS.md, rule 10"
108
+ },
109
+ {
110
+ "id": "tags-releases-publishing-ask",
111
+ "statement": "Tags, releases and publishing (npm, the wiki's repository, images) are asked for first.",
112
+ "when": { "action": ["tag", "release", "publish"] },
113
+ "verdict": "ask",
114
+ "source": "AGENTS.md, rule 10"
115
+ },
116
+ {
117
+ "id": "remotes-and-settings-ask",
118
+ "statement": "Remotes and repository settings are changed only with the owner's OK.",
119
+ "when": {
120
+ "action": ["change", "add", "remove", "set", "rename"],
121
+ "target": ["remote*", "settings", "secrets", "webhook*"]
122
+ },
123
+ "verdict": "ask",
124
+ "source": "AGENTS.md, rule 10"
125
+ },
126
+ {
127
+ "id": "email-stays-private",
128
+ "statement": "The owner's e-mail address identifies the owner only; it is not sent to services unless the owner asks.",
129
+ "when": { "action": ["send", "post", "submit"], "target": ["email", "e-mail", "mail*"] },
130
+ "verdict": "ask",
131
+ "source": "the owner, phase 2: security"
132
+ },
133
+ {
134
+ "id": "questions-are-not-settled-in-code",
135
+ "statement": "An open question (BRAINSTORM.md Q<n>) is never settled in code: the owner answers it in ORDERS.md.",
136
+ "when": { "action": ["settle", "decide", "answer"], "target": ["question*", "BRAINSTORM*"] },
137
+ "verdict": "violation",
138
+ "source": "AGENTS.md, read first"
139
+ }
140
+ ]
141
+ }