@bongos/core 1.24.7 → 1.24.8
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/.bongos-core.json +97 -37
- package/clients/bongos-client/README.md +1 -1
- package/clients/bongos-client/bongos-client.global.js +8 -0
- package/clients/bongos-client/index.cjs +8 -0
- package/clients/bongos-client/index.d.ts +12 -0
- package/clients/bongos-client/index.mjs +8 -0
- package/docs/api/openapi.json +260 -3
- package/docs/api-reference.md +6 -2
- package/docs/copy-inventory.md +27 -4
- package/docs/copy-registry.json +244 -6
- package/docs/module-api-changelog.md +2 -0
- package/docs/page-inventory.json +40 -4
- package/docs/page-readings.json +61 -1
- package/modules/government/decision-board.js +5 -0
- package/modules/government/decision-rules.js +3 -0
- package/modules/government/routes/government.js +2 -0
- package/modules/hall-ui/public/market-watch-rules-lib.js +207 -0
- package/modules/hall-ui/public/market-watch-rules.css +68 -0
- package/modules/hall-ui/public/market-watch-rules.html +54 -0
- package/modules/hall-ui/public/market-watch-rules.js +129 -0
- package/modules/hall-ui/public/market-watch-rules.states.json +17 -0
- package/modules/market-watch/matter-acts.js +59 -0
- package/modules/market-watch/module.json +5 -4
- package/modules/market-watch/proposals.js +214 -0
- package/modules/market-watch/research.js +49 -8
- package/modules/market-watch/routes/rules.js +202 -0
- package/modules/market-watch/rules-logic.js +264 -0
- package/modules/market-watch/rules-view.js +165 -0
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/release-notes.json +6 -0
- package/scripts/bongos/government-walk.js +18 -2
- package/scripts/bongos/run-unit-tests.js +3 -0
- package/src/bongos/module-scope-map.js +2 -0
- package/src/bongos/serve-internal.js +2 -1
- package/src/module-api.js +1 -1
- package/tests/government_act_alone_buildings.mjs +3 -0
- package/tests/government_decision_rules.mjs +4 -1
- package/tests/governor_matter_acts.mjs +5 -1
- package/tests/hall_page_gate_map.mjs +3 -0
- package/tests/market_watch_module.mjs +1 -0
- package/tests/market_watch_rules.mjs +496 -0
- package/tests/market_watch_rules_db.mjs +133 -0
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
// tests/market_watch_rules_db.mjs — the rules page's round trip against a REAL Postgres
|
|
2
|
+
// (task 1004941, goal 1000137).
|
|
3
|
+
//
|
|
4
|
+
// What only a real engine can say: a member's proposal is filed under the table's CHECKs
|
|
5
|
+
// (a rule change must name its version), approving it supersedes the version in use and
|
|
6
|
+
// writes the next one in one transaction without tripping the one-active index, the new
|
|
7
|
+
// row records who proposed it, who approved it, when and why, and the weekly run's own
|
|
8
|
+
// rules loader (store.createStore(pool).activeRules, what run.js calls) then reads it.
|
|
9
|
+
// Also: an approved add-item proposal creates the tracked item, and the page's read
|
|
10
|
+
// (rules-view.readView, with its last-run-cost and builder-name SQL) runs.
|
|
11
|
+
//
|
|
12
|
+
// The module is default:false, so CI's migrate.sh never applies its SQL: this file
|
|
13
|
+
// applies market_watch_001 and 002 itself. Rows live under a project origin no instance
|
|
14
|
+
// has and are deleted before and after. Self-skips without a reachable Postgres; in the
|
|
15
|
+
// INTEGRATION set (scripts/bongos/run-unit-tests.js). DB-free half: tests/market_watch_rules.mjs.
|
|
16
|
+
//
|
|
17
|
+
// Run: DATABASE_URL=... node tests/market_watch_rules_db.mjs
|
|
18
|
+
|
|
19
|
+
import { createRequire } from 'node:module';
|
|
20
|
+
import { readFileSync } from 'node:fs';
|
|
21
|
+
import { strict as assert } from 'node:assert';
|
|
22
|
+
import { insertTestBuilders } from './helpers.mjs';
|
|
23
|
+
|
|
24
|
+
const require = createRequire(import.meta.url);
|
|
25
|
+
const { Pool } = require('pg');
|
|
26
|
+
const seed = require('../modules/market-watch/seed.js');
|
|
27
|
+
const store = require('../modules/market-watch/store.js');
|
|
28
|
+
const proposals = require('../modules/market-watch/proposals.js');
|
|
29
|
+
const view = require('../modules/market-watch/rules-view.js');
|
|
30
|
+
const research = require('../modules/market-watch/research.js');
|
|
31
|
+
const pricing = require('../src/bongos/llm-pricing.js');
|
|
32
|
+
|
|
33
|
+
const MIGRATION = readFileSync(new URL('../modules/market-watch/migrations/market_watch_001_tables.sql', import.meta.url), 'utf8');
|
|
34
|
+
const MIGRATION_002 = readFileSync(new URL('../modules/market-watch/migrations/market_watch_002_run.sql', import.meta.url), 'utf8');
|
|
35
|
+
|
|
36
|
+
const pool = new Pool({ connectionString: process.env.DATABASE_URL || undefined });
|
|
37
|
+
try {
|
|
38
|
+
await pool.query('SELECT 1');
|
|
39
|
+
} catch (e) {
|
|
40
|
+
console.log(`market_watch_rules_db.mjs SKIPPED — no reachable Postgres (${e.code || e.message}).`);
|
|
41
|
+
await pool.end().catch(() => {});
|
|
42
|
+
process.exit(0);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const P = 'https://t1004941-rules.example';
|
|
46
|
+
const OWNER = 91049411, ADA = 91049412;
|
|
47
|
+
const q = (sql, params) => pool.query(sql, params);
|
|
48
|
+
const withTx = async (fn) => {
|
|
49
|
+
const client = await pool.connect();
|
|
50
|
+
try {
|
|
51
|
+
await client.query('BEGIN');
|
|
52
|
+
const out = await fn(client);
|
|
53
|
+
await client.query('COMMIT');
|
|
54
|
+
return out;
|
|
55
|
+
} catch (e) {
|
|
56
|
+
await client.query('ROLLBACK').catch(() => {});
|
|
57
|
+
throw e;
|
|
58
|
+
} finally { client.release(); }
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
async function cleanup() {
|
|
62
|
+
await q(`DELETE FROM market_watch_proposals WHERE project = $1`, [P]).catch(() => {});
|
|
63
|
+
await q(`DELETE FROM market_watch_items WHERE project = $1`, [P]).catch(() => {});
|
|
64
|
+
await q(`DELETE FROM market_watch_rule_versions WHERE project = $1`, [P]).catch(() => {});
|
|
65
|
+
await q(`DELETE FROM builders WHERE id = ANY($1::bigint[])`, [[OWNER, ADA]]).catch(() => {});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
let failed = 0;
|
|
69
|
+
async function check(name, fn) {
|
|
70
|
+
try { await fn(); console.log(`ok - ${name}`); } catch (e) { failed += 1; console.log(`not ok - ${name}\n ${e && e.stack}`); }
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
try {
|
|
74
|
+
await q(MIGRATION);
|
|
75
|
+
await q(MIGRATION_002);
|
|
76
|
+
await cleanup();
|
|
77
|
+
await insertTestBuilders(pool, [{ id: OWNER, login: 't1004941-owner' }, { id: ADA, login: 't1004941-ada' }]);
|
|
78
|
+
const r = seed.RULES_V1;
|
|
79
|
+
await q(`INSERT INTO market_watch_rule_versions (project, version, status, search_queries, sources, rubric, instructions, summary, reason, approved_at)
|
|
80
|
+
VALUES ($1, 1, 'active', $2::jsonb, $3::jsonb, $4::jsonb, $5, $6, $7, now())`,
|
|
81
|
+
[P, JSON.stringify(r.searchQueries), JSON.stringify(r.sources), JSON.stringify(seed.RUBRIC), r.instructions, r.summary, r.reason]);
|
|
82
|
+
|
|
83
|
+
await check('a proposal round-trips to a new version, and the weekly run\'s rules loader reads it', async () => {
|
|
84
|
+
const filed = await proposals.createProposal(pool, {
|
|
85
|
+
project: P, step: 'searches', change: { op: 'add', text: 'open-source bounty boards' }, reason: 'finds Algora and Opire', proposedBy: ADA,
|
|
86
|
+
});
|
|
87
|
+
assert.equal(filed.ok, true, JSON.stringify(filed));
|
|
88
|
+
const out = await proposals.decideProposal({ project: P, id: filed.proposal.id, decision: 'approve', decidedBy: OWNER, withTx });
|
|
89
|
+
assert.equal(out.ok, true, JSON.stringify(out));
|
|
90
|
+
const { rows } = await q(`SELECT version, status, author_id, approved_by, approved_at, reason, search_queries
|
|
91
|
+
FROM market_watch_rule_versions WHERE project = $1 ORDER BY version`, [P]);
|
|
92
|
+
assert.deepEqual(rows.map((v) => [v.version, v.status]), [[1, 'superseded'], [2, 'active']]);
|
|
93
|
+
assert.equal(String(rows[1].author_id), String(ADA));
|
|
94
|
+
assert.equal(String(rows[1].approved_by), String(OWNER));
|
|
95
|
+
assert.ok(rows[1].approved_at instanceof Date);
|
|
96
|
+
assert.equal(rows[1].reason, 'finds Algora and Opire');
|
|
97
|
+
const loaded = await store.createStore(pool).activeRules(P);
|
|
98
|
+
assert.equal(loaded.version, 2);
|
|
99
|
+
assert.ok(loaded.search_queries.includes('open-source bounty boards'));
|
|
100
|
+
const { rows: [p] } = await q(`SELECT status, decided_by, rule_version_id FROM market_watch_proposals WHERE id = $1`, [filed.proposal.id]);
|
|
101
|
+
assert.equal(p.status, 'applied');
|
|
102
|
+
assert.equal(String(p.rule_version_id), String(out.version.id));
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
await check('an approved add-item proposal creates the tracked item', async () => {
|
|
106
|
+
const filed = await proposals.createProposal(pool, {
|
|
107
|
+
project: P, step: 'names', change: { op: 'add', name: 'Algora', url: 'https://algora.io', kind: 'competitor', why: 'bounties' }, reason: 'they pay per task', proposedBy: ADA,
|
|
108
|
+
});
|
|
109
|
+
const out = await proposals.decideProposal({ project: P, id: filed.proposal.id, decision: 'approve', decidedBy: OWNER, withTx });
|
|
110
|
+
assert.equal(out.status, 'applied');
|
|
111
|
+
const { rows: [it] } = await q(`SELECT kind, url, added_via, added_by, status FROM market_watch_items WHERE project = $1 AND name = 'Algora'`, [P]);
|
|
112
|
+
assert.deepEqual([it.kind, it.url, it.added_via, String(it.added_by), it.status], ['competitor', 'https://algora.io', 'proposal', String(ADA), 'active']);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
await check('the page read runs on the real schema', async () => {
|
|
116
|
+
await proposals.createProposal(pool, { project: P, step: 'brief', change: { op: 'set', text: 'Write five lines.' }, reason: 'shorter', proposedBy: ADA });
|
|
117
|
+
const page = await view.readView(pool, { project: P, decide: { mode: 'owner' }, pricing, model: research.MODEL });
|
|
118
|
+
assert.deepEqual(page.history.map((h) => h.version), [1, 2]);
|
|
119
|
+
assert.equal(page.history[1].by, 't1004941-ada');
|
|
120
|
+
assert.equal(page.next.version, 3);
|
|
121
|
+
assert.equal(page.cost.basis, 'estimate', 'no run has cost anything here');
|
|
122
|
+
assert.equal(page.steps.find((s) => s.key === 'names').value, 1);
|
|
123
|
+
});
|
|
124
|
+
} finally {
|
|
125
|
+
await cleanup();
|
|
126
|
+
await pool.end();
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (failed) {
|
|
130
|
+
console.log(`market_watch_rules_db.mjs: ${failed} failed`);
|
|
131
|
+
process.exit(1);
|
|
132
|
+
}
|
|
133
|
+
console.log('market_watch_rules_db.mjs: all passed');
|