@subseam/mcp 0.4.33 → 0.4.36
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/main.js +290 -31
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -14122,15 +14122,15 @@ async function runWalkGrep(pattern, root, signal) {
|
|
|
14122
14122
|
} catch (e) {
|
|
14123
14123
|
throw new ToolError(`grep: invalid regex: ${e instanceof Error ? e.message : String(e)}`);
|
|
14124
14124
|
}
|
|
14125
|
-
const
|
|
14125
|
+
const hits2 = [];
|
|
14126
14126
|
let budget = GREP_OUTPUT_LIMIT;
|
|
14127
14127
|
const push = (line) => {
|
|
14128
14128
|
budget -= line.length + 1;
|
|
14129
14129
|
if (budget < 0) {
|
|
14130
|
-
|
|
14130
|
+
hits2.push(`[output truncated at ${GREP_OUTPUT_LIMIT} bytes]`);
|
|
14131
14131
|
return false;
|
|
14132
14132
|
}
|
|
14133
|
-
|
|
14133
|
+
hits2.push(line);
|
|
14134
14134
|
return true;
|
|
14135
14135
|
};
|
|
14136
14136
|
const stat4 = await fs4.stat(root).catch(() => null);
|
|
@@ -14141,9 +14141,9 @@ async function runWalkGrep(pattern, root, signal) {
|
|
|
14141
14141
|
}
|
|
14142
14142
|
if (signal?.aborted)
|
|
14143
14143
|
throw new ToolError("grep: aborted");
|
|
14144
|
-
if (
|
|
14144
|
+
if (hits2.length === 0)
|
|
14145
14145
|
return "no matches";
|
|
14146
|
-
return
|
|
14146
|
+
return hits2.join("\n");
|
|
14147
14147
|
}
|
|
14148
14148
|
async function grepFile(file2, re, push) {
|
|
14149
14149
|
const stream = fssync2.createReadStream(file2, { encoding: "utf8" });
|
|
@@ -30133,21 +30133,21 @@ function mergeSources(textByRepo, concepts) {
|
|
|
30133
30133
|
else arr.push(c);
|
|
30134
30134
|
}
|
|
30135
30135
|
const used = /* @__PURE__ */ new Set();
|
|
30136
|
-
const
|
|
30136
|
+
const hits2 = [];
|
|
30137
30137
|
for (const [repo2, matches] of textByRepo) {
|
|
30138
30138
|
for (const m of matches) {
|
|
30139
30139
|
const covering = smallestCovering(byFile.get(`${repo2}${SEP}${m.path}`), m.line);
|
|
30140
30140
|
if (covering !== void 0) {
|
|
30141
30141
|
used.add(covering);
|
|
30142
|
-
|
|
30142
|
+
hits2.push({ repo: repo2, path: m.path, line: m.line, content: m.content, concept: covering, hitClass: "text+graph" });
|
|
30143
30143
|
} else {
|
|
30144
|
-
|
|
30144
|
+
hits2.push({ repo: repo2, path: m.path, line: m.line, content: m.content, hitClass: "text-only" });
|
|
30145
30145
|
}
|
|
30146
30146
|
}
|
|
30147
30147
|
}
|
|
30148
30148
|
for (const c of concepts) {
|
|
30149
30149
|
if (used.has(c)) continue;
|
|
30150
|
-
|
|
30150
|
+
hits2.push({
|
|
30151
30151
|
repo: c.repo,
|
|
30152
30152
|
path: c.location.path,
|
|
30153
30153
|
line: c.location.startLine,
|
|
@@ -30156,7 +30156,7 @@ function mergeSources(textByRepo, concepts) {
|
|
|
30156
30156
|
hitClass: "graph-only"
|
|
30157
30157
|
});
|
|
30158
30158
|
}
|
|
30159
|
-
return dedupe(
|
|
30159
|
+
return dedupe(hits2);
|
|
30160
30160
|
}
|
|
30161
30161
|
function smallestCovering(concepts, line) {
|
|
30162
30162
|
if (concepts === void 0) return void 0;
|
|
@@ -30170,9 +30170,9 @@ function smallestCovering(concepts, line) {
|
|
|
30170
30170
|
function span(c) {
|
|
30171
30171
|
return c.location.endLine - c.location.startLine;
|
|
30172
30172
|
}
|
|
30173
|
-
function dedupe(
|
|
30173
|
+
function dedupe(hits2) {
|
|
30174
30174
|
const byLoc = /* @__PURE__ */ new Map();
|
|
30175
|
-
for (const h of
|
|
30175
|
+
for (const h of hits2) {
|
|
30176
30176
|
const key = `${h.repo}${SEP}${h.path}${SEP}${h.line}`;
|
|
30177
30177
|
const existing = byLoc.get(key);
|
|
30178
30178
|
if (existing === void 0 || existing.concept === void 0 && h.concept !== void 0) {
|
|
@@ -30184,8 +30184,8 @@ function dedupe(hits) {
|
|
|
30184
30184
|
|
|
30185
30185
|
// ../explore-tool/src/rank.ts
|
|
30186
30186
|
init_esm_shims();
|
|
30187
|
-
function rankHits(
|
|
30188
|
-
return [...
|
|
30187
|
+
function rankHits(hits2) {
|
|
30188
|
+
return [...hits2].sort(compare);
|
|
30189
30189
|
}
|
|
30190
30190
|
function compare(a, b) {
|
|
30191
30191
|
const ga = a.concept;
|
|
@@ -30221,8 +30221,8 @@ function historySummary(c) {
|
|
|
30221
30221
|
}
|
|
30222
30222
|
|
|
30223
30223
|
// ../explore-tool/src/project.ts
|
|
30224
|
-
function projectHits(
|
|
30225
|
-
return
|
|
30224
|
+
function projectHits(hits2, stamps) {
|
|
30225
|
+
return hits2.map((h) => projectOne(h, stamps.get(h.repo)));
|
|
30226
30226
|
}
|
|
30227
30227
|
function projectOne(h, stamp) {
|
|
30228
30228
|
const diverged = h.concept !== void 0 && (stamp?.modified.has(h.path) ?? false);
|
|
@@ -30340,8 +30340,8 @@ function conceptLine(hit) {
|
|
|
30340
30340
|
else if (c.verdict !== null) parts.push(c.verdict);
|
|
30341
30341
|
return ` \u21B3 ${parts.join(" \xB7 ")}`;
|
|
30342
30342
|
}
|
|
30343
|
-
function stampOf(
|
|
30344
|
-
return
|
|
30343
|
+
function stampOf(hits2) {
|
|
30344
|
+
return hits2[0]?.stamp ?? "unknown";
|
|
30345
30345
|
}
|
|
30346
30346
|
function dirOf(path7) {
|
|
30347
30347
|
const d = dirname13(path7);
|
|
@@ -30597,11 +30597,26 @@ var definitionDraft = external_exports.object({
|
|
|
30597
30597
|
rung: external_exports.object({ disposition: external_exports.enum(["block", "warn", "off"]), means: external_exports.string() }).optional(),
|
|
30598
30598
|
conflicts: external_exports.literal("not checked")
|
|
30599
30599
|
});
|
|
30600
|
-
|
|
30601
|
-
|
|
30600
|
+
var draftAt = external_exports.discriminatedUnion("state", [
|
|
30601
|
+
external_exports.object({ state: external_exports.literal("current"), sha: external_exports.string(), ordinal: external_exports.number() }),
|
|
30602
|
+
external_exports.object({
|
|
30603
|
+
state: external_exports.literal("computing"),
|
|
30604
|
+
tipSha: external_exports.string(),
|
|
30605
|
+
tipOrdinal: external_exports.number(),
|
|
30606
|
+
banked: external_exports.object({ sha: external_exports.string(), ordinal: external_exports.number() }).nullable()
|
|
30607
|
+
})
|
|
30608
|
+
]);
|
|
30609
|
+
var sha8 = (sha) => sha.slice(0, 8);
|
|
30610
|
+
function draftAtLine(at) {
|
|
30611
|
+
if (at.state === "current") return `verdict at ${sha8(at.sha)} (the tip)`;
|
|
30612
|
+
return at.banked === null ? `computing at ${sha8(at.tipSha)}, no verdict banked yet` : `verdict at ${sha8(at.banked.sha)} (tip is ${sha8(at.tipSha)}, computing)`;
|
|
30613
|
+
}
|
|
30614
|
+
function notComputedLines(uncomputed, atTip) {
|
|
30615
|
+
const at = atTip ? "at tip" : "at that commit";
|
|
30616
|
+
if (uncomputed.length <= 5) return uncomputed.map((u) => ` ${at}, not computed: ${u.path} (${u.reason})`);
|
|
30602
30617
|
const byCause = /* @__PURE__ */ new Map();
|
|
30603
30618
|
for (const u of uncomputed) byCause.set(u.reason, [...byCause.get(u.reason) ?? [], u.path]);
|
|
30604
|
-
return [...byCause].map(([reason, paths]) => ` at
|
|
30619
|
+
return [...byCause].map(([reason, paths]) => ` ${at}, not computed: ${paths.length} file${paths.length === 1 ? "" : "s"} (${reason}), e.g. ${paths.slice(0, 3).join(", ")}`);
|
|
30605
30620
|
}
|
|
30606
30621
|
var FAILURES_SHOWN = 20;
|
|
30607
30622
|
var EXAMPLES_FAILING_SHOWN = 3;
|
|
@@ -30614,7 +30629,7 @@ function exampleLines(examples) {
|
|
|
30614
30629
|
...examples.wouldFail === null ? [] : [` would fail: ${where(examples.wouldFail)} ${examples.wouldFail.does} (no code does this yet)`]
|
|
30615
30630
|
];
|
|
30616
30631
|
}
|
|
30617
|
-
function renderDraft(d) {
|
|
30632
|
+
function renderDraft(d, atTip = true) {
|
|
30618
30633
|
const at = (c) => `${c.sha.slice(0, 9)} (${c.committedAt.slice(0, 10)})`;
|
|
30619
30634
|
const h = d.history;
|
|
30620
30635
|
const since = h === null || h.since === null ? "" : ` since ${at(h.since)}`;
|
|
@@ -30625,10 +30640,10 @@ function renderDraft(d) {
|
|
|
30625
30640
|
const shown = d.atTip.failures.slice(0, FAILURES_SHOWN).map((f) => `${f.path}:${f.line} ${f.cause}`);
|
|
30626
30641
|
const more = d.atTip.failures.length - shown.length;
|
|
30627
30642
|
const notEvaluated = d.atTip.notEvaluated ?? null;
|
|
30628
|
-
const tipAt = ` at tip ${d.atTip.sha.slice(0, 9)}`;
|
|
30643
|
+
const tipAt = ` at ${atTip ? "tip " : ""}${d.atTip.sha.slice(0, 9)}`;
|
|
30629
30644
|
const tip = d.atTip.failures.length > 0 ? `${tipAt}: ${d.atTip.failures.length} failing: ` + shown.join("; ") + (more > 0 ? `; \u2026 and ${more} more` : "") : notEvaluated !== null ? `${tipAt}: not evaluated (${notEvaluated})` : `${tipAt}: holds`;
|
|
30630
30645
|
const tipRest = d.atTip.failures.length > 0 && notEvaluated !== null ? [`${tipAt}, the rest was not evaluated (${notEvaluated})`] : [];
|
|
30631
|
-
const open7 = notComputedLines(d.atTip.uncomputed);
|
|
30646
|
+
const open7 = notComputedLines(d.atTip.uncomputed, atTip);
|
|
30632
30647
|
const rung = d.rung === void 0 ? [] : [` on approval, in force at ${d.rung.means}`];
|
|
30633
30648
|
if (typeof d.gated === "string") return [` ${d.statement}`, ` gated: ${d.gated} This definition is not evaluated.`, ...rung, ` conflicts: ${d.conflicts}`].join("\n");
|
|
30634
30649
|
return [` ${d.statement}`, ...exampleLines(d.examples), ` history: ${history}`, ...floor, tip, ...tipRest, ...open7, ...rung, ` conflicts: ${d.conflicts}`].join("\n");
|
|
@@ -30989,6 +31004,236 @@ function renderSummary(s) {
|
|
|
30989
31004
|
|
|
30990
31005
|
// ../define/src/tool/show.ts
|
|
30991
31006
|
init_esm_shims();
|
|
31007
|
+
|
|
31008
|
+
// ../define/src/library/entries.ts
|
|
31009
|
+
init_esm_shims();
|
|
31010
|
+
|
|
31011
|
+
// ../define/src/library/entries/one-integration-point.ts
|
|
31012
|
+
init_esm_shims();
|
|
31013
|
+
var oneIntegrationPoint = {
|
|
31014
|
+
id: "one-integration-point",
|
|
31015
|
+
practice: "One integration point for each external system",
|
|
31016
|
+
otherNames: [
|
|
31017
|
+
"gateway",
|
|
31018
|
+
"adapter",
|
|
31019
|
+
"ports and adapters",
|
|
31020
|
+
"hexagonal architecture",
|
|
31021
|
+
"API client wrapper",
|
|
31022
|
+
"external API",
|
|
31023
|
+
"third-party API",
|
|
31024
|
+
"repository pattern",
|
|
31025
|
+
"data access layer",
|
|
31026
|
+
"separation of concerns"
|
|
31027
|
+
],
|
|
31028
|
+
quality: { characteristic: "Maintainability", subcharacteristic: "Modularity" },
|
|
31029
|
+
sources: [
|
|
31030
|
+
{ title: 'Martin Fowler, "Gateway" (2021)', url: "https://martinfowler.com/articles/gateway-pattern.html" }
|
|
31031
|
+
],
|
|
31032
|
+
wisdom: "Code that talks to an external system (a database, a payment provider, GitHub) does it through one object that encapsulates that access, so the rest of the code depends on your interface, not on the foreign one. When the external system changes, fails or is replaced, there is one place to change, one place that knows its errors, and one place to fake in tests.",
|
|
31033
|
+
split: "Three claims, because the practice makes three separate promises and each can break on its own. (1) The boundary: code that handles requests never calls the external library directly; it binds to the external library's API on one side and to the integration point's classes on the other. (2) The shape inside the boundary: each external resource (on RealWorld, each stored entity) has exactly one dedicated handler, so two handlers never drift apart on the same resource; it binds to the resource types and the handler classes. (3) The failure contract: when the external system answers with nothing or with an error, the request answers with an explicit status code instead of an unhandled error; it binds to the external API's calls that can fail. The cut falls at the promises, never at a folder: a claim about which folder may call the library breaks the day the code moves, and says nothing about the other two promises. On RealWorld the external system is the database, reached through its ORM library.",
|
|
31034
|
+
claims: [
|
|
31035
|
+
{
|
|
31036
|
+
sentence: "Controllers, services and middleware never call the database library directly; only repositories do.",
|
|
31037
|
+
concept: "the database library's API, and the repository classes",
|
|
31038
|
+
intended: {
|
|
31039
|
+
bindsTo: ["the MikroORM EntityManager and EntityRepository APIs", "classes that extend EntityRepository"],
|
|
31040
|
+
mustFail: ["ArticleService", "ProfileService", "UserService", "TagService", "AuthMiddleware"],
|
|
31041
|
+
mustPass: ["ArticleController", "UserController", "ProfileController", "TagController", "UserRepository"]
|
|
31042
|
+
}
|
|
31043
|
+
},
|
|
31044
|
+
{
|
|
31045
|
+
sentence: "Each stored entity has exactly one dedicated repository.",
|
|
31046
|
+
concept: "the stored entity classes, and the repository classes",
|
|
31047
|
+
intended: {
|
|
31048
|
+
bindsTo: ["classes decorated as MikroORM entities", "classes that extend EntityRepository"],
|
|
31049
|
+
mustFail: ["Article", "Comment", "Tag"],
|
|
31050
|
+
mustPass: ["User"]
|
|
31051
|
+
}
|
|
31052
|
+
},
|
|
31053
|
+
{
|
|
31054
|
+
sentence: "Every database lookup that fails when it finds nothing states the status code the request answers with.",
|
|
31055
|
+
concept: "the database library's find-or-fail lookups",
|
|
31056
|
+
intended: {
|
|
31057
|
+
bindsTo: ["calls to findOneOrFail"],
|
|
31058
|
+
mustFail: [
|
|
31059
|
+
"ArticleService.findAll",
|
|
31060
|
+
"ArticleService.findOne",
|
|
31061
|
+
"ArticleService.addComment",
|
|
31062
|
+
"ArticleService.deleteComment",
|
|
31063
|
+
"ArticleService.favorite",
|
|
31064
|
+
"ArticleService.unFavorite",
|
|
31065
|
+
"ArticleService.findComments",
|
|
31066
|
+
"ArticleService.update",
|
|
31067
|
+
"ProfileService.findOne",
|
|
31068
|
+
"ProfileService.findProfile",
|
|
31069
|
+
"ProfileService.follow",
|
|
31070
|
+
"ProfileService.unFollow",
|
|
31071
|
+
"UserService.update",
|
|
31072
|
+
"UserService.findByEmail"
|
|
31073
|
+
],
|
|
31074
|
+
mustPass: ["AuthMiddleware.use"]
|
|
31075
|
+
}
|
|
31076
|
+
}
|
|
31077
|
+
]
|
|
31078
|
+
};
|
|
31079
|
+
|
|
31080
|
+
// ../define/src/library/entries/least-privilege.ts
|
|
31081
|
+
init_esm_shims();
|
|
31082
|
+
var leastPrivilege = {
|
|
31083
|
+
id: "least-privilege",
|
|
31084
|
+
practice: "Least privilege: every change is made only by someone allowed to make it",
|
|
31085
|
+
otherNames: [
|
|
31086
|
+
"principle of least privilege",
|
|
31087
|
+
"access control",
|
|
31088
|
+
"authorization",
|
|
31089
|
+
"deny by default",
|
|
31090
|
+
"broken access control",
|
|
31091
|
+
"insecure direct object reference",
|
|
31092
|
+
"IDOR",
|
|
31093
|
+
"broken object level authorization",
|
|
31094
|
+
"BOLA",
|
|
31095
|
+
"ownership check",
|
|
31096
|
+
"authentication required"
|
|
31097
|
+
],
|
|
31098
|
+
quality: { characteristic: "Security", subcharacteristic: "Integrity" },
|
|
31099
|
+
sources: [
|
|
31100
|
+
{
|
|
31101
|
+
title: 'Saltzer and Schroeder, "The Protection of Information in Computer Systems" (1975), design principle (f): least privilege',
|
|
31102
|
+
url: "https://web.mit.edu/Saltzer/www/publications/protection/Basic.html"
|
|
31103
|
+
},
|
|
31104
|
+
{
|
|
31105
|
+
title: "OWASP ASVS 5.0, V8 Authorization: 8.2.1 function-level and 8.2.2 data-specific access",
|
|
31106
|
+
url: "https://github.com/OWASP/ASVS/blob/master/5.0/en/0x17-V8-Authorization.md"
|
|
31107
|
+
}
|
|
31108
|
+
],
|
|
31109
|
+
wisdom: "Every program and every user operates with the least set of privileges necessary for the job. In a web service that means two checks: an operation is reachable only by a caller allowed to use that operation at all (function level), and it acts only on records that caller is allowed to touch (data level). Missing the second is the classic insecure direct object reference: any signed-in user can change anyone's record by changing an id in the request.",
|
|
31110
|
+
split: `One claim per level, and one per kind of owned record, because each is enforced in a different place and each can be missing while the others hold. (1) Function level: every request that changes stored data requires a signed-in user, with signing up as the one named exception. It binds to the request handlers that write, and to the step that establishes the signed-in user. (2) and (3) Data level, per owned record: on RealWorld, articles and comments each have an author, so each gets its own claim that only its author may change or delete it. They bind to the operations that change that record and to the record's author. The cut falls at the record type, not at the route: one claim per route would miss the next route that changes the same record, and one claim for "all records" would hide which record lost its check.`,
|
|
31111
|
+
claims: [
|
|
31112
|
+
{
|
|
31113
|
+
sentence: "Every request that changes stored data requires a signed-in user, except signing up.",
|
|
31114
|
+
concept: "the request handlers that change stored data, and the sign-in check",
|
|
31115
|
+
intended: {
|
|
31116
|
+
bindsTo: ["controller handlers whose calls reach a database write", "AuthMiddleware"],
|
|
31117
|
+
mustFail: ["UserController.delete"],
|
|
31118
|
+
mustPass: [
|
|
31119
|
+
"ArticleController.create",
|
|
31120
|
+
"ArticleController.update",
|
|
31121
|
+
"ArticleController.delete",
|
|
31122
|
+
"ArticleController.createComment",
|
|
31123
|
+
"ArticleController.deleteComment",
|
|
31124
|
+
"ArticleController.favorite",
|
|
31125
|
+
"ArticleController.unFavorite",
|
|
31126
|
+
"UserController.update",
|
|
31127
|
+
"ProfileController.follow",
|
|
31128
|
+
"ProfileController.unFollow",
|
|
31129
|
+
"UserController.create"
|
|
31130
|
+
]
|
|
31131
|
+
}
|
|
31132
|
+
},
|
|
31133
|
+
{
|
|
31134
|
+
sentence: "Only an article's author may change or delete that article.",
|
|
31135
|
+
concept: "the operations that change an article, and the article's author",
|
|
31136
|
+
intended: {
|
|
31137
|
+
bindsTo: ["ArticleService.update", "ArticleService.delete", "Article.author"],
|
|
31138
|
+
mustFail: ["ArticleService.update", "ArticleService.delete"],
|
|
31139
|
+
mustPass: [],
|
|
31140
|
+
planted: [{ branch: "planted/article-author-check", mustPass: ["ArticleService.update", "ArticleService.delete"] }]
|
|
31141
|
+
}
|
|
31142
|
+
},
|
|
31143
|
+
{
|
|
31144
|
+
sentence: "Only a comment's author may delete that comment.",
|
|
31145
|
+
concept: "the operation that deletes a comment, and the comment's author",
|
|
31146
|
+
intended: {
|
|
31147
|
+
bindsTo: ["ArticleService.deleteComment", "Comment.author"],
|
|
31148
|
+
mustFail: ["ArticleService.deleteComment"],
|
|
31149
|
+
mustPass: [],
|
|
31150
|
+
planted: [{ branch: "planted/comment-author-check", mustPass: ["ArticleService.deleteComment"] }]
|
|
31151
|
+
}
|
|
31152
|
+
}
|
|
31153
|
+
]
|
|
31154
|
+
};
|
|
31155
|
+
|
|
31156
|
+
// ../define/src/library/entries.ts
|
|
31157
|
+
var PRACTICE_ENTRIES = [oneIntegrationPoint, leastPrivilege];
|
|
31158
|
+
|
|
31159
|
+
// ../define/src/library/search.ts
|
|
31160
|
+
init_esm_shims();
|
|
31161
|
+
var IGNORED = /* @__PURE__ */ new Set(["how", "the", "and", "for", "one", "can", "what", "does", "define", "definition", "definitions", "write", "should", "with", "that", "this", "our", "your", "code"]);
|
|
31162
|
+
function words(text) {
|
|
31163
|
+
return text.toLowerCase().split(/[^a-z0-9]+/).filter((w) => w.length >= 3 && !IGNORED.has(w));
|
|
31164
|
+
}
|
|
31165
|
+
function hits(queryWords, text) {
|
|
31166
|
+
const own = words(text);
|
|
31167
|
+
return queryWords.filter((q) => own.some((w) => w.startsWith(q))).length;
|
|
31168
|
+
}
|
|
31169
|
+
function searchPractices(entries, query) {
|
|
31170
|
+
const q = [...new Set(words(query))];
|
|
31171
|
+
const scored = entries.map((entry) => ({
|
|
31172
|
+
entry,
|
|
31173
|
+
score: 3 * hits(q, [entry.practice, ...entry.otherNames].join(" ")) + 2 * hits(q, `${entry.quality.characteristic} ${entry.quality.subcharacteristic}`) + hits(q, [entry.wisdom, entry.split, ...entry.claims.map((c) => c.sentence)].join(" "))
|
|
31174
|
+
}));
|
|
31175
|
+
const best = Math.max(0, ...scored.map((s) => s.score));
|
|
31176
|
+
return scored.filter((s) => s.score > 0 && 2 * s.score >= best).sort((a, b) => b.score - a.score).map((s) => s.entry);
|
|
31177
|
+
}
|
|
31178
|
+
|
|
31179
|
+
// ../define/src/library/render.ts
|
|
31180
|
+
init_esm_shims();
|
|
31181
|
+
|
|
31182
|
+
// ../define/src/library/entry.ts
|
|
31183
|
+
init_esm_shims();
|
|
31184
|
+
var EXAMPLE_PROJECT = {
|
|
31185
|
+
name: "RealWorld",
|
|
31186
|
+
spec: "https://github.com/gothinkster/realworld",
|
|
31187
|
+
repo: "mikro-orm/nestjs-realworld-example-app",
|
|
31188
|
+
commit: "e723ffb798f7c7c6cad0037b0ca25d05b93db8ef"
|
|
31189
|
+
};
|
|
31190
|
+
var QUALITY_MODEL_SOURCE = {
|
|
31191
|
+
title: "ISO/IEC 25010:2023 product quality model, as listed by the arc42 quality model",
|
|
31192
|
+
url: "https://quality.arc42.org/standards/iso-25010"
|
|
31193
|
+
};
|
|
31194
|
+
|
|
31195
|
+
// ../define/src/library/render.ts
|
|
31196
|
+
function recordLine(claim) {
|
|
31197
|
+
const r = claim.record;
|
|
31198
|
+
if (r === void 0) return "not yet run through the product";
|
|
31199
|
+
if (r.kind === "failing") return `the product cannot admit or evaluate it yet (${r.issue})`;
|
|
31200
|
+
return `admitted as ${r.definitionId} v${r.version}, ${r.rung}`;
|
|
31201
|
+
}
|
|
31202
|
+
function renderPractice(entry) {
|
|
31203
|
+
const out2 = [
|
|
31204
|
+
`## ${entry.practice}`,
|
|
31205
|
+
`Also known as: ${entry.otherNames.join(", ")}.`,
|
|
31206
|
+
`Quality (ISO/IEC 25010:2023): ${entry.quality.characteristic} / ${entry.quality.subcharacteristic}.`,
|
|
31207
|
+
"",
|
|
31208
|
+
entry.wisdom,
|
|
31209
|
+
"",
|
|
31210
|
+
`How to split it into definitions, shown on ${EXAMPLE_PROJECT.name} (${EXAMPLE_PROJECT.repo} at ${EXAMPLE_PROJECT.commit.slice(0, 8)}):`,
|
|
31211
|
+
entry.split,
|
|
31212
|
+
"",
|
|
31213
|
+
"Enter each sentence on its own (`define` with `nlIntent`), rewritten for your own code's concepts:"
|
|
31214
|
+
];
|
|
31215
|
+
entry.claims.forEach((claim, i) => {
|
|
31216
|
+
out2.push(`${i + 1}. "${claim.sentence}"`);
|
|
31217
|
+
out2.push(` binds to: ${claim.concept}. On ${EXAMPLE_PROJECT.name}: ${recordLine(claim)}.`);
|
|
31218
|
+
});
|
|
31219
|
+
out2.push("", "Sources:");
|
|
31220
|
+
for (const s of [...entry.sources, QUALITY_MODEL_SOURCE]) out2.push(`- ${s.title}: ${s.url}`);
|
|
31221
|
+
return out2.join("\n");
|
|
31222
|
+
}
|
|
31223
|
+
function renderPracticeSearch(query, matches, all) {
|
|
31224
|
+
if (matches.length === 0) {
|
|
31225
|
+
return [
|
|
31226
|
+
`show: no practice entry matches "${query}". The entries are:`,
|
|
31227
|
+
...all.map((e) => `- ${e.practice} (search: ${e.otherNames.slice(0, 3).join(", ")})`)
|
|
31228
|
+
].join("\n");
|
|
31229
|
+
}
|
|
31230
|
+
return [
|
|
31231
|
+
`show: ${matches.length} practice entr${matches.length === 1 ? "y" : "ies"} for "${query}". Each states a practice as definitions on concepts (classes, methods, routes), never on files or folders, so they follow the code when it moves.`,
|
|
31232
|
+
...matches.map(renderPractice)
|
|
31233
|
+
].join("\n\n");
|
|
31234
|
+
}
|
|
31235
|
+
|
|
31236
|
+
// ../define/src/tool/show.ts
|
|
30992
31237
|
var input3 = external_exports.object({
|
|
30993
31238
|
definitionId: external_exports.string().uuid().optional(),
|
|
30994
31239
|
repo: external_exports.string().min(1).optional(),
|
|
@@ -30999,7 +31244,10 @@ var input3 = external_exports.object({
|
|
|
30999
31244
|
// (`locationPrefix`). Dashboard-mode filters; meaningless beside `definitionId`.
|
|
31000
31245
|
versionStatus: external_exports.enum(["defaulted", "ratified", "corrected"]).optional(),
|
|
31001
31246
|
provenance: external_exports.enum(["authored", "mined", "witness-derived"]).optional(),
|
|
31002
|
-
locationPrefix: external_exports.string().min(1).optional()
|
|
31247
|
+
locationPrefix: external_exports.string().min(1).optional(),
|
|
31248
|
+
// The practice library (direction/define/language.md §9.6): a search over product content, never
|
|
31249
|
+
// over this tenant's definitions, so it is an arm of its own and takes no other field beside it.
|
|
31250
|
+
practice: external_exports.string().min(1).optional()
|
|
31003
31251
|
});
|
|
31004
31252
|
var statusBody = external_exports.object({
|
|
31005
31253
|
definitions: external_exports.array(external_exports.object({
|
|
@@ -31082,24 +31330,33 @@ var showBody = external_exports.discriminatedUnion("ok", [
|
|
|
31082
31330
|
bindings: external_exports.array(external_exports.object({ role: external_exports.string(), repo: external_exports.string(), anchorGrain: external_exports.string(), boundAtCommit: external_exports.string() })),
|
|
31083
31331
|
violations: external_exports.array(showViolation),
|
|
31084
31332
|
liveSuppressions: external_exports.array(showSuppression),
|
|
31085
|
-
draft: definitionDraft.nullable()
|
|
31333
|
+
draft: definitionDraft.nullable(),
|
|
31334
|
+
/** Absent from older servers. */
|
|
31335
|
+
draftAt: draftAt.nullable().optional()
|
|
31086
31336
|
}),
|
|
31087
31337
|
external_exports.object({ ok: external_exports.literal(false) })
|
|
31088
31338
|
]);
|
|
31089
31339
|
var showTool = {
|
|
31090
31340
|
name: "show",
|
|
31091
|
-
description:
|
|
31341
|
+
description: 'Show this tenant\'s definitions. With `definitionId`: ONE definition as a coherent object \u2014 every version with its status and provenance, the approval stamp, subject bindings, standing violations, live suppressions, and banked witnesses. Without: the corpus dashboard (admitted definitions, the open drift backlog, corpus size + evaluation staleness), optionally filtered by `repo`, epistemic `status`, `versionStatus` (use `defaulted` to see the un-affirmed definitions), `provenance`, or `locationPrefix` (e.g. `app/src/billing/`). With `practice` (words, e.g. "one integration point for an external API" or "least privilege"): the practice library \u2014 how to state a coding best practice as definitions on your code\'s concepts, with the plain sentences to enter through `define`.',
|
|
31092
31342
|
capability: "define",
|
|
31093
31343
|
inputSchema: input3.shape,
|
|
31094
31344
|
async handler(raw, ctx) {
|
|
31095
31345
|
const args2 = input3.parse(raw);
|
|
31346
|
+
if (args2.practice !== void 0) {
|
|
31347
|
+
const { practice, ...rest } = args2;
|
|
31348
|
+
if (Object.values(rest).some((v) => v !== void 0)) {
|
|
31349
|
+
return { text: "show: `practice` searches the practice library and takes no other field beside it \u2014 search the library, or read this tenant's definitions, not both." };
|
|
31350
|
+
}
|
|
31351
|
+
return { text: renderPracticeSearch(practice, searchPractices(PRACTICE_ENTRIES, practice), PRACTICE_ENTRIES) };
|
|
31352
|
+
}
|
|
31096
31353
|
if (args2.definitionId !== void 0) {
|
|
31097
31354
|
const raw2 = await ctx.gateway.invoke("define-show", { definitionId: args2.definitionId });
|
|
31098
31355
|
const object2 = readBody(showBody, raw2, "show", "define-show");
|
|
31099
31356
|
if (!object2.ok) return { text: object2.text };
|
|
31100
31357
|
return { text: renderObject(args2.definitionId, object2.value) };
|
|
31101
31358
|
}
|
|
31102
|
-
const { definitionId: _omit, ...filters } = args2;
|
|
31359
|
+
const { definitionId: _omit, practice: _practice, ...filters } = args2;
|
|
31103
31360
|
const result = await ctx.gateway.invoke("define-status", filters);
|
|
31104
31361
|
const status = readBody(statusBody, result, "show", "define-status");
|
|
31105
31362
|
if (!status.ok) return { text: status.text };
|
|
@@ -31129,8 +31386,10 @@ function renderObject(definitionId, r) {
|
|
|
31129
31386
|
out2.push("Bindings (current version):");
|
|
31130
31387
|
for (const [line, n] of counts) out2.push(` \u2022 ${line}${n > 1 ? ` (\xD7${n})` : ""}`);
|
|
31131
31388
|
}
|
|
31132
|
-
|
|
31133
|
-
${
|
|
31389
|
+
const at = r.draftAt ?? null;
|
|
31390
|
+
const atLine = at === null ? "" : ` ${draftAtLine(at)}`;
|
|
31391
|
+
out2.push(r.draft === null ? at === null ? "Draft (current version): none \u2014 the version has no subject binding, or canvas has published no version of its repo." : `Draft (current version): ${draftAtLine(at)}` : `Draft (current version):${atLine}
|
|
31392
|
+
${renderDraft(r.draft, at?.state !== "computing")}`);
|
|
31134
31393
|
if (r.violations.length === 0) {
|
|
31135
31394
|
out2.push("Standing violations: none on the ledger.");
|
|
31136
31395
|
} else {
|
|
@@ -48433,7 +48692,7 @@ var workReadTools = createWorkReadToolProviders({ capability: "work" });
|
|
|
48433
48692
|
var bundledProviders = [src_default2, src_default, tension_default, ...defineTools, ...decisionTools, ...captureTools, ...buildTools, secureTool, ...workTools, ...workReadTools];
|
|
48434
48693
|
|
|
48435
48694
|
// package.json
|
|
48436
|
-
var version2 = "0.4.
|
|
48695
|
+
var version2 = "0.4.36";
|
|
48437
48696
|
|
|
48438
48697
|
// src/server.ts
|
|
48439
48698
|
var SERVER_VERSION = version2;
|