docs: apply fleet-template (16-artifact scaffold)

Adds missing standard artifacts:
- README.md (if missing)
- AGENTS.md (AI agent contract)
- PLAN.md (current sprint)
- STATUS.md (where we are)
- DEVELOPMENT.md (dev workflow)
- DEPLOYMENT.md (deploy procedure)
- TESTING.md (test strategy)
- DECISIONS.md (ADR index + templates)
- .github/CODEOWNERS
- .github/workflows/ci.yml

Preserves all existing artifacts.

Refs: RugMunchMedia/fleet-template
This commit is contained in:
Crypto Rug Munch 2026-07-02 02:07:13 +07:00
commit 47ba268131
310 changed files with 38429 additions and 0 deletions

View file

@ -0,0 +1,12 @@
(() => {
const getChannelData = AudioBuffer.prototype.getChannelData;
AudioBuffer.prototype.getChannelData = function(channel) {
const data = getChannelData.call(this, channel);
for (let i = 0; i < data.length; i += 100) {
data[i] += (Math.random() - 0.5) * 0.0001;
}
return data;
};
})();

View file

@ -0,0 +1,18 @@
(() => {
const noise = 0.00017348278297823374;
const toDataURL = HTMLCanvasElement.prototype.toDataURL;
HTMLCanvasElement.prototype.toDataURL = function(type, quality) {
const canvas = this;
const ctx = canvas.getContext('2d');
if (ctx) {
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
for (let i = 0; i < imageData.data.length; i += 4) {
imageData.data[i] = Math.min(255, Math.max(0, imageData.data[i] + (Math.random() > 0.5 ? 1 : -1) * noise * 255));
}
ctx.putImageData(imageData, 0, 0);
}
return toDataURL.call(this, type, quality);
};
})();

View file

@ -0,0 +1,31 @@
(() => {
window.__pry_mouse = { x: 0, y: 0, clicks: 0 };
document.addEventListener('mousemove', (e) => {
window.__pry_mouse.x = e.clientX;
window.__pry_mouse.y = e.clientY;
});
window.__pry_humanClick = async (selector) => {
const el = document.querySelector(selector);
if (!el) return;
const rect = el.getBoundingClientRect();
const targetX = rect.left + rect.width / 2 + (Math.random() - 0.5) * 10;
const targetY = rect.top + rect.height / 2 + (Math.random() - 0.5) * 10;
const steps = Math.floor(Math.random() * 10) + 15;
for (let i = 0; i <= steps; i++) {
const t = i / steps;
const x = window.__pry_mouse.x + (targetX - window.__pry_mouse.x) * (1 - Math.pow(1 - t, 3));
const y = window.__pry_mouse.y + (targetY - window.__pry_mouse.y) * (1 - Math.pow(1 - t, 3));
el.dispatchEvent(new MouseEvent('mousemove', { clientX: x, clientY: y, bubbles: true }));
await new Promise(r => setTimeout(r, Math.random() * 30 + 10));
}
el.dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
await new Promise(r => setTimeout(r, Math.random() * 100 + 50));
el.dispatchEvent(new MouseEvent('mousedown', { bubbles: true }));
await new Promise(r => setTimeout(r, Math.random() * 50 + 20));
el.dispatchEvent(new MouseEvent('mouseup', { bubbles: true }));
el.dispatchEvent(new MouseEvent('click', { bubbles: true }));
window.__pry_mouse.clicks++;
};
})();

View file

@ -0,0 +1,19 @@
(() => {
window.__pry_humanType = async (selector, text) => {
const el = document.querySelector(selector);
if (!el) return;
el.focus();
el.value = '';
for (const char of text) {
el.value += char;
el.dispatchEvent(new Event('input', { bubbles: true }));
el.dispatchEvent(new Event('keydown', { bubbles: true }));
el.dispatchEvent(new Event('keyup', { bubbles: true }));
const delay = char === ' ' ? Math.random() * 200 + 100 : Math.random() * 80 + 40;
await new Promise(r => setTimeout(r, delay));
}
el.dispatchEvent(new Event('change', { bubbles: true }));
};
})();

View file

@ -0,0 +1,14 @@
(() => {
Object.defineProperty(navigator, 'webdriver', { get: () => undefined });
Object.defineProperty(navigator, 'plugins', { get: () => [1, 2, 3, 4, 5] });
Object.defineProperty(navigator, 'languages', { get: () => ['en-US', 'en'] });
Object.defineProperty(navigator, 'hardwareConcurrency', { get: () => Math.floor(Math.random() * 4) + 2 });
Object.defineProperty(navigator, 'deviceMemory', { get: () => Math.floor(Math.random() * 4) + 2 });
window.chrome = { runtime: {} };
const originalQuery = window.navigator.permissions.query;
window.navigator.permissions.query = (p) => (
p.name === 'notifications' ? Promise.resolve({state: 'denied'}) : originalQuery(p)
);
})();

View file

@ -0,0 +1,18 @@
(() => {
const noise = 0.0008210699841618288;
const getParameter = WebGLRenderingContext.prototype.getParameter;
WebGLRenderingContext.prototype.getParameter = function(p) {
if (p === 37445) return 'Intel Inc.';
if (p === 37446) return 'Intel Iris OpenGL Engine';
const result = getParameter.call(this, p);
if (typeof result === 'number' && !Number.isInteger(result)) return result + noise;
return result;
};
const getExtension = WebGLRenderingContext.prototype.getExtension;
WebGLRenderingContext.prototype.getExtension = function(name) {
if (name === 'WEBGL_debug_renderer_info') return null;
return getExtension.call(this, name);
};
})();