@memberjunction/cli 6.2.0-edge.1 → 6.2.0-edge.2

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 (59) hide show
  1. package/dist/commands/agent/init.d.ts +12 -0
  2. package/dist/commands/agent/init.d.ts.map +1 -1
  3. package/dist/commands/agent/init.js +42 -8
  4. package/dist/commands/agent/init.js.map +1 -1
  5. package/dist/commands/migrate/convert.d.ts.map +1 -1
  6. package/dist/commands/migrate/convert.js +15 -1
  7. package/dist/commands/migrate/convert.js.map +1 -1
  8. package/dist/commands/migrate/rebake.d.ts.map +1 -1
  9. package/dist/commands/migrate/rebake.js +7 -0
  10. package/dist/commands/migrate/rebake.js.map +1 -1
  11. package/dist/commands/rubric/diff.d.ts +11 -0
  12. package/dist/commands/rubric/diff.d.ts.map +1 -0
  13. package/dist/commands/rubric/diff.js +20 -0
  14. package/dist/commands/rubric/diff.js.map +1 -0
  15. package/dist/commands/rubric/evaluate.d.ts +12 -0
  16. package/dist/commands/rubric/evaluate.d.ts.map +1 -0
  17. package/dist/commands/rubric/evaluate.js +21 -0
  18. package/dist/commands/rubric/evaluate.js.map +1 -0
  19. package/dist/commands/rubric/index.d.ts +6 -0
  20. package/dist/commands/rubric/index.d.ts.map +1 -0
  21. package/dist/commands/rubric/index.js +13 -0
  22. package/dist/commands/rubric/index.js.map +1 -0
  23. package/dist/commands/rubric/list.d.ts +6 -0
  24. package/dist/commands/rubric/list.d.ts.map +1 -0
  25. package/dist/commands/rubric/list.js +14 -0
  26. package/dist/commands/rubric/list.js.map +1 -0
  27. package/dist/commands/rubric/show.d.ts +9 -0
  28. package/dist/commands/rubric/show.d.ts.map +1 -0
  29. package/dist/commands/rubric/show.js +16 -0
  30. package/dist/commands/rubric/show.js.map +1 -0
  31. package/dist/commands/rubric/validate.d.ts +9 -0
  32. package/dist/commands/rubric/validate.d.ts.map +1 -0
  33. package/dist/commands/rubric/validate.js +16 -0
  34. package/dist/commands/rubric/validate.js.map +1 -0
  35. package/dist/commands/test/index.d.ts.map +1 -1
  36. package/dist/commands/test/index.js +2 -0
  37. package/dist/commands/test/index.js.map +1 -1
  38. package/dist/commands/test/promote-criteria.d.ts +10 -0
  39. package/dist/commands/test/promote-criteria.d.ts.map +1 -0
  40. package/dist/commands/test/promote-criteria.js +25 -0
  41. package/dist/commands/test/promote-criteria.js.map +1 -0
  42. package/dist/commands/test/report.d.ts +9 -0
  43. package/dist/commands/test/report.d.ts.map +1 -0
  44. package/dist/commands/test/report.js +18 -0
  45. package/dist/commands/test/report.js.map +1 -0
  46. package/dist/commands/test/run.d.ts +1 -0
  47. package/dist/commands/test/run.d.ts.map +1 -1
  48. package/dist/commands/test/run.js +4 -0
  49. package/dist/commands/test/run.js.map +1 -1
  50. package/dist/commands/test/suite.d.ts +1 -0
  51. package/dist/commands/test/suite.d.ts.map +1 -1
  52. package/dist/commands/test/suite.js +4 -0
  53. package/dist/commands/test/suite.js.map +1 -1
  54. package/dist/init-templates/citizen-builder/.env.example +6 -0
  55. package/dist/init-templates/citizen-builder/docker/Dockerfile +10 -2
  56. package/dist/init-templates/citizen-builder/docker-compose.yml +6 -0
  57. package/dist/init-templates/citizen-builder/scripts/docker-entrypoint.sh +56 -20
  58. package/oclif.manifest.json +1702 -1443
  59. package/package.json +22 -22
@@ -16,6 +16,8 @@ export default class Test extends Command {
16
16
  this.log(' mj test suite <suite-id> - Execute a test suite');
17
17
  this.log(' mj test list - List available tests');
18
18
  this.log(' mj test validate - Validate test definitions');
19
+ this.log(' mj test promote-criteria <test> - Copy inline criteria into a Draft rubric');
20
+ this.log(' mj test report <run-id> - Print the per-criterion rubric breakdown');
19
21
  this.log(' mj test history - View test execution history');
20
22
  this.log(' mj test compare - Compare test runs for regressions');
21
23
  this.log('');
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/test/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEtC,MAAM,CAAC,OAAO,OAAO,IAAK,SAAQ,OAAO;aAChC,gBAAW,GAAG,6DAA6D,CAAC;aAE5E,aAAQ,GAAG;QAChB,mDAAmD;QACnD,uEAAuE;QACvE,sDAAsD;QACtD,0CAA0C;QAC1C,mDAAmD;QACnD,oDAAoD;KACrD,CAAC;IAEF,KAAK,CAAC,GAAG;QACP,IAAI,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC;QAC/C,IAAI,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;QAChC,IAAI,CAAC,GAAG,CAAC,2DAA2D,CAAC,CAAC;QACtE,IAAI,CAAC,GAAG,CAAC,0DAA0D,CAAC,CAAC;QACrE,IAAI,CAAC,GAAG,CAAC,0DAA0D,CAAC,CAAC;QACrE,IAAI,CAAC,GAAG,CAAC,+DAA+D,CAAC,CAAC;QAC1E,IAAI,CAAC,GAAG,CAAC,iEAAiE,CAAC,CAAC;QAC5E,IAAI,CAAC,GAAG,CAAC,uEAAuE,CAAC,CAAC;QAClF,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACb,IAAI,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;QAChD,IAAI,CAAC,GAAG,CAAC,kEAAkE,CAAC,CAAC;QAC7E,IAAI,CAAC,GAAG,CAAC,0DAA0D,CAAC,CAAC;QACrE,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACb,IAAI,CAAC,GAAG,CAAC,iEAAiE,CAAC,CAAC;IAC9E,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/test/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEtC,MAAM,CAAC,OAAO,OAAO,IAAK,SAAQ,OAAO;aAChC,gBAAW,GAAG,6DAA6D,CAAC;aAE5E,aAAQ,GAAG;QAChB,mDAAmD;QACnD,uEAAuE;QACvE,sDAAsD;QACtD,0CAA0C;QAC1C,mDAAmD;QACnD,oDAAoD;KACrD,CAAC;IAEF,KAAK,CAAC,GAAG;QACP,IAAI,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC;QAC/C,IAAI,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;QAChC,IAAI,CAAC,GAAG,CAAC,2DAA2D,CAAC,CAAC;QACtE,IAAI,CAAC,GAAG,CAAC,0DAA0D,CAAC,CAAC;QACrE,IAAI,CAAC,GAAG,CAAC,0DAA0D,CAAC,CAAC;QACrE,IAAI,CAAC,GAAG,CAAC,+DAA+D,CAAC,CAAC;QAC1E,IAAI,CAAC,GAAG,CAAC,8EAA8E,CAAC,CAAC;QACzF,IAAI,CAAC,GAAG,CAAC,6EAA6E,CAAC,CAAC;QACxF,IAAI,CAAC,GAAG,CAAC,iEAAiE,CAAC,CAAC;QAC5E,IAAI,CAAC,GAAG,CAAC,uEAAuE,CAAC,CAAC;QAClF,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACb,IAAI,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;QAChD,IAAI,CAAC,GAAG,CAAC,kEAAkE,CAAC,CAAC;QAC7E,IAAI,CAAC,GAAG,CAAC,0DAA0D,CAAC,CAAC;QACrE,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACb,IAAI,CAAC,GAAG,CAAC,iEAAiE,CAAC,CAAC;IAC9E,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class TestPromoteCriteria extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ test: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
7
+ };
8
+ run(): Promise<void>;
9
+ }
10
+ //# sourceMappingURL=promote-criteria.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"promote-criteria.d.ts","sourceRoot":"","sources":["../../../src/commands/test/promote-criteria.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,OAAO,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,CAAC,OAAO,OAAO,mBAAoB,SAAQ,OAAO;IACtD,MAAM,CAAC,WAAW,SAAuG;IAEzH,MAAM,CAAC,QAAQ,WAGb;IAEF,MAAM,CAAC,IAAI;;MAKT;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAS3B"}
@@ -0,0 +1,25 @@
1
+ import { Args, Command } from '@oclif/core';
2
+ export default class TestPromoteCriteria extends Command {
3
+ static { this.description = 'Copy a test\'s inline judge criteria into a Draft rubric and set Test.RubricID. Does not publish.'; }
4
+ static { this.examples = [
5
+ '<%= config.bin %> <%= command.id %> <test-id>',
6
+ '<%= config.bin %> <%= command.id %> "Reply check"',
7
+ ]; }
8
+ static { this.args = {
9
+ test: Args.string({
10
+ description: 'Test name or ID',
11
+ required: true,
12
+ }),
13
+ }; }
14
+ async run() {
15
+ const { PromoteCriteriaCommand } = await import('@memberjunction/testing-cli');
16
+ const { args } = await this.parse(TestPromoteCriteria);
17
+ try {
18
+ await new PromoteCriteriaCommand().Execute(args.test);
19
+ }
20
+ catch (error) {
21
+ this.error(error);
22
+ }
23
+ }
24
+ }
25
+ //# sourceMappingURL=promote-criteria.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"promote-criteria.js","sourceRoot":"","sources":["../../../src/commands/test/promote-criteria.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,CAAC,OAAO,OAAO,mBAAoB,SAAQ,OAAO;aAC/C,gBAAW,GAAG,mGAAmG,CAAC;aAElH,aAAQ,GAAG;QAChB,+CAA+C;QAC/C,mDAAmD;KACpD,CAAC;aAEK,SAAI,GAAG;QACZ,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC;YAChB,WAAW,EAAE,iBAAiB;YAC9B,QAAQ,EAAE,IAAI;SACf,CAAC;KACH,CAAC;IAEF,KAAK,CAAC,GAAG;QACP,MAAM,EAAE,sBAAsB,EAAE,GAAG,MAAM,MAAM,CAAC,6BAA6B,CAAC,CAAC;QAC/E,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;QACvD,IAAI,CAAC;YACH,MAAM,IAAI,sBAAsB,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,KAAK,CAAC,KAAc,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class TestReport extends Command {
3
+ static description: string;
4
+ static args: {
5
+ runId: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
6
+ };
7
+ run(): Promise<void>;
8
+ }
9
+ //# sourceMappingURL=report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../../src/commands/test/report.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,OAAO,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,CAAC,OAAO,OAAO,UAAW,SAAQ,OAAO;IAC7C,MAAM,CAAC,WAAW,SAA8D;IAEhF,MAAM,CAAC,IAAI;;MAET;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAS3B"}
@@ -0,0 +1,18 @@
1
+ import { Args, Command } from '@oclif/core';
2
+ export default class TestReport extends Command {
3
+ static { this.description = 'Print the per-criterion rubric breakdown for a test run.'; }
4
+ static { this.args = {
5
+ runId: Args.string({ description: 'Test run ID', required: true }),
6
+ }; }
7
+ async run() {
8
+ const { CloseMJProvider, ReportCommand } = await import('@memberjunction/testing-cli');
9
+ const { args } = await this.parse(TestReport);
10
+ try {
11
+ await new ReportCommand().execute(args.runId, {}, undefined);
12
+ }
13
+ finally {
14
+ await CloseMJProvider();
15
+ }
16
+ }
17
+ }
18
+ //# sourceMappingURL=report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../../../src/commands/test/report.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,CAAC,OAAO,OAAO,UAAW,SAAQ,OAAO;aACtC,gBAAW,GAAG,0DAA0D,CAAC;aAEzE,SAAI,GAAG;QACZ,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,aAAa,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;KACnE,CAAC;IAEF,KAAK,CAAC,GAAG;QACP,MAAM,EAAE,eAAe,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,6BAA6B,CAAC,CAAC;QACvF,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QAC9C,IAAI,CAAC;YACH,MAAM,IAAI,aAAa,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,EAAE,SAAkB,CAAC,CAAC;QACxE,CAAC;gBAAS,CAAC;YACT,MAAM,eAAe,EAAE,CAAC;QAC1B,CAAC;IACH,CAAC"}
@@ -13,6 +13,7 @@ export default class TestRun extends Command {
13
13
  'dry-run': import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
14
14
  verbose: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
15
15
  'checks-module': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
16
+ rubric: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
16
17
  'oracles-module': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
17
18
  };
18
19
  run(): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../src/commands/test/run.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAe,MAAM,aAAa,CAAC;AAGnD,MAAM,CAAC,OAAO,OAAO,OAAQ,SAAQ,OAAO;IAC1C,MAAM,CAAC,WAAW,SAAyC;IAE3D,MAAM,CAAC,QAAQ,WAMb;IAEF,MAAM,CAAC,IAAI;;MAKT;IAEF,MAAM,CAAC,KAAK;;;;;;;;;MAmCV;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CA6B3B"}
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../src/commands/test/run.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAe,MAAM,aAAa,CAAC;AAGnD,MAAM,CAAC,OAAO,OAAO,OAAQ,SAAQ,OAAO;IAC1C,MAAM,CAAC,WAAW,SAAyC;IAE3D,MAAM,CAAC,QAAQ,WAMb;IAEF,MAAM,CAAC,IAAI;;MAKT;IAEF,MAAM,CAAC,KAAK;;;;;;;;;;MAsCV;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CA8B3B"}
@@ -43,6 +43,9 @@ export default class TestRun extends Command {
43
43
  'integration check bundles register on the IntegrationCheckRegistry. Durable form: ' +
44
44
  "mj.config.cjs `testing.checkModules` (this repo loads '@memberjunction/integration-test-suite' that way).",
45
45
  }),
46
+ rubric: Flags.string({
47
+ description: 'Rubric override: name or id, optionally @version (1.2.0 or a version id)',
48
+ }),
46
49
  'oracles-module': Flags.string({
47
50
  description: 'Path to a JS/TS module that exports custom IOracle classes or instances. ' +
48
51
  'Each export is registered on the engine before the test runs — used by non-MJ ' +
@@ -68,6 +71,7 @@ export default class TestRun extends Command {
68
71
  output: flags.output,
69
72
  dryRun: flags['dry-run'],
70
73
  verbose: flags.verbose,
74
+ rubric: flags.rubric,
71
75
  oraclesModule: flags['oracles-module'],
72
76
  checksModule: flags['checks-module'],
73
77
  });
@@ -1 +1 @@
1
- {"version":3,"file":"run.js","sourceRoot":"","sources":["../../../src/commands/test/run.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEpG,MAAM,CAAC,OAAO,OAAO,OAAQ,SAAQ,OAAO;aACnC,gBAAW,GAAG,qCAAqC,CAAC;aAEpD,aAAQ,GAAG;QAChB,+CAA+C;QAC/C,mEAAmE;QACnE,qEAAqE;QACrE,mFAAmF;QACnF,yDAAyD;KAC1D,CAAC;aAEK,SAAI,GAAG;QACZ,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC;YAClB,WAAW,EAAE,oBAAoB;YACjC,QAAQ,EAAE,KAAK;SAChB,CAAC;KACH,CAAC;aAEK,UAAK,GAAG;QACb,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC;YACjB,IAAI,EAAE,GAAG;YACT,WAAW,EAAE,sBAAsB;SACpC,CAAC;QACF,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC;YACxB,IAAI,EAAE,GAAG;YACT,WAAW,EAAE,0CAA0C;SACxD,CAAC;QACF,MAAM,EAAE,gBAAgB;QACxB,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC;YACnB,IAAI,EAAE,GAAG;YACT,WAAW,EAAE,kBAAkB;SAChC,CAAC;QACF,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC;YACvB,WAAW,EAAE,4BAA4B;YACzC,OAAO,EAAE,KAAK;SACf,CAAC;QACF,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC;YACrB,IAAI,EAAE,GAAG;YACT,WAAW,EAAE,qCAAqC;YAClD,OAAO,EAAE,KAAK;SACf,CAAC;QACF,eAAe,EAAE,KAAK,CAAC,MAAM,CAAC;YAC5B,WAAW,EACT,qFAAqF;gBACrF,oFAAoF;gBACpF,2GAA2G;SAC9G,CAAC;QACF,gBAAgB,EAAE,KAAK,CAAC,MAAM,CAAC;YAC7B,WAAW,EACT,2EAA2E;gBAC3E,gFAAgF;gBAChF,gFAAgF;SACnF,CAAC;KACH,CAAC;IAEF,KAAK,CAAC,GAAG;QACP,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,6BAA6B,CAAC,CAAC;QAEnE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAElD,IAAI,CAAC;YACH,yCAAyC;YACzC,2EAA2E;YAC3E,MAAM,UAAU,GAAG,IAAI,UAAU,EAAE,CAAC;YACpC,MAAM,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE;gBACpC,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,WAAW,EAAE,KAAK,CAAC,WAAW;gBAC9B,MAAM,EAAE,mBAAmB,CAAC;oBAC1B,MAAM,EAAE,KAAK,CAAC,MAAM;oBACpB,MAAM,EAAE,SAAkB;oBAC1B,aAAa,EAAE,SAAkB;oBACjC,GAAG,EAAE,eAAe;iBACrB,CAAC;gBACF,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,MAAM,EAAE,KAAK,CAAC,SAAS,CAAC;gBACxB,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,aAAa,EAAE,KAAK,CAAC,gBAAgB,CAAC;gBACtC,YAAY,EAAE,KAAK,CAAC,eAAe,CAAC;aACrC,CAAC,CAAC;QAEL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,KAAK,CAAC,KAAc,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC"}
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../../src/commands/test/run.ts"],"names":[],"mappings":"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"}
@@ -13,6 +13,7 @@ export default class TestSuite extends Command {
13
13
  delay: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<number, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
14
14
  parallel: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
15
15
  'max-parallel': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<number, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
16
+ rubric: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
16
17
  'flaky-check': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<number, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
17
18
  'checks-module': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
18
19
  'oracles-module': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
@@ -1 +1 @@
1
- {"version":3,"file":"suite.d.ts","sourceRoot":"","sources":["../../../src/commands/test/suite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAe,MAAM,aAAa,CAAC;AAGnD,MAAM,CAAC,OAAO,OAAO,SAAU,SAAQ,OAAO;IAC5C,MAAM,CAAC,WAAW,SAA0B;IAE5C,MAAM,CAAC,QAAQ,WAKb;IAEF,MAAM,CAAC,IAAI;;MAKT;IAEF,MAAM,CAAC,KAAK;;;;;;;;;;;MA4CV;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CA+B3B"}
1
+ {"version":3,"file":"suite.d.ts","sourceRoot":"","sources":["../../../src/commands/test/suite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAe,MAAM,aAAa,CAAC;AAGnD,MAAM,CAAC,OAAO,OAAO,SAAU,SAAQ,OAAO;IAC5C,MAAM,CAAC,WAAW,SAA0B;IAE5C,MAAM,CAAC,QAAQ,WAKb;IAEF,MAAM,CAAC,IAAI;;MAKT;IAEF,MAAM,CAAC,KAAK;;;;;;;;;;;;MA+CV;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAgC3B"}
@@ -43,6 +43,9 @@ export default class TestSuite extends Command {
43
43
  description: 'Maximum number of parallel workers (default 4)',
44
44
  default: 4,
45
45
  }),
46
+ rubric: Flags.string({
47
+ description: 'Rubric override for every test: name or id, optionally @version',
48
+ }),
46
49
  'flaky-check': Flags.integer({
47
50
  description: 'Run each test N times to detect flakiness (variance > 0.3 or mixed pass/fail = flaky). Recommended: 3 or 5',
48
51
  }),
@@ -78,6 +81,7 @@ export default class TestSuite extends Command {
78
81
  parallel: flags.parallel,
79
82
  maxParallel: flags['max-parallel'],
80
83
  flakyCheck: flags['flaky-check'],
84
+ rubric: flags.rubric,
81
85
  oraclesModule: flags['oracles-module'],
82
86
  checksModule: flags['checks-module'],
83
87
  });
@@ -1 +1 @@
1
- {"version":3,"file":"suite.js","sourceRoot":"","sources":["../../../src/commands/test/suite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEpG,MAAM,CAAC,OAAO,OAAO,SAAU,SAAQ,OAAO;aACrC,gBAAW,GAAG,sBAAsB,CAAC;aAErC,aAAQ,GAAG;QAChB,gDAAgD;QAChD,kEAAkE;QAClE,8DAA8D;QAC9D,4EAA4E;KAC7E,CAAC;aAEK,SAAI,GAAG;QACZ,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC;YACnB,WAAW,EAAE,0BAA0B;YACvC,QAAQ,EAAE,KAAK;SAChB,CAAC;KACH,CAAC;aAEK,UAAK,GAAG;QACb,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC;YACjB,IAAI,EAAE,GAAG;YACT,WAAW,EAAE,4BAA4B;SAC1C,CAAC;QACF,MAAM,EAAE,gBAAgB;QACxB,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC;YACnB,IAAI,EAAE,GAAG;YACT,WAAW,EAAE,kBAAkB;SAChC,CAAC;QACF,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC;YACrB,IAAI,EAAE,GAAG;YACT,WAAW,EAAE,qCAAqC;YAClD,OAAO,EAAE,KAAK;SACf,CAAC;QACF,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC;YACnB,IAAI,EAAE,GAAG;YACT,WAAW,EAAE,0EAA0E;YACvF,OAAO,EAAE,CAAC;SACX,CAAC;QACF,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC;YACtB,IAAI,EAAE,GAAG;YACT,WAAW,EAAE,oDAAoD;YACjE,OAAO,EAAE,KAAK;SACf,CAAC;QACF,cAAc,EAAE,KAAK,CAAC,OAAO,CAAC;YAC5B,WAAW,EAAE,gDAAgD;YAC7D,OAAO,EAAE,CAAC;SACX,CAAC;QACF,aAAa,EAAE,KAAK,CAAC,OAAO,CAAC;YAC3B,WAAW,EAAE,4GAA4G;SAC1H,CAAC;QACF,eAAe,EAAE,KAAK,CAAC,MAAM,CAAC;YAC5B,WAAW,EACT,qFAAqF;gBACrF,oFAAoF;gBACpF,2GAA2G;SAC9G,CAAC;QACF,gBAAgB,EAAE,KAAK,CAAC,MAAM,CAAC;YAC7B,WAAW,EACT,2EAA2E;gBAC3E,iFAAiF;gBACjF,gFAAgF;SACnF,CAAC;KACH,CAAC;IAEF,KAAK,CAAC,GAAG;QACP,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,6BAA6B,CAAC,CAAC;QAErE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAEpD,IAAI,CAAC;YACH,2CAA2C;YAC3C,2EAA2E;YAC3E,MAAM,YAAY,GAAG,IAAI,YAAY,EAAE,CAAC;YACxC,MAAM,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE;gBACvC,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,MAAM,EAAE,mBAAmB,CAAC;oBAC1B,MAAM,EAAE,KAAK,CAAC,MAAM;oBACpB,MAAM,EAAE,SAAkB;oBAC1B,aAAa,EAAE,SAAkB;oBACjC,GAAG,EAAE,eAAe;iBACrB,CAAC;gBACF,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,WAAW,EAAE,KAAK,CAAC,cAAc,CAAC;gBAClC,UAAU,EAAE,KAAK,CAAC,aAAa,CAAC;gBAChC,aAAa,EAAE,KAAK,CAAC,gBAAgB,CAAC;gBACtC,YAAY,EAAE,KAAK,CAAC,eAAe,CAAC;aACrC,CAAC,CAAC;QAEL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,KAAK,CAAC,KAAc,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC"}
1
+ {"version":3,"file":"suite.js","sourceRoot":"","sources":["../../../src/commands/test/suite.ts"],"names":[],"mappings":"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"}
@@ -2,6 +2,12 @@
2
2
  # MemberJunction Citizen Agent Builder Environment Configuration
3
3
  # ==============================================================================
4
4
 
5
+ # MemberJunction Version
6
+ # The release this workspace runs: both the CLI inside the container and the MemberJunction
7
+ # install it creates. `mj agent init` sets it to its own version so the container matches the CLI
8
+ # that scaffolded the workspace. To move to another release, change it and run: docker compose build
9
+ MJ_VERSION=
10
+
5
11
  # Database Configuration
6
12
  DB_PASSWORD=TestPassword123!
7
13
  DB_PORT=1433
@@ -8,8 +8,16 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
8
8
  procps \
9
9
  && rm -rf /var/lib/apt/lists/*
10
10
 
11
- # Install MemberJunction CLI and process manager globally
12
- RUN npm install -g @memberjunction/cli pm2 pnpm
11
+ # The MemberJunction release this workspace was scaffolded for. `mj agent init` writes it to
12
+ # .env from its own version and docker-compose.yml passes it in, so the CLI inside the container
13
+ # is the same release as the one that created the workspace. Never install unpinned: that
14
+ # resolves npm's `latest` tag, which can be a different major line from the scaffolding CLI.
15
+ ARG MJ_VERSION
16
+ RUN if [ -z "$MJ_VERSION" ]; then \
17
+ echo "ERROR: the MJ_VERSION build arg is required. Set MJ_VERSION in .env ('mj agent init' writes it)." >&2; \
18
+ exit 1; \
19
+ fi \
20
+ && npm install -g "@memberjunction/cli@${MJ_VERSION}" pm2 pnpm
13
21
 
14
22
  WORKDIR /workspace
15
23
 
@@ -23,6 +23,10 @@ services:
23
23
  build:
24
24
  context: .
25
25
  dockerfile: docker/Dockerfile
26
+ args:
27
+ # Required: the CLI and MemberJunction release inside the container must match the CLI
28
+ # that scaffolded this workspace. `mj agent init` writes it to .env.
29
+ MJ_VERSION: "${MJ_VERSION:?MJ_VERSION is not set in .env - re-run mj agent init, or set it to the MemberJunction version to install}"
26
30
  platform: linux/amd64
27
31
  restart: unless-stopped
28
32
  depends_on:
@@ -37,6 +41,8 @@ services:
37
41
  DB_USERNAME: "sa"
38
42
  DB_PASSWORD: "${DB_PASSWORD:-TestPassword123!}"
39
43
  DB_DATABASE: "${DB_DATABASE:-MemberJunction}"
44
+ # Tells the entrypoint which MemberJunction release `mj install` must fetch
45
+ MJ_VERSION: "${MJ_VERSION}"
40
46
  MJ_BASE_ENCRYPTION_KEY: "${MJ_BASE_ENCRYPTION_KEY:-0123456789abcdef0123456789abcdef}"
41
47
  # LLM Provider API Keys
42
48
  AI_VENDOR_API_KEY__OpenAILLM: "${OPENAI_API_KEY:-}"
@@ -33,16 +33,33 @@ echo "SQL Server is reachable!"
33
33
 
34
34
  cd /workspace
35
35
 
36
- # 2. First-time setup: install MemberJunction if not already installed
37
- if [ ! -f "/workspace/package.json" ]; then
36
+ # 2. Provisioning. State lives on the workspace volume so it survives restarts, and each step
37
+ # that must not run twice records its own completion: `mj app install` of an app that is
38
+ # already installed is an error, so a failure in a LATER step has to be retried on restart
39
+ # without re-running an earlier one. Failures are not masked. With `set -e` a failed step
40
+ # exits the container loudly (see `docker compose logs mj`), `restart: unless-stopped`
41
+ # retries it, and nothing reports success until every step has actually succeeded.
42
+ STATE_DIR="/workspace/.citizen-builder"
43
+
44
+ # A workspace provisioned by an earlier version of this script kept no state. Its package.json
45
+ # means `mj install` completed and the old script then ran every remaining step, so treat it as
46
+ # provisioned: re-running `mj app install` against its already-installed app would fail.
47
+ if [ -f "/workspace/package.json" ] && [ ! -d "$STATE_DIR" ]; then
48
+ mkdir -p "$STATE_DIR"
49
+ touch "$STATE_DIR/core-installed" "$STATE_DIR/app-installed" "$STATE_DIR/provisioned"
50
+ fi
51
+ mkdir -p "$STATE_DIR"
52
+
53
+ if [ ! -f "$STATE_DIR/provisioned" ]; then
38
54
  echo ""
39
55
  echo "========================================================================"
40
56
  echo " First-Time Setup: Installing MemberJunction via 'mj install'..."
41
57
  echo " This runs once and initializes your database, API, and Explorer."
42
58
  echo "========================================================================"
43
59
 
44
- # Generate install configuration
45
- cat << EOF > /tmp/install.config.json
60
+ if [ ! -f "$STATE_DIR/core-installed" ]; then
61
+ # Generate install configuration
62
+ cat << EOF > /tmp/install.config.json
46
63
  {
47
64
  "PackageManager": "pnpm",
48
65
  "dbUrl": "$DB_HOST",
@@ -67,35 +84,54 @@ if [ ! -f "/workspace/package.json" ]; then
67
84
  }
68
85
  EOF
69
86
 
70
- # Execute headless install
71
- mj install --yes --fast --config /tmp/install.config.json --dir /workspace
72
- pnpm add -w @angular/compiler@21.2.22 2>/dev/null || true
87
+ # Install the release this workspace is pinned to (MJ_VERSION, the same release as the CLI
88
+ # in this container). Without a tag, `mj install --yes` takes the newest stable GitHub
89
+ # release, which need not match that CLI.
90
+ INSTALL_TAG_ARGS=()
91
+ if [ -n "${MJ_VERSION:-}" ]; then
92
+ INSTALL_TAG_ARGS=(--tag "v${MJ_VERSION}")
93
+ else
94
+ echo "WARNING: MJ_VERSION is not set; 'mj install' will pick the newest stable release, which may not match this container's CLI."
95
+ fi
96
+
97
+ # Execute headless install. Safe to retry: the installer checkpoints completed phases.
98
+ mj install --yes --fast --config /tmp/install.config.json --dir /workspace "${INSTALL_TAG_ARGS[@]}"
99
+ touch "$STATE_DIR/core-installed"
100
+ pnpm add -w @angular/compiler@21.2.22 2>/dev/null || true
101
+ fi
73
102
 
74
103
  # Install Open App business context (More Cheese default or custom enterprise app)
75
- APP_URL="${OPEN_APP_INSTALL_URL:-https://github.com/MemberJunction/more-cheese}"
76
- echo "Installing business context Open App: $APP_URL..."
77
- if [ -n "$GITHUB_TOKEN" ]; then
78
- AUTH_APP_URL=$(echo "$APP_URL" | sed -E "s|https://github.com/|https://$GITHUB_TOKEN@github.com/|")
79
- mj app install "$AUTH_APP_URL" || echo "Notice: mj app install completed or skipped."
80
- else
81
- mj app install "$APP_URL" || echo "Notice: mj app install completed or skipped."
104
+ if [ ! -f "$STATE_DIR/app-installed" ]; then
105
+ APP_URL="${OPEN_APP_INSTALL_URL:-https://github.com/MemberJunction/more-cheese}"
106
+ echo "Installing business context Open App: $APP_URL..."
107
+ if [ -n "$GITHUB_TOKEN" ]; then
108
+ AUTH_APP_URL=$(echo "$APP_URL" | sed -E "s|https://github.com/|https://$GITHUB_TOKEN@github.com/|")
109
+ mj app install "$AUTH_APP_URL"
110
+ else
111
+ mj app install "$APP_URL"
112
+ fi
113
+ touch "$STATE_DIR/app-installed"
82
114
  fi
83
115
 
84
- # Generate capabilities catalog
116
+ # Generate capabilities catalog. Useful to the coding agent but not needed for a running
117
+ # stack, so a failure warns instead of stopping the container, and says what it means.
85
118
  if [ -f "/work/scripts/generate-capabilities.sh" ]; then
86
- bash /work/scripts/generate-capabilities.sh || echo "Notice: Capabilities generation completed."
119
+ bash /work/scripts/generate-capabilities.sh \
120
+ || echo "WARNING: capabilities catalog generation failed, so the catalog may be missing or stale. Re-run scripts/generate-capabilities.sh."
87
121
  fi
88
122
 
89
- # Push starter metadata
123
+ # Push starter metadata. --ci: never prompt (there is no terminal here) and exit non-zero
124
+ # on error. Safe to repeat on a retry: mj sync push upserts.
90
125
  if [ -d "/work/metadata" ]; then
91
- mj sync push --dir /work/metadata || echo "Notice: Initial metadata push completed."
126
+ mj sync push --dir /work/metadata --ci
92
127
  fi
93
128
 
129
+ touch "$STATE_DIR/provisioned"
94
130
  echo "MemberJunction installation and provisioning complete!"
95
131
  else
96
132
  echo "Existing MemberJunction workspace detected in /workspace."
97
- # Apply any pending migrations
98
- mj migrate || echo "Database migrations up to date."
133
+ # Apply any pending migrations (exits 0 when already up to date)
134
+ mj migrate
99
135
  fi
100
136
 
101
137
  # Configure MJExplorer host binding and compiler alignment