openvibers/openvibe.meme Commits
AI text may describe people: openvibe-sdk 0.78.0 (replaces #26) (#35)
Changes
@@@ -9,11 +9,11 @@"port": "5120","domain": "openvibe.meme","contracts": "openvibe-contracts v0.234.0",-- "sdk": "openvibe-sdk v0.74.0",++ "sdk": "openvibe-sdk v0.78.0","shared": "openvibe-shared v4.67.0","packages": ["openvibe-contracts v0.234.0",-- "openvibe-sdk v0.74.0",++ "openvibe-sdk v0.78.0","openvibe-shared v4.67.0"],"summary": "OpenVibe.Meme is the open meme database, rebuilt with AI. The importer reads only public Chat and Live APIs and proposes a candidate when a recurring phrase appears in at least two uses on two different days; the candidate is born hidden with a verbatim citation for every use and stays hidden until a staff person publishes it. Every citation is re-verified daily, a 404 marks it gone and an entry whose origin is gone is hidden. People vote once a week for meme of the week, and a caption is plain text over a template, never a rendered image. Every public entry is one Search Fabric document queued in the service's outbox.",@@@ -16,7 +16,7 @@"helmet": "^8.1.0","iovalkey": "^0.4.0","openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.234.0",-- "openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.74.0",++ "openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.78.0","openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.67.0","pg": "^8.23.0"},@@@ -1166,9 +1166,9 @@}},"node_modules/openvibe-sdk": {-- "version": "0.74.0",-- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.74.0",-- "integrity": "sha512-DO9KVPnUriY/I4lX6ZEJtXaUvRDbJyqnqJxvlpl+zkNGFILpmuBXVJogNOCfK071Qci1gg7C4Iw1Xrseklcajg==",++ "version": "0.78.0",++ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.78.0",++ "integrity": "sha512-xOUpk7+K1gB3qhaXE0a+GpHkJZOJd+HKr7+EqfQwZqQxXr7fumMHt6/y2y0A1ersqHjZtx3WMvMc49bfBrBv2g==","license": "MIT","bin": {"openvibe-download": "bin/openvibe-download.js"@@@ -27,7 +27,7 @@"helmet": "^8.1.0","iovalkey": "^0.4.0","openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.234.0",-- "openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.74.0",++ "openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.78.0","openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.67.0","pg": "^8.23.0"},nnew file mode 100644@@@ -0,0 +1,20 @@++'use strict';++/**++ * The owner, 2026-10-31: AI text may describe people. openvibe-sdk 0.78.0 turns its looks filter off, so a summary that++ * describes a person is kept as written and nothing is held back over it. The explicit gate (sex acts and porn) is a++ * different rule and stays.++ */++const assert = require('assert');++const { cleanSummary, hasLooks } = require('../server/text/no-looks');++const { check, done } = require('./helpers/boot');++++(async () => {++ await check('a summary that describes a person is kept as written', async () => {++ assert.strictEqual(cleanSummary('Cozmo is offline', 'A shirtless man in a kitchen laughs.'), 'A shirtless man in a kitchen laughs.');++ assert.strictEqual(hasLooks('A man in a blue shirt'), false);++ });++ await check('an ordinary summary survives too', async () => {++ assert.strictEqual(cleanSummary('Cozmo is offline', 'The robot is not online; chat keeps asking about its Wi-Fi.'), 'The robot is not online; chat keeps asking about its Wi-Fi.');++ });++ done();++})().catch((e) => { console.error(e); process.exit(1); });@@@ -158,17 +158,18 @@ const answer = (score, extra = {}) => (prompt) => JSON.stringify({} finally { await t2.close(); }});-- await check('the rule: text that names looks never reaches the public', async () => {++ // The owner, 2026-10-31: AI text may describe people (openvibe-sdk 0.78.0 turns the looks filter off).++ await check('text that describes a person is published like any other', async () => {const t2 = await boot({ ai: { answer: answer(0.99, { title: 'Cozmo in his blue shirt', summary: 'A man in a kitchen says the robot is offline.' }) } });try {const entry = await candidate(t2, { slug: 'looks-one', title: 'Looks one', uses: [at(0), at(2), at(3)] });const out = await t2.ctx.judgeJob.runOnce({ force: true });-- if (out.published !== 0) throw new Error('an entry whose text names looks was published');++ if (out.published !== 1) throw new Error('an entry that describes a person was held back');const after = await t2.ctx.entries.byId(entry.id);-- if (after.visibility !== 'hidden') throw new Error('the entry is not hidden');-- if (after.title === 'Cozmo in his blue shirt') throw new Error('the title that named looks was used');++ if (after.visibility !== 'public') throw new Error('the entry is not public');++ if (after.title !== 'Cozmo in his blue shirt') throw new Error('the AI title was not used');const verdict = await t2.ctx.entries.judgement(entry.id);-- if (!verdict.looks) throw new Error('the judgement does not say the text named looks');++ if (verdict.looks) throw new Error('the judgement still flags looks');} finally { await t2.close(); }});ddeleted file mode 100644@@@ -1,38 +0,0 @@--'use strict';--/**-- * No looks in public AI text: a summary that names looks is replaced by the entry's title; a normal summary is-- * kept and repaired only where noLooks has something to repair. Verbatim quotes are never passed through.-- */--const assert = require('assert');--const { cleanSummary, hasLooks } = require('../server/text/no-looks');--const { boot, check, done } = require('./helpers/boot');----(async () => {-- await check('a summary that names looks becomes the title', async () => {-- assert.strictEqual(cleanSummary('Cozmo is offline', 'A shirtless man in a kitchen laughs.'), 'Cozmo is offline');-- assert.strictEqual(cleanSummary('Cozmo is offline', 'A little robot is not online.'), 'Cozmo is offline');-- assert.ok(hasLooks('A shirtless man in a kitchen laughs.'));-- });---- await check('an ordinary summary survives', async () => {-- const s = cleanSummary('Cozmo is offline', 'The robot is not online; chat keeps asking about its Wi-Fi.');-- assert.strictEqual(s, 'The robot is not online; chat keeps asking about its Wi-Fi.');-- });---- const t = await boot();-- try {-- await check('createCandidate stores the title, never the looks summary', async () => {-- const out = await t.ctx.entries.createCandidate({-- slug: 'looks', title: 'Robot is offline', kind: 'meme', summary: 'A shirtless man reacts to the offline robot.',-- status: 'rising', first_seen_at: new Date().toISOString(), last_seen_at: new Date().toISOString(), visibility: 'hidden',-- citations: [{ role: 'origin', source_service: 'chat', source_type: 'chat_message', source_id: '1001', quote_text: 'the robot is offline again', url: `${t.upstreams.url}/`, observed_at: new Date().toISOString() }],-- });-- assert.strictEqual(out.entry.summary, 'Robot is offline');-- const quote = await t.ctx.s.db.value('SELECT quote_text FROM meme_citations WHERE entry_id = $1', [out.entry.id]);-- assert.strictEqual(quote, 'the robot is offline again', 'the verbatim quote is not rewritten');-- });-- } finally {-- await t.close();-- }-- done();--})();
@@ -9,11 +9,11 @@
@@ -9,11 +9,11 @@
"port": "5120",
"port": "5120",
"domain": "openvibe.meme",
"domain": "openvibe.meme",
"contracts": "openvibe-contracts v0.234.0",
"contracts": "openvibe-contracts v0.234.0",
- "sdk": "openvibe-sdk v0.74.0",
+ "sdk": "openvibe-sdk v0.78.0",
"shared": "openvibe-shared v4.67.0",
"shared": "openvibe-shared v4.67.0",
"packages": [
"packages": [
"openvibe-contracts v0.234.0",
"openvibe-contracts v0.234.0",
- "openvibe-sdk v0.74.0",
+ "openvibe-sdk v0.78.0",
"openvibe-shared v4.67.0"
"openvibe-shared v4.67.0"
],
],
"summary": "OpenVibe.Meme is the open meme database, rebuilt with AI. The importer reads only public Chat and Live APIs and proposes a candidate when a recurring phrase appears in at least two uses on two different days; the candidate is born hidden with a verbatim citation for every use and stays hidden until a staff person publishes it. Every citation is re-verified daily, a 404 marks it gone and an entry whose origin is gone is hidden. People vote once a week for meme of the week, and a caption is plain text over a template, never a rendered image. Every public entry is one Search Fabric document queued in the service's outbox.",
"summary": "OpenVibe.Meme is the open meme database, rebuilt with AI. The importer reads only public Chat and Live APIs and proposes a candidate when a recurring phrase appears in at least two uses on two different days; the candidate is born hidden with a verbatim citation for every use and stays hidden until a staff person publishes it. Every citation is re-verified daily, a 404 marks it gone and an entry whose origin is gone is hidden. People vote once a week for meme of the week, and a caption is plain text over a template, never a rendered image. Every public entry is one Search Fabric document queued in the service's outbox.",
@@ -16,7 +16,7 @@
@@ -16,7 +16,7 @@
"helmet": "^8.1.0",
"helmet": "^8.1.0",
"iovalkey": "^0.4.0",
"iovalkey": "^0.4.0",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.234.0",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.234.0",
- "openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.74.0",
+ "openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.78.0",
"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.67.0",
"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.67.0",
"pg": "^8.23.0"
"pg": "^8.23.0"
},
},
@@ -1166,9 +1166,9 @@
@@ -1166,9 +1166,9 @@
}
}
},
},
"node_modules/openvibe-sdk": {
"node_modules/openvibe-sdk": {
- "version": "0.74.0",
- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.74.0",
- "integrity": "sha512-DO9KVPnUriY/I4lX6ZEJtXaUvRDbJyqnqJxvlpl+zkNGFILpmuBXVJogNOCfK071Qci1gg7C4Iw1Xrseklcajg==",
+ "version": "0.78.0",
+ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.78.0",
+ "integrity": "sha512-xOUpk7+K1gB3qhaXE0a+GpHkJZOJd+HKr7+EqfQwZqQxXr7fumMHt6/y2y0A1ersqHjZtx3WMvMc49bfBrBv2g==",
"license": "MIT",
"license": "MIT",
"bin": {
"bin": {
"openvibe-download": "bin/openvibe-download.js"
"openvibe-download": "bin/openvibe-download.js"
@@ -27,7 +27,7 @@
@@ -27,7 +27,7 @@
"helmet": "^8.1.0",
"helmet": "^8.1.0",
"iovalkey": "^0.4.0",
"iovalkey": "^0.4.0",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.234.0",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.234.0",
- "openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.74.0",
+ "openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.78.0",
"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.67.0",
"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.67.0",
"pg": "^8.23.0"
"pg": "^8.23.0"
},
},
new file mode 100644
new file mode 100644
@@ -0,0 +1,20 @@
@@ -0,0 +1,20 @@
+'use strict';
+/**
+ * The owner, 2026-10-31: AI text may describe people. openvibe-sdk 0.78.0 turns its looks filter off, so a summary that
+ * describes a person is kept as written and nothing is held back over it. The explicit gate (sex acts and porn) is a
+ * different rule and stays.
+ */
+const assert = require('assert');
+const { cleanSummary, hasLooks } = require('../server/text/no-looks');
+const { check, done } = require('./helpers/boot');
+
+(async () => {
+ await check('a summary that describes a person is kept as written', async () => {
+ assert.strictEqual(cleanSummary('Cozmo is offline', 'A shirtless man in a kitchen laughs.'), 'A shirtless man in a kitchen laughs.');
+ assert.strictEqual(hasLooks('A man in a blue shirt'), false);
+ });
+ await check('an ordinary summary survives too', async () => {
+ assert.strictEqual(cleanSummary('Cozmo is offline', 'The robot is not online; chat keeps asking about its Wi-Fi.'), 'The robot is not online; chat keeps asking about its Wi-Fi.');
+ });
+ done();
+})().catch((e) => { console.error(e); process.exit(1); });
@@ -158,17 +158,18 @@ const answer = (score, extra = {}) => (prompt) => JSON.stringify({
@@ -158,17 +158,18 @@ const answer = (score, extra = {}) => (prompt) => JSON.stringify({
} finally { await t2.close(); }
} finally { await t2.close(); }
});
});
- await check('the rule: text that names looks never reaches the public', async () => {
+ // The owner, 2026-10-31: AI text may describe people (openvibe-sdk 0.78.0 turns the looks filter off).
+ await check('text that describes a person is published like any other', async () => {
const t2 = await boot({ ai: { answer: answer(0.99, { title: 'Cozmo in his blue shirt', summary: 'A man in a kitchen says the robot is offline.' }) } });
const t2 = await boot({ ai: { answer: answer(0.99, { title: 'Cozmo in his blue shirt', summary: 'A man in a kitchen says the robot is offline.' }) } });
try {
try {
const entry = await candidate(t2, { slug: 'looks-one', title: 'Looks one', uses: [at(0), at(2), at(3)] });
const entry = await candidate(t2, { slug: 'looks-one', title: 'Looks one', uses: [at(0), at(2), at(3)] });
const out = await t2.ctx.judgeJob.runOnce({ force: true });
const out = await t2.ctx.judgeJob.runOnce({ force: true });
- if (out.published !== 0) throw new Error('an entry whose text names looks was published');
+ if (out.published !== 1) throw new Error('an entry that describes a person was held back');
const after = await t2.ctx.entries.byId(entry.id);
const after = await t2.ctx.entries.byId(entry.id);
- if (after.visibility !== 'hidden') throw new Error('the entry is not hidden');
- if (after.title === 'Cozmo in his blue shirt') throw new Error('the title that named looks was used');
+ if (after.visibility !== 'public') throw new Error('the entry is not public');
+ if (after.title !== 'Cozmo in his blue shirt') throw new Error('the AI title was not used');
const verdict = await t2.ctx.entries.judgement(entry.id);
const verdict = await t2.ctx.entries.judgement(entry.id);
- if (!verdict.looks) throw new Error('the judgement does not say the text named looks');
+ if (verdict.looks) throw new Error('the judgement still flags looks');
} finally { await t2.close(); }
} finally { await t2.close(); }
});
});
deleted file mode 100644
deleted file mode 100644
@@ -1,38 +0,0 @@
@@ -1,38 +0,0 @@
-'use strict';
-/**
- * No looks in public AI text: a summary that names looks is replaced by the entry's title; a normal summary is
- * kept and repaired only where noLooks has something to repair. Verbatim quotes are never passed through.
- */
-const assert = require('assert');
-const { cleanSummary, hasLooks } = require('../server/text/no-looks');
-const { boot, check, done } = require('./helpers/boot');
-
-(async () => {
- await check('a summary that names looks becomes the title', async () => {
- assert.strictEqual(cleanSummary('Cozmo is offline', 'A shirtless man in a kitchen laughs.'), 'Cozmo is offline');
- assert.strictEqual(cleanSummary('Cozmo is offline', 'A little robot is not online.'), 'Cozmo is offline');
- assert.ok(hasLooks('A shirtless man in a kitchen laughs.'));
- });
-
- await check('an ordinary summary survives', async () => {
- const s = cleanSummary('Cozmo is offline', 'The robot is not online; chat keeps asking about its Wi-Fi.');
- assert.strictEqual(s, 'The robot is not online; chat keeps asking about its Wi-Fi.');
- });
-
- const t = await boot();
- try {
- await check('createCandidate stores the title, never the looks summary', async () => {
- const out = await t.ctx.entries.createCandidate({
- slug: 'looks', title: 'Robot is offline', kind: 'meme', summary: 'A shirtless man reacts to the offline robot.',
- status: 'rising', first_seen_at: new Date().toISOString(), last_seen_at: new Date().toISOString(), visibility: 'hidden',
- citations: [{ role: 'origin', source_service: 'chat', source_type: 'chat_message', source_id: '1001', quote_text: 'the robot is offline again', url: `${t.upstreams.url}/`, observed_at: new Date().toISOString() }],
- });
- assert.strictEqual(out.entry.summary, 'Robot is offline');
- const quote = await t.ctx.s.db.value('SELECT quote_text FROM meme_citations WHERE entry_id = $1', [out.entry.id]);
- assert.strictEqual(quote, 'the robot is offline again', 'the verbatim quote is not rewritten');
- });
- } finally {
- await t.close();
- }
- done();
-})();