fix: redact operational skill review sources

This commit is contained in:
Marcos Paulo
2026-09-04 04:37:04 +00:00
parent aa85864868
commit 6ccc692759
17 changed files with 117 additions and 189 deletions
+47 -27
View File
@@ -1,15 +1,28 @@
import { catalog } from './catalog.js';
import { files } from './files.js';
const state = { selected: catalog[0], query: '', preview: 'original', source: '', file: null };
const state = { selected: catalog[0], query: '', preview: 'original', file: null, sourceByPath: new Map(), lens: false };
const $ = (selector) => document.querySelector(selector);
const escape = (value) => value.replace(/[&<>"']/g, (character) => ({ '&':'&amp;', '<':'&lt;', '>':'&gt;', '"':'&quot;', "'":'&#039;' })[character]);
const redact = (value) => value.replace(/(NDO_PASS[^\n=]*[=:]\s*["']?)[^\n"']+/gi, '$1[REDACTED]').replace(/(password["']?\s*[:=]\s*["']?)[^\n"']+/gi, '$1[REDACTED]').replace(/\bsysadm@netcracker\.com\b/gi, '[REDACTED SERVICE ACCOUNT]');
const redact = (value, entry) => {
const safe = value.replace(/(NDO_PASS[^\n=]*[=:]\s*["']?)[^\n"']+/gi, '$1[REDACTED]').replace(/(password["']?\s*[:=]\s*["']?)[^\n"']+/gi, '$1[REDACTED]').replace(/\b[\w.+-]+@[\w.-]+\.[a-z]{2,}\b/gi, '[REDACTED SERVICE ACCOUNT]');
return entry.id === 'ndo-repro' ? safe.replace(/https?:\/\/[^\s)>]+/gi, '[REDACTED URL]').replace(/\b(?:[\w-]+\.)*netcracker\.[\w.-]+\b/gi, '[REDACTED HOST]').replace(/\bpedro[._ -]?aranha\b/gi, '[REDACTED CONTRIBUTOR]') : safe;
};
const download = (name, content) => { const url = URL.createObjectURL(new Blob([content], { type: 'text/markdown' })); const a = document.createElement('a'); a.href = url; a.download = name; a.click(); URL.revokeObjectURL(url); };
const copy = async (content) => {
if (navigator.clipboard?.writeText) return navigator.clipboard.writeText(content);
const textarea = document.createElement('textarea'); textarea.value = content; textarea.setAttribute('readonly', ''); textarea.style.position = 'fixed'; textarea.style.opacity = '0'; document.body.append(textarea); textarea.select(); document.execCommand('copy'); textarea.remove();
};
const packageFiles = (entry = state.selected) => files[entry.id] || [{ name: 'SKILL.md', path: entry.path, kind: 'skill' }];
const unchangedDraft = (file) => `# ${file.name}\n\n> Kept as-is in the improved package\n\nThis ${file.kind} file was not rewritten. Select **Change lens** to see why the improved draft concentrates its changes in the main skill contract.`;
const currentSource = () => state.sourceByPath.get(state.file.path);
const currentContent = () => state.preview === 'original' ? (currentSource() || 'Loading original file…') : (state.file.improved || (state.file.name === 'SKILL.md' ? state.selected.improved : (currentSource() ? `# ${state.file.name}\n\n> Kept as-is in the improved package\n\n${currentSource()}` : unchangedDraft(state.file))));
const changeRows = (entry) => entry.improve.map((why, index) => ({
kind: ['SAFETY', 'SCOPE', 'EVIDENCE', 'STRUCTURE'][index] || 'CLARITY',
before: index === 0 ? 'The submitted guidance leaves a material decision implicit.' : 'The submitted package carries detail without a clear boundary.',
after: index === 0 ? 'The improved draft makes the operating rule explicit.' : 'The improved draft moves the decision into a smaller, reviewable contract.',
why
}));
function visible() { return catalog.filter((item) => `${item.author} ${item.title} ${item.focus}`.toLowerCase().includes(state.query)); }
function syncUrl() {
@@ -18,48 +31,55 @@ function syncUrl() {
url.searchParams.set('skill', state.selected.id);
url.searchParams.set('view', state.preview);
if (state.file && state.file.name !== 'SKILL.md') url.searchParams.set('file', state.file.name); else url.searchParams.delete('file');
if (state.preview === 'improved' && state.lens) url.searchParams.set('lens', 'changes'); else url.searchParams.delete('lens');
history.replaceState({}, '', url);
}
function selectFromUrl() {
const params = new URLSearchParams(window.location.search);
const author = params.get('author');
const id = params.get('skill');
const view = params.get('view');
const author = params.get('author'); const id = params.get('skill'); const view = params.get('view');
const byAuthor = author && catalog.filter((item) => item.author.toLowerCase() === author.toLowerCase());
const byId = id && catalog.find((item) => item.id === id);
state.selected = byId || byAuthor?.[0] || catalog[0];
state.query = byAuthor ? state.selected.author.toLowerCase() : '';
state.preview = view === 'improved' ? 'improved' : 'original';
const available = files[state.selected.id] || [{ name:'SKILL.md', path:state.selected.path, kind:'skill' }];
state.file = available.find((item) => item.name === params.get('file')) || available[0];
state.lens = state.preview === 'improved' && params.get('lens') === 'changes';
state.file = packageFiles().find((item) => item.name === params.get('file')) || packageFiles()[0];
$('#skill-filter').value = byAuthor ? state.selected.author : '';
}
function renderList() {
const items = visible();
$('#count').textContent = `${items.length} of ${catalog.length} reviewed`;
$('#skill-list').innerHTML = items.map((item) => `<button role="option" aria-selected="${item.id === state.selected.id}" class="${item.id === state.selected.id ? 'active' : ''}" data-id="${item.id}"><span>${escape(item.author)}</span><strong>${escape(item.title)}</strong><small>${escape(item.status)}</small></button>`).join('');
$('#skill-list').querySelectorAll('button').forEach((button) => button.addEventListener('click', () => { state.selected = catalog.find((item) => item.id === button.dataset.id); state.file = (files[state.selected.id] || [{ name:'SKILL.md', path:state.selected.path, kind:'skill' }])[0]; state.preview = 'original'; state.source = ''; syncUrl(); renderList(); renderDetail(); }));
$('#skill-list').querySelectorAll('button').forEach((button) => button.addEventListener('click', () => {
state.selected = catalog.find((item) => item.id === button.dataset.id); state.file = packageFiles()[0]; state.preview = 'original'; state.lens = false; syncUrl(); renderList(); renderDetail(); loadSelectedFile();
}));
}
async function original(entry) {
if (state.source) return state.source;
try { state.source = redact(await (await fetch(state.file.path)).text()); } catch { state.source = '# Original preview unavailable\n\nServe this site from the repository root to load the submitted source.'; }
renderDetail();
return state.source;
async function loadSelectedFile() {
const entry = state.selected; const file = state.file;
if (state.sourceByPath.has(file.path)) return state.sourceByPath.get(file.path);
try { state.sourceByPath.set(file.path, redact(await (await fetch(file.path)).text(), entry)); }
catch { state.sourceByPath.set(file.path, '# Original preview unavailable\n\nServe this site from the repository root to load the submitted source.'); }
if (state.selected.id === entry.id && state.file.path === file.path) renderDetail();
return state.sourceByPath.get(file.path);
}
function lensMarkup(entry) {
return `<section class="change-lens" aria-label="Why this improved draft changed"><header><div><span>CHANGE LENS</span><h3>What changed — and why.</h3></div><button data-lens aria-pressed="true">Back to draft</button></header><p>The improved draft keeps the job, but narrows the decisions an agent must make from memory.</p><div class="change-rows">${changeRows(entry).map((change, index) => `<article><span>0${index + 1} / ${change.kind}</span><div><b> Before</b><p>${escape(change.before)}</p></div><div><b>+ After</b><p>${escape(change.after)}</p></div><aside><b>Why</b><p>${escape(change.why)}</p></aside></article>`).join('')}</div></section>`;
}
function previewMarkup(entry, available) {
if (state.preview === 'improved' && state.lens) return lensMarkup(entry);
const label = state.preview === 'original' ? 'ORIGINAL / SAFETY-REDACTED WHERE NEEDED' : 'IMPROVED DRAFT / PACKAGE-AWARE';
return `<section class="preview"><header><span>${label}</span><div>${state.preview === 'improved' ? '<button data-lens aria-pressed="false">Change lens</button>' : ''}<button data-copy>Copy</button><button data-download>Download</button></div></header><nav class="file-tabs" aria-label="Skill package files">${available.map((item) => `<button class="${item.name === state.file.name ? 'active' : ''}" data-file="${escape(item.name)}"><span>${escape(item.kind)}</span>${escape(item.name)}</button>`).join('')}</nav><pre><code>${escape(currentContent())}</code></pre></section>`;
}
function renderDetail() {
const entry = state.selected; const available = files[entry.id] || [{ name:'SKILL.md', path:entry.path, kind:'skill' }]; const markdown = state.preview === 'original' ? (state.source || 'Loading original Markdown…') : entry.improved;
$('#detail').innerHTML = `<header><div><span class="status">${escape(entry.status)}</span><h2>${escape(entry.title)}</h2><p>Submitted by <a class="author-link" href="?author=${encodeURIComponent(entry.author)}">${escape(entry.author)}</a> · <a class="share-link" href="?author=${encodeURIComponent(entry.author)}&skill=${encodeURIComponent(entry.id)}&view=${state.preview}">share review ↗</a></p></div><div class="switch" role="group" aria-label="Preview version"><button class="${state.preview === 'original' ? 'active' : ''}" data-preview="original">Original</button><button class="${state.preview === 'improved' ? 'active' : ''}" data-preview="improved">Improved draft</button></div></header>
<div class="purpose"><span>THE JOB</span><p>${escape(entry.focus)}</p></div>
<div class="review-grid"><section><span>WHAT'S ALREADY WORKING</span><ul>${entry.wins.map((item) => `<li>${escape(item)}</li>`).join('')}</ul></section><section><span>HIGHEST-VALUE IMPROVEMENTS</span><ul>${entry.improve.map((item) => `<li>${escape(item)}</li>`).join('')}</ul></section></div>
<aside class="extras"><span>GOOD NEXT ADDITION</span><p>${escape(entry.extras)}</p></aside>
<section class="preview"><header><span>${state.preview === 'original' ? 'ORIGINAL / SAFETY-REDACTED WHERE NEEDED' : 'IMPROVED DRAFT / READY TO ADAPT'}</span><div><button data-copy>Copy</button><button data-download>Download</button></div></header><nav class="file-tabs" aria-label="Skill package files">${available.map((item) => `<button class="${item.name === state.file.name ? 'active' : ''}" data-file="${escape(item.name)}"><span>${escape(item.kind)}</span>${escape(item.name)}</button>`).join('')}</nav><pre><code>${escape(markdown)}</code></pre></section>`;
$('#detail').querySelectorAll('[data-file]').forEach((button) => button.addEventListener('click', () => { state.file = available.find((item) => item.name === button.dataset.file) || available[0]; state.source = ''; state.preview = 'original'; syncUrl(); renderDetail(); }));
$('#detail').querySelectorAll('[data-preview]').forEach((button) => button.addEventListener('click', () => { state.preview = button.dataset.preview; state.source = state.preview === 'original' ? state.source : ''; syncUrl(); renderDetail(); if (state.preview === 'original') original(entry); }));
$('[data-copy]').addEventListener('click', async () => { const content = state.preview === 'original' ? await original(entry) : entry.improved; await copy(content); $('[data-copy]').textContent = 'Copied'; });
$('[data-download]').addEventListener('click', async () => download(`${entry.id}-${state.file.name.replaceAll('/', '-')}-${state.preview}.md`, state.preview === 'original' ? await original(entry) : entry.improved));
if (state.preview === 'original' && !state.source) original(entry);
const entry = state.selected; const available = packageFiles(entry);
$('#detail').innerHTML = `<header><div><span class="status">${escape(entry.status)}</span><h2>${escape(entry.title)}</h2><p>Submitted by <a class="author-link" href="?author=${encodeURIComponent(entry.author)}">${escape(entry.author)}</a> · <a class="share-link" href="?author=${encodeURIComponent(entry.author)}&skill=${encodeURIComponent(entry.id)}&view=${state.preview}">share review ↗</a></p></div><div class="switch" role="group" aria-label="Preview version"><button class="${state.preview === 'original' ? 'active' : ''}" data-preview="original">Original</button><button class="${state.preview === 'improved' ? 'active' : ''}" data-preview="improved">Improved draft</button></div></header><div class="purpose"><span>THE JOB</span><p>${escape(entry.focus)}</p></div><div class="review-grid"><section><span>WHAT'S ALREADY WORKING</span><ul>${entry.wins.map((item) => `<li>${escape(item)}</li>`).join('')}</ul></section><section><span>HIGHEST-VALUE IMPROVEMENTS</span><ul>${entry.improve.map((item) => `<li>${escape(item)}</li>`).join('')}</ul></section></div><aside class="extras"><span>GOOD NEXT ADDITION</span><p>${escape(entry.extras)}</p></aside>${previewMarkup(entry, available)}`;
$('#detail').querySelectorAll('[data-file]').forEach((button) => button.addEventListener('click', () => { state.file = available.find((item) => item.name === button.dataset.file) || available[0]; syncUrl(); renderDetail(); loadSelectedFile(); }));
$('#detail').querySelectorAll('[data-preview]').forEach((button) => button.addEventListener('click', () => { state.preview = button.dataset.preview; state.lens = false; syncUrl(); renderDetail(); loadSelectedFile(); }));
$('#detail').querySelectorAll('[data-lens]').forEach((button) => button.addEventListener('click', () => { state.lens = !state.lens; syncUrl(); renderDetail(); }));
$('[data-copy]')?.addEventListener('click', async () => { await loadSelectedFile(); await copy(currentContent()); $('[data-copy]').textContent = 'Copied'; });
$('[data-download]')?.addEventListener('click', async () => { await loadSelectedFile(); download(`${entry.id}-${state.file.name.replaceAll('/', '-')}-${state.preview}.md`, currentContent()); });
}
$('#skill-filter').addEventListener('input', (event) => { state.query = event.target.value.toLowerCase().trim(); renderList(); });
window.addEventListener('popstate', () => { state.source = ''; selectFromUrl(); renderList(); renderDetail(); });
selectFromUrl();
renderList(); renderDetail();
window.addEventListener('popstate', () => { selectFromUrl(); renderList(); renderDetail(); loadSelectedFile(); });
selectFromUrl(); renderList(); renderDetail(); loadSelectedFile();