eve-hub 0.16.23 → 0.16.25
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/package.json +1 -1
- package/prepare.mjs +22 -2
- package/templates/engineering.md +3 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eve-hub",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.25",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "Bot-side code shared by every hub agent: registry tools, the roster hook, the eve channel, the host sandbox and browser, and model helpers.",
|
|
6
6
|
"type": "module",
|
package/prepare.mjs
CHANGED
|
@@ -77,17 +77,36 @@ const broker: GitHubLeaseBroker = async (sandbox, rules) => {
|
|
|
77
77
|
// \`-R\` or \`gh repo clone|view|fork\` target differs from the declared repository, nor a \`git\`
|
|
78
78
|
// remote outside it, so this does. \`authorize\` can't read the sandbox, so a remote name such as
|
|
79
79
|
// \`origin\` can't be resolved: authenticated git names the declared repository's URL itself.
|
|
80
|
+
// \`repository\` may be null: eve's tool text tells bots to omit it for \`gh api user\`,
|
|
81
|
+
// \`gh repo list\` and \`gh search\`, and a user token isn't narrowed by it anyway.
|
|
80
82
|
const GIT_REMOTE_COMMANDS = ["fetch", "ls-remote", "pull", "push"];
|
|
83
|
+
const GIT_GLOBAL_VALUE_OPTIONS = ["-C", "-c", "--git-dir", "--work-tree", "--namespace", "--config-env"];
|
|
84
|
+
const GIT_REMOTE_VALUE_OPTIONS = ["--depth", "--deepen", "--shallow-since", "--shallow-exclude", "--upload-pack", "--receive-pack", "--exec", "--refmap", "--negotiation-tip", "-o", "--push-option", "--server-option", "-j", "--jobs", "--filter", "--recurse-submodules-default"];
|
|
81
85
|
const targets = (argv: readonly string[]) => [
|
|
82
86
|
...argv.flatMap((a, i) => (a === "--repo" || a === "-R" ? [argv[i + 1] ?? ""] : a.startsWith("--repo=") ? [a.slice(7)] : [])),
|
|
83
87
|
...(argv[0] === "gh" && argv[1] === "repo" && ["clone", "view", "fork"].includes(argv[2] ?? "") && argv[3] && !argv[3].startsWith("-") ? [argv[3]] : []),
|
|
84
88
|
];
|
|
85
89
|
const GITHUB_URL = /^(?:https:\\/\\/github\\.com\\/|git@github\\.com:|ssh:\\/\\/git@github\\.com\\/)/i;
|
|
86
90
|
const canonical = (repo: string) => repo.toLowerCase().replace(GITHUB_URL, "").replace(/\\/$/, "").replace(/\\.git$/, "");
|
|
91
|
+
const operands = (args: readonly string[], valued: readonly string[]) => {
|
|
92
|
+
const found: string[] = [];
|
|
93
|
+
for (let i = 0; i < args.length; i++) {
|
|
94
|
+
if (valued.includes(args[i])) i++;
|
|
95
|
+
else if (!args[i].startsWith("-")) found.push(args[i]);
|
|
96
|
+
}
|
|
97
|
+
return found;
|
|
98
|
+
};
|
|
99
|
+
const gitRemote = (argv: readonly string[]) => {
|
|
100
|
+
let i = 1;
|
|
101
|
+
while (argv[i]?.startsWith("-")) i += GIT_GLOBAL_VALUE_OPTIONS.includes(argv[i]) ? 2 : 1;
|
|
102
|
+
const remote = operands(argv.slice(i + 1), GIT_REMOTE_VALUE_OPTIONS)[0] ?? "";
|
|
103
|
+
return GIT_REMOTE_COMMANDS.includes(argv[i] ?? "") && GITHUB_URL.test(remote) ? [remote] : null;
|
|
104
|
+
};
|
|
87
105
|
const commandTargets = (argv: readonly string[]) =>
|
|
88
|
-
argv[0] === "git" ? (
|
|
106
|
+
argv[0] === "git" ? gitRemote(argv)
|
|
89
107
|
: argv[0] === "gh-signed-commit" ? (targets(argv).length ? targets(argv) : null)
|
|
90
108
|
: targets(argv);
|
|
109
|
+
const inOrg = (repo: string) => canonical(repo).startsWith(\`\${ORG}/\`);
|
|
91
110
|
|
|
92
111
|
export default git({
|
|
93
112
|
github: {
|
|
@@ -95,7 +114,8 @@ export default git({
|
|
|
95
114
|
broker,
|
|
96
115
|
authorize: ({ argv, repository }) => {
|
|
97
116
|
const found = commandTargets(argv);
|
|
98
|
-
|
|
117
|
+
if (found === null || !found.every(inOrg)) return false;
|
|
118
|
+
return repository === null || (inOrg(repository) && found.every((t) => canonical(t) === canonical(repository)));
|
|
99
119
|
},
|
|
100
120
|
principalType: "user",
|
|
101
121
|
},
|
package/templates/engineering.md
CHANGED
|
@@ -3,12 +3,13 @@
|
|
|
3
3
|
- Question it again whenever two fixes on one idea fail.
|
|
4
4
|
- Why: a correct fix for the wrong problem costs a full build and review, then a second one.
|
|
5
5
|
- **Brief before building**
|
|
6
|
-
- The owner posts a brief, scaled to the change (three lines for a copy fix): the required behavior in the human's words, how it works today (file:line), every PR, repo or moving part it adds, and the real-path test.
|
|
6
|
+
- The owner posts a brief, scaled to the change (three lines for a copy fix). It leads with its impact for the human: the measured change (latency, CPU, cost, steps), or the named work it unblocks with that work's number. Then the required behavior in the human's words, how it works today (file:line), every PR, repo or moving part it adds, and the real-path test.
|
|
7
|
+
- A step or PR with no measured impact, schema cleanup that only tidies included, is offered to the human as optional, never built by default.
|
|
7
8
|
- Building waits for the human's yes, even while they're offline; meanwhile do the research, the repro and the draft. Picking an option that names what gets built counts as a yes.
|
|
8
9
|
- Build only what the brief names; within it, make the sensible call on details and say which you made.
|
|
9
10
|
- A new PR, repo or subsystem, or a dropped requirement, is a question to the human, never a build step or a review blocker.
|
|
10
11
|
- Small reversible setup (a webhook, a secret, a project setting) isn't building: do it, then say what you set.
|
|
11
|
-
- Why: the human's yes on scope is cheaper than their no on a finished PR.
|
|
12
|
+
- Why: the human's yes on scope is cheaper than their no on a finished PR, and a step that changes nothing they can measure still costs a build, a review and the code it leaves behind.
|
|
12
13
|
- **Build it right**
|
|
13
14
|
- Fix the cause at the module that owns the broken invariant, then grep for the same bug elsewhere. No guard, retry, catch or default that hides a failure.
|
|
14
15
|
- Subtract before you add: every new flag, layer, cache, retry or file names the requirement that forces it today. A replacement deletes the old mechanism.
|