mirror of
https://github.com/jjbrunton/Sauci.git
synced 2026-10-31 18:19:43 +00:00
docs(question-types): document interaction contract
This commit is contained in:
1 parent
53a48ab6d5
commit
450c527d1e
8 files changed
+135
-8
No files matched your search
@@ -1,7 +1,8 @@
|
||||
import { access, readFile, readdir } from 'node:fs/promises';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const root = path.resolve(new URL('..', import.meta.url).pathname);
|
||||
const root = path.resolve(fileURLToPath(new URL('..', import.meta.url)));
|
||||
const errors = [];
|
||||
const scoped = process.argv.includes('--scope');
|
||||
|
||||
@@ -156,6 +157,22 @@ if (!scoped) {
|
||||
if (!(await exists(target))) fail(path.join(root, 'docs', 'index.md'), `broken documentation link ${match[1]}`, 'correct the link or restore the maintained document');
|
||||
}
|
||||
|
||||
const sharedTypesFile = path.join(root, 'packages', 'shared', 'src', 'types', 'index.ts');
|
||||
const sharedTypes = await readFile(sharedTypesFile, 'utf8');
|
||||
const union = sharedTypes.match(/export type QuestionType\s*=\s*([^;]+);/);
|
||||
const canonicalQuestionTypes = union?.[1].match(/'([^']+)'/g)?.map((value) => value.slice(1, -1));
|
||||
const questionTypesDoc = path.join(root, 'docs', 'question-types.md');
|
||||
const questionTypesSource = await readFile(questionTypesDoc, 'utf8');
|
||||
const documentedQuestionTypes = questionTypesSource.match(/<!-- question-types:\s*([^>]+)\s*-->/)?.[1]
|
||||
.split(',').map((value) => value.trim()).filter(Boolean);
|
||||
if (!canonicalQuestionTypes?.length) {
|
||||
fail(sharedTypesFile, 'QuestionType union could not be read', 'keep QuestionType as a quoted string union');
|
||||
} else if (!documentedQuestionTypes?.length) {
|
||||
fail(questionTypesDoc, 'question type contract marker is missing', 'add <!-- question-types: type-a,type-b --> with every supported type');
|
||||
} else if (canonicalQuestionTypes.join(',') !== documentedQuestionTypes.join(',')) {
|
||||
fail(questionTypesDoc, 'documented question types differ from the shared QuestionType union', `set the contract marker to ${canonicalQuestionTypes.join(',')}`);
|
||||
}
|
||||
|
||||
const mcpAuth = await readFile(path.join(root, 'apps', 'mcp', 'src', 'lib', 'auth.ts'), 'utf8');
|
||||
if (/allowing all requests|query\(['"]apiKey/i.test(mcpAuth)) {
|
||||
fail(path.join(root, 'apps', 'mcp', 'src', 'lib', 'auth.ts'), 'MCP authentication can leak or fail open', 'require a configured Bearer token and fail closed');
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { readFile, readdir } from 'node:fs/promises';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const root = path.resolve(new URL('..', import.meta.url).pathname);
|
||||
const root = path.resolve(fileURLToPath(new URL('..', import.meta.url)));
|
||||
const base = path.join(root, '.agents', 'learnings');
|
||||
const requiredSections = ['## Symptom', '## Reproduction', '## Cause', '## Remediation', '## Evidence'];
|
||||
const failures = [];
|
||||
@@ -11,7 +12,7 @@ for (const state of ['inbox', 'promoted']) {
|
||||
for (const name of await readdir(directory)) {
|
||||
if (!name.endsWith('.md')) continue;
|
||||
const file = path.join(directory, name);
|
||||
const source = await readFile(file, 'utf8');
|
||||
const source = (await readFile(file, 'utf8')).replace(/\r\n/g, '\n');
|
||||
const frontmatter = source.match(/^---\n([\s\S]*?)\n---/);
|
||||
if (!frontmatter) { failures.push(`${file}: missing YAML frontmatter`); continue; }
|
||||
const fields = Object.fromEntries(frontmatter[1].split('\n').map((line) => {
|
||||
|
||||
Reference in new issue
Block a user