madeby 0.3.4 → 0.3.5
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/dist/madeby.mjs +93 -63
- package/package.json +1 -1
package/dist/madeby.mjs
CHANGED
|
@@ -1882,58 +1882,55 @@ function whoCommand(args) {
|
|
|
1882
1882
|
// src/init-repo.ts
|
|
1883
1883
|
import { existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync6, writeFileSync as writeFileSync2 } from "node:fs";
|
|
1884
1884
|
import { dirname as dirname2, join as join5 } from "node:path";
|
|
1885
|
-
var
|
|
1886
|
-
var
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
runs-on: ubuntu-latest
|
|
1891
|
-
steps:
|
|
1892
|
-
- uses: actions/checkout@v4
|
|
1893
|
-
with:
|
|
1894
|
-
fetch-depth: 0
|
|
1895
|
-
- uses: MadeByFYI/MadeBy/packages/action@v0.2.0
|
|
1896
|
-
`;
|
|
1897
|
-
var AGENTS_CONVENTION = `# AGENTS.md \u2014 Authorship disclosure convention (ACO)
|
|
1898
|
-
${ACO_SENTINEL}
|
|
1899
|
-
|
|
1900
|
-
This repository asks any AI agent \u2014 or a human working with one \u2014 to **disclose who authored the
|
|
1901
|
-
changes they make**, per **ACO, the Authorship Certificate of Origin**
|
|
1902
|
-
(https://github.com/MadeByFYI/MadeBy/blob/main/ACO.md).
|
|
1903
|
-
|
|
1904
|
-
## The rule
|
|
1905
|
-
|
|
1906
|
-
When you author or modify content here, disclose the authorship **category** on your commit \u2014 one of:
|
|
1907
|
-
|
|
1908
|
-
- \`human\` \u2014 a human authored it, no AI involvement.
|
|
1909
|
-
- \`with_ai\` \u2014 a human authored it with disclosed AI assistance.
|
|
1910
|
-
- \`ai\` \u2014 an AI agent authored it (a human remains accountable).
|
|
1911
|
-
|
|
1912
|
-
Disclose **per commit, honestly** \u2014 the category describes what actually happened for that change.
|
|
1913
|
-
|
|
1914
|
-
## The one-line way (asserted tier \u2014 no keys, no setup)
|
|
1915
|
-
|
|
1916
|
-
After you commit, run the matching command (works with no install via \`npx\`):
|
|
1917
|
-
|
|
1918
|
-
| Category | Command |
|
|
1919
|
-
|-----------|----------------------------------|
|
|
1920
|
-
| \`human\` | \`npx madeby@latest me\` |
|
|
1921
|
-
| \`with_ai\` | \`npx madeby@latest me --with-ai <tool>\` |
|
|
1922
|
-
| \`ai\` | \`npx madeby@latest ai [tool]\` |
|
|
1923
|
-
|
|
1924
|
-
Undisclosed content stays *unknown*, never guessed. See ACO for the standard.
|
|
1925
|
-
`;
|
|
1926
|
-
var ACO_SECTION = `
|
|
1927
|
-
${ACO_SENTINEL}
|
|
1928
|
-
## Authorship disclosure (ACO)
|
|
1885
|
+
var ACO_VERSION = 1;
|
|
1886
|
+
var ACO_OPEN = `<!-- madeby:aco v${ACO_VERSION} -->`;
|
|
1887
|
+
var ACO_CLOSE = `<!-- /madeby:aco -->`;
|
|
1888
|
+
var ACO_OPEN_RE = /<!-- madeby:aco(?: v(\d+))? -->/;
|
|
1889
|
+
var ACO_BODY = `## Authorship disclosure (ACO)
|
|
1929
1890
|
|
|
1930
|
-
|
|
1931
|
-
|
|
1891
|
+
When you author or modify content here, **disclose who authored it** \u2014 per
|
|
1892
|
+
[ACO, the Authorship Certificate of Origin](https://github.com/MadeByFYI/MadeBy/blob/main/ACO.md).
|
|
1893
|
+
After you commit, run the command for the honest category (no install, no setup):
|
|
1932
1894
|
|
|
1933
1895
|
- **ai** \u2014 an AI authored it (the committer stays accountable): \`npx madeby@latest ai [tool]\`
|
|
1934
1896
|
- **with_ai** \u2014 a human authored it with AI assistance: \`npx madeby@latest me --with-ai [tool]\`
|
|
1935
1897
|
- **human** \u2014 a human authored it: \`npx madeby@latest me\`
|
|
1898
|
+
|
|
1899
|
+
Disclose per commit, honestly. Undisclosed content stays *unknown*, never guessed.
|
|
1900
|
+
`;
|
|
1901
|
+
var ACO_BLOCK = `${ACO_OPEN}
|
|
1902
|
+
${ACO_BODY}${ACO_CLOSE}
|
|
1936
1903
|
`;
|
|
1904
|
+
var AGENTS_CONVENTION = `# AGENTS.md
|
|
1905
|
+
|
|
1906
|
+
${ACO_BLOCK}`;
|
|
1907
|
+
var ACO_SECTION = `
|
|
1908
|
+
${ACO_BLOCK}`;
|
|
1909
|
+
function findAcoBlock(content) {
|
|
1910
|
+
const m = ACO_OPEN_RE.exec(content);
|
|
1911
|
+
if (!m) return null;
|
|
1912
|
+
const start = m.index;
|
|
1913
|
+
const version = m[1] !== void 0 ? Number(m[1]) : null;
|
|
1914
|
+
const closeIdx = content.indexOf(ACO_CLOSE, start);
|
|
1915
|
+
let end;
|
|
1916
|
+
if (closeIdx !== -1) {
|
|
1917
|
+
end = closeIdx + ACO_CLOSE.length;
|
|
1918
|
+
if (content[end] === "\n") end += 1;
|
|
1919
|
+
} else {
|
|
1920
|
+
end = content.length;
|
|
1921
|
+
}
|
|
1922
|
+
return { version, start, end };
|
|
1923
|
+
}
|
|
1924
|
+
function acoStatus(content) {
|
|
1925
|
+
const loc = findAcoBlock(content);
|
|
1926
|
+
if (!loc) return "absent";
|
|
1927
|
+
if (loc.version === null || loc.version < ACO_VERSION) return "outdated";
|
|
1928
|
+
if (loc.version > ACO_VERSION) return "newer";
|
|
1929
|
+
return "current";
|
|
1930
|
+
}
|
|
1931
|
+
function replaceAcoBlock(content, loc) {
|
|
1932
|
+
return content.slice(0, loc.start) + ACO_BLOCK + content.slice(loc.end);
|
|
1933
|
+
}
|
|
1937
1934
|
function writeIfAbsent(abs, rel, content, created, skipped) {
|
|
1938
1935
|
if (existsSync4(abs)) {
|
|
1939
1936
|
skipped.push(rel);
|
|
@@ -1951,25 +1948,36 @@ function ensureAco(abs, rel, res, opts) {
|
|
|
1951
1948
|
res.created.push(rel);
|
|
1952
1949
|
return;
|
|
1953
1950
|
}
|
|
1954
|
-
const
|
|
1955
|
-
|
|
1951
|
+
const content = readFileSync6(abs, "utf8");
|
|
1952
|
+
const status = acoStatus(content);
|
|
1953
|
+
if (status === "absent") {
|
|
1954
|
+
const sep = content.endsWith("\n") ? "" : "\n";
|
|
1955
|
+
writeFileSync2(abs, content + sep + ACO_SECTION);
|
|
1956
|
+
res.merged.push(rel);
|
|
1957
|
+
} else if (status === "outdated") {
|
|
1958
|
+
if (opts.update) {
|
|
1959
|
+
writeFileSync2(abs, replaceAcoBlock(content, findAcoBlock(content)));
|
|
1960
|
+
res.updated.push(rel);
|
|
1961
|
+
} else {
|
|
1962
|
+
res.outdated.push(rel);
|
|
1963
|
+
}
|
|
1964
|
+
} else {
|
|
1956
1965
|
res.skipped.push(rel);
|
|
1957
|
-
return;
|
|
1958
1966
|
}
|
|
1959
|
-
const sep = current.endsWith("\n") ? "\n" : "\n\n";
|
|
1960
|
-
writeFileSync2(abs, current + sep + ACO_SECTION);
|
|
1961
|
-
res.merged.push(rel);
|
|
1962
1967
|
}
|
|
1963
1968
|
function initRepo(root, opts = {}) {
|
|
1964
1969
|
const mode = opts.mode ?? "advisory";
|
|
1965
1970
|
const host = opts.host ?? "github";
|
|
1971
|
+
const update = opts.update ?? false;
|
|
1966
1972
|
const created = [];
|
|
1967
1973
|
const skipped = [];
|
|
1968
1974
|
const merged = [];
|
|
1969
|
-
const
|
|
1975
|
+
const updated = [];
|
|
1976
|
+
const outdated = [];
|
|
1977
|
+
const res = { created, skipped, merged, updated, outdated };
|
|
1970
1978
|
writeIfAbsent(join5(root, ".madeby", "policy.json"), ".madeby/policy.json", JSON.stringify({ version: 0, mode }, null, 2) + "\n", created, skipped);
|
|
1971
|
-
ensureAco(join5(root, "AGENTS.md"), "AGENTS.md", res, { createIfAbsent: true });
|
|
1972
|
-
ensureAco(join5(root, "CLAUDE.md"), "CLAUDE.md", res, { createIfAbsent: false });
|
|
1979
|
+
ensureAco(join5(root, "AGENTS.md"), "AGENTS.md", res, { createIfAbsent: true, update });
|
|
1980
|
+
ensureAco(join5(root, "CLAUDE.md"), "CLAUDE.md", res, { createIfAbsent: false, update });
|
|
1973
1981
|
if (host === "github") {
|
|
1974
1982
|
writeIfAbsent(join5(root, ".github", "workflows", "disclosure.yml"), ".github/workflows/disclosure.yml", GH_WORKFLOW, created, skipped);
|
|
1975
1983
|
}
|
|
@@ -1980,6 +1988,12 @@ function initRepo(root, opts = {}) {
|
|
|
1980
1988
|
if (merged.length > 0) {
|
|
1981
1989
|
nextSteps.push(`Merged the ACO disclosure rule into your existing ${merged.join(" + ")} \u2014 review the appended "Authorship disclosure (ACO)" section and tune it to your repo.`);
|
|
1982
1990
|
}
|
|
1991
|
+
if (updated.length > 0) {
|
|
1992
|
+
nextSteps.push(`Refreshed an outdated ACO convention in ${updated.join(" + ")} to the current version \u2014 review the change before committing.`);
|
|
1993
|
+
}
|
|
1994
|
+
if (outdated.length > 0) {
|
|
1995
|
+
nextSteps.push(`${outdated.join(" + ")} carries an OUTDATED ACO convention \u2014 run 'madeby init --update' to refresh it in place (only the ACO block changes).`);
|
|
1996
|
+
}
|
|
1983
1997
|
if (host === "azure-devops") {
|
|
1984
1998
|
nextSteps.push("Add the Azure Pipelines template (packages/action/azure-pipelines-disclosure.yml) and wire it as a PR build-validation branch policy.");
|
|
1985
1999
|
} else if (host !== "github") {
|
|
@@ -1990,8 +2004,19 @@ function initRepo(root, opts = {}) {
|
|
|
1990
2004
|
}
|
|
1991
2005
|
nextSteps.push("Contributors disclose origin with a Co-Authored-By / Generated-by trailer (AI), an Authored-by-human trailer ('madeby me'), an Authored-by-ai trailer ('madeby ai' \u2014 AI authored, committer accountable), a DCO Signed-off-by, or a signed commit. Evidence upgrade: 'madeby ai --witness' records your own AI session's witnessed spans.");
|
|
1992
2006
|
nextSteps.push("Existing history is accounted for honestly, not fabricated: run 'madeby check' over full history to recognize what's already disclosed; pre-adoption commits stay unknown. See madeby://guide/backfill.");
|
|
1993
|
-
return { created, skipped, merged, policyMode: mode, host, nextSteps };
|
|
2007
|
+
return { created, skipped, merged, updated, outdated, policyMode: mode, host, nextSteps };
|
|
1994
2008
|
}
|
|
2009
|
+
var GH_WORKFLOW = `name: Disclosure
|
|
2010
|
+
on: pull_request
|
|
2011
|
+
jobs:
|
|
2012
|
+
madeby:
|
|
2013
|
+
runs-on: ubuntu-latest
|
|
2014
|
+
steps:
|
|
2015
|
+
- uses: actions/checkout@v4
|
|
2016
|
+
with:
|
|
2017
|
+
fetch-depth: 0
|
|
2018
|
+
- uses: MadeByFYI/MadeBy/packages/action@v0.2.0
|
|
2019
|
+
`;
|
|
1995
2020
|
|
|
1996
2021
|
// src/commands/init.ts
|
|
1997
2022
|
function initCommand(args) {
|
|
@@ -2002,11 +2027,14 @@ function initCommand(args) {
|
|
|
2002
2027
|
return;
|
|
2003
2028
|
}
|
|
2004
2029
|
const mode = args.includes("--required") ? "required" : "advisory";
|
|
2030
|
+
const update = args.includes("--update");
|
|
2005
2031
|
const hostIdx = args.indexOf("--host");
|
|
2006
2032
|
const host = hostIdx >= 0 ? args[hostIdx + 1] : void 0;
|
|
2007
|
-
const r = initRepo(root, { mode, host });
|
|
2033
|
+
const r = initRepo(root, { mode, host, update });
|
|
2008
2034
|
for (const f of r.created) console.log(` + ${f}`);
|
|
2009
2035
|
for (const f of r.merged) console.log(` ~ ${f} (merged in the ACO rule)`);
|
|
2036
|
+
for (const f of r.updated) console.log(` \u2191 ${f} (ACO convention refreshed to the current version)`);
|
|
2037
|
+
for (const f of r.outdated) console.log(` ! ${f} (ACO convention OUTDATED \u2014 run 'madeby init --update')`);
|
|
2010
2038
|
for (const f of r.skipped) console.log(` \xB7 ${f} (exists \u2014 left as-is)`);
|
|
2011
2039
|
console.log(`
|
|
2012
2040
|
madeby init \u2014 policy: ${r.policyMode}, host: ${r.host}`);
|
|
@@ -2018,7 +2046,7 @@ madeby init \u2014 policy: ${r.policyMode}, host: ${r.host}`);
|
|
|
2018
2046
|
import { execFileSync as execFileSync6 } from "node:child_process";
|
|
2019
2047
|
import { createInterface } from "node:readline";
|
|
2020
2048
|
var DEFAULT_PROTOCOL = "2024-11-05";
|
|
2021
|
-
var SERVER_INFO = { name: "madeby", version: "0.3.
|
|
2049
|
+
var SERVER_INFO = { name: "madeby", version: "0.3.5" };
|
|
2022
2050
|
function rootFor(path) {
|
|
2023
2051
|
const cwd = path && path.length ? path : process.cwd();
|
|
2024
2052
|
return execFileSync6("git", ["-C", cwd, "-c", "core.quotePath=false", "rev-parse", "--show-toplevel"], { encoding: "utf8" }).trim();
|
|
@@ -2033,16 +2061,17 @@ var repoInput = {
|
|
|
2033
2061
|
var TOOLS = [
|
|
2034
2062
|
{
|
|
2035
2063
|
name: "init",
|
|
2036
|
-
description: "Align a repository with MadeBy in one call: create .madeby/policy.json (advisory by default \u2014 reports, never fails) and the CI disclosure check for the host (github default; azure-devops guided). Idempotent \u2014 never clobbers an existing policy or workflow. Returns the files created/skipped and the recommended next steps. Read the resources: madeby://guide/align (full workflow), madeby://guide/enforce (make the check required \u2014 the host's control plane, exact commands), madeby://guide/backfill (account for existing history honestly \u2014 never fabricate).",
|
|
2064
|
+
description: "Align a repository with MadeBy in one call: create .madeby/policy.json (advisory by default \u2014 reports, never fails) and the CI disclosure check for the host (github default; azure-devops guided). Idempotent \u2014 never clobbers an existing policy or workflow. Returns the files created/skipped and the recommended next steps. Read the resources: madeby://guide/align (full workflow), madeby://guide/enforce (make the check required \u2014 the host's control plane, exact commands), madeby://guide/backfill (account for existing history honestly \u2014 never fabricate). The ACO convention block is versioned: the result flags an `outdated` AGENTS.md/CLAUDE.md (drift); call again with update:true to refresh just that block in place \u2014 how an agent keeps the convention current.",
|
|
2037
2065
|
inputSchema: {
|
|
2038
2066
|
type: "object",
|
|
2039
2067
|
properties: {
|
|
2040
2068
|
path: { type: "string", description: "path to the repo (default: the server's working directory)" },
|
|
2041
2069
|
mode: { enum: ["advisory", "required"], description: "policy mode to seed (default: advisory)" },
|
|
2042
|
-
host: { type: "string", description: "CI host to wire: github (default) or azure-devops" }
|
|
2070
|
+
host: { type: "string", description: "CI host to wire: github (default) or azure-devops" },
|
|
2071
|
+
update: { type: "boolean", description: "refresh an outdated ACO convention block in place (drift update); default false (report only)" }
|
|
2043
2072
|
}
|
|
2044
2073
|
},
|
|
2045
|
-
handler: (args) => initRepo(rootFor(args.path), { mode: args.mode, host: args.host })
|
|
2074
|
+
handler: (args) => initRepo(rootFor(args.path), { mode: args.mode, host: args.host, update: args.update })
|
|
2046
2075
|
},
|
|
2047
2076
|
{
|
|
2048
2077
|
name: "check",
|
|
@@ -2305,8 +2334,9 @@ function help() {
|
|
|
2305
2334
|
console.log(`madeby \u2014 verifiable content provenance ("made by whom?")
|
|
2306
2335
|
|
|
2307
2336
|
Usage:
|
|
2308
|
-
madeby init Set MadeBy up: write .madeby/policy.json + the
|
|
2309
|
-
|
|
2337
|
+
madeby init Set MadeBy up: write .madeby/policy.json + the ACO AGENTS.md convention
|
|
2338
|
+
+ the CI disclosure check. --update refreshes an outdated ACO block in
|
|
2339
|
+
place; --required to enforce now; --host azure-devops for Azure Pipelines.
|
|
2310
2340
|
madeby check [<range>] The gate: do commits meet .madeby/policy.json? (a verdict \u2014 exit
|
|
2311
2341
|
code gates). <range> e.g. origin/main..HEAD; in CI it's auto-detected.
|
|
2312
2342
|
--json for a machine-readable result.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "madeby",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.5",
|
|
4
4
|
"mcpName": "io.github.MadeByFYI/madeby",
|
|
5
5
|
"description": "Disclose AI authorship of code. `npx madeby ai` adds an Authored-by-ai git trailer; AI coding agents disclose per the ACO standard (human/with_ai/ai) from an AGENTS.md convention. Disclosure, not detection. Gate PRs with `madeby check`.",
|
|
6
6
|
"license": "MIT",
|