@amistio/cli 0.1.21 → 0.1.23
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/README.md +1 -1
- package/dist/index.js +79 -4
- package/dist/index.js.map +3 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ npm install -g @amistio/cli
|
|
|
9
9
|
amistio --help
|
|
10
10
|
```
|
|
11
11
|
|
|
12
|
-
The package install only installs the `amistio` command. Repository cloning, project pairing, credential storage, sync watching, and runner execution happen only when the user explicitly runs commands such as `amistio bootstrap`, `amistio import`, `amistio pair`, `amistio sync watch`, or `amistio run --watch`. When the app copies a personal project into an organization, the CLI command syntax stays the same; create the org-scoped code and run `amistio import <code>` from the intended local checkout.
|
|
12
|
+
The package install only installs the `amistio` command. Repository cloning, project pairing, credential storage, sync watching, and runner execution happen only when the user explicitly runs commands such as `amistio bootstrap`, `amistio import`, `amistio pair`, `amistio sync watch`, or `amistio run --watch`. When the app copies a personal project into an organization, the CLI command syntax stays the same; create the org-scoped code and run `amistio import <code>` from the intended local checkout. Import scans repo-local project-brain docs plus recognized repo-local IDE, harness, and local AI tool memory or instruction files such as `AGENTS.md`, `.github/copilot-instructions.md`, `.cursor/rules/*.mdc`, `.windsurfrules`, and `memories/*.md`; durable Amistio memory belongs in `docs/memory/`, and global plugin or harness memory outside the repository is not scanned by default.
|
|
13
13
|
|
|
14
14
|
Runner lifecycle controls in the web app, such as update, restart, and remove, apply only to the runner paired by that user unless the active organization role is an admin role. The runner API binds command polling, command status, logs, activity, and tool sessions to the local runner credential that produced them.
|
|
15
15
|
|
package/dist/index.js
CHANGED
|
@@ -4570,6 +4570,14 @@ var projectContextTopLevelWarningMaxLength = 600;
|
|
|
4570
4570
|
var validProjectContextSliceKinds = /* @__PURE__ */ new Set(["overview", "architecture", "domain", "data", "api", "frontend", "backend", "cli", "workflow", "operations", "security", "testing", "unknown"]);
|
|
4571
4571
|
var validProjectContextEntityTypes = /* @__PURE__ */ new Set(["project", "system", "component", "domain", "tool", "decision", "feature", "risk", "team", "workflow", "unknown"]);
|
|
4572
4572
|
var validProjectContextRelationTypes = /* @__PURE__ */ new Set(["uses", "depends_on", "decides", "supersedes", "touches", "blocks", "implements", "mentions"]);
|
|
4573
|
+
var canonicalProjectContextCitationSources = /* @__PURE__ */ new Map([
|
|
4574
|
+
["projectbrain", "projectBrain"],
|
|
4575
|
+
["approvedbrain", "projectBrain"],
|
|
4576
|
+
["approvedprojectbrain", "projectBrain"],
|
|
4577
|
+
["localsource", "localSource"],
|
|
4578
|
+
["runnerstate", "runnerState"],
|
|
4579
|
+
["mixed", "mixed"]
|
|
4580
|
+
]);
|
|
4573
4581
|
function createImplementationVerificationPrompt(workItem) {
|
|
4574
4582
|
return [
|
|
4575
4583
|
"# Amistio Implementation Verification",
|
|
@@ -4727,6 +4735,7 @@ function createProjectContextRefreshPrompt(workItem, context) {
|
|
|
4727
4735
|
"- Use only these exact singular slice kind values: overview, architecture, domain, data, api, frontend, backend, cli, workflow, operations, security, testing, unknown.",
|
|
4728
4736
|
"- Capture entities and relations that explain how the app is put together and where future work should look first.",
|
|
4729
4737
|
"- Prefer summaries, repository-relative paths, short citations, tags, and freshness status over raw source excerpts.",
|
|
4738
|
+
"- Use only these exact citation source values: projectBrain, localSource, runnerState, mixed. Approved project-brain records use projectBrain, not approvedBrain.",
|
|
4730
4739
|
"- Mark stale or missing areas explicitly instead of guessing.",
|
|
4731
4740
|
"- Keep coverage.missingAreas entries concise noun phrases under 160 characters.",
|
|
4732
4741
|
"- Keep coverage.warnings and verificationPlan entries under 300 characters; keep top-level warnings under 600 characters.",
|
|
@@ -5400,6 +5409,7 @@ function normalizeProjectContextCitationPaths(value, options) {
|
|
|
5400
5409
|
return citation;
|
|
5401
5410
|
}
|
|
5402
5411
|
const normalizedCitation = { ...citation };
|
|
5412
|
+
normalizedCitation.source = normalizeProjectContextCitationSource(normalizedCitation.source);
|
|
5403
5413
|
if (typeof normalizedCitation.repoPath === "string") {
|
|
5404
5414
|
normalizedCitation.repoPath = normalizeProjectContextRepoPath(normalizedCitation.repoPath, options);
|
|
5405
5415
|
}
|
|
@@ -5408,6 +5418,13 @@ function normalizeProjectContextCitationPaths(value, options) {
|
|
|
5408
5418
|
}
|
|
5409
5419
|
return normalized;
|
|
5410
5420
|
}
|
|
5421
|
+
function normalizeProjectContextCitationSource(value) {
|
|
5422
|
+
if (typeof value !== "string") {
|
|
5423
|
+
return value;
|
|
5424
|
+
}
|
|
5425
|
+
const sourceKey = value.trim().replace(/[\s_-]+/g, "").toLowerCase();
|
|
5426
|
+
return canonicalProjectContextCitationSources.get(sourceKey) ?? value;
|
|
5427
|
+
}
|
|
5411
5428
|
function normalizeProjectContextRepoPath(value, options) {
|
|
5412
5429
|
const trimmed = value.trim();
|
|
5413
5430
|
if (!trimmed || /^[A-Za-z][A-Za-z0-9+.-]*:\/\//.test(trimmed) || /^file:/i.test(trimmed) || /^[A-Za-z]:($|[^\\/])/.test(trimmed)) {
|
|
@@ -5635,6 +5652,8 @@ var controlPlaneRoots2 = ["architecture", "context", "decisions", "features", "m
|
|
|
5635
5652
|
var excludedDirectoryNames = /* @__PURE__ */ new Set([".git", "node_modules", ".pnpm-store", ".next", "dist", "build", "coverage", ".cache", "cache", "tmp", "temp", "vendor"]);
|
|
5636
5653
|
var excludedFileNames = /* @__PURE__ */ new Set(["docs/context/amistio-project.md", "context/amistio-project.md"]);
|
|
5637
5654
|
var generatedPathSegments = /* @__PURE__ */ new Set(["generated", "__generated__", "vendor", "vendors"]);
|
|
5655
|
+
var rootAgentGuidanceFiles = /* @__PURE__ */ new Set(["agents.md", "claude.md", "gemini.md", "codex.md"]);
|
|
5656
|
+
var extensionlessInstructionFiles = /* @__PURE__ */ new Set([".cursorrules", ".windsurfrules", ".clinerules"]);
|
|
5638
5657
|
var documentFolderByType = {
|
|
5639
5658
|
architecture: "docs/architecture",
|
|
5640
5659
|
context: "docs/context",
|
|
@@ -5674,7 +5693,7 @@ async function scanLegacyDocuments(options) {
|
|
|
5674
5693
|
skipped.push({ repoPath, reason: "excluded" });
|
|
5675
5694
|
continue;
|
|
5676
5695
|
}
|
|
5677
|
-
const contentFormat =
|
|
5696
|
+
const contentFormat = importableContentFormatFromRepoPath(repoPath);
|
|
5678
5697
|
if (!contentFormat) {
|
|
5679
5698
|
skipped.push({ repoPath, reason: "notMarkdown" });
|
|
5680
5699
|
continue;
|
|
@@ -5826,6 +5845,8 @@ function isAmistioManagedDocument(content) {
|
|
|
5826
5845
|
return /^\s*<!--[\s\S]*?amistioDocumentId\s*:/i.test(content);
|
|
5827
5846
|
}
|
|
5828
5847
|
function classifyLegacyDocument(repoPath, content) {
|
|
5848
|
+
const localMemoryDocumentType = classifyLocalMemoryDocument(repoPath, content);
|
|
5849
|
+
if (localMemoryDocumentType) return localMemoryDocumentType;
|
|
5829
5850
|
const haystack = `${repoPath} ${inferTitle2(content, repoPath)}`.toLowerCase();
|
|
5830
5851
|
if (/\b(prompt|prompts|instruction|instructions|copilot|agent|skill)\b/.test(haystack)) return "prompt";
|
|
5831
5852
|
if (/\b(adr|decision|decisions|rfc)\b/.test(haystack)) return "decision";
|
|
@@ -5837,10 +5858,10 @@ function classifyLegacyDocument(repoPath, content) {
|
|
|
5837
5858
|
return "context";
|
|
5838
5859
|
}
|
|
5839
5860
|
function canonicalImportPath(sourcePath, documentType, contentFormat) {
|
|
5840
|
-
if (isCanonicalControlPlanePath(sourcePath)) {
|
|
5861
|
+
if (isCanonicalControlPlanePath(sourcePath) && inferContentFormatFromRepoPath(sourcePath)) {
|
|
5841
5862
|
return sourcePath;
|
|
5842
5863
|
}
|
|
5843
|
-
if (isLegacyControlPlanePath(sourcePath)) {
|
|
5864
|
+
if (isLegacyControlPlanePath(sourcePath) && inferContentFormatFromRepoPath(sourcePath)) {
|
|
5844
5865
|
return `docs/${sourcePath}`;
|
|
5845
5866
|
}
|
|
5846
5867
|
const baseSlug = slugFromPath(sourcePath);
|
|
@@ -5859,6 +5880,60 @@ function uniqueDestinationPath(basePath, sourcePath, usedPaths) {
|
|
|
5859
5880
|
usedPaths.add(uniquePath);
|
|
5860
5881
|
return uniquePath;
|
|
5861
5882
|
}
|
|
5883
|
+
function importableContentFormatFromRepoPath(repoPath) {
|
|
5884
|
+
return inferContentFormatFromRepoPath(repoPath) ?? localMemoryImportContentFormat(repoPath);
|
|
5885
|
+
}
|
|
5886
|
+
function localMemoryImportContentFormat(repoPath) {
|
|
5887
|
+
const normalized = normalizeRepoPath4(repoPath);
|
|
5888
|
+
const lowerPath = normalized.toLowerCase();
|
|
5889
|
+
const basename = lowerPath.split("/").at(-1) ?? lowerPath;
|
|
5890
|
+
if (extensionlessInstructionFiles.has(basename)) return "markdown";
|
|
5891
|
+
if (/\.mdc$/i.test(normalized) && isRepoLocalToolMemoryPath(normalized)) return "markdown";
|
|
5892
|
+
return void 0;
|
|
5893
|
+
}
|
|
5894
|
+
function classifyLocalMemoryDocument(repoPath, content) {
|
|
5895
|
+
const normalized = normalizeRepoPath4(repoPath);
|
|
5896
|
+
if (!isRepoLocalMemoryOrInstructionPath(normalized)) return void 0;
|
|
5897
|
+
if (isMemoryImportPath(normalized) || hasMemoryCue(normalized, content)) {
|
|
5898
|
+
return "memory";
|
|
5899
|
+
}
|
|
5900
|
+
if (isInstructionImportPath(normalized)) {
|
|
5901
|
+
return "prompt";
|
|
5902
|
+
}
|
|
5903
|
+
return void 0;
|
|
5904
|
+
}
|
|
5905
|
+
function isRepoLocalMemoryOrInstructionPath(repoPath) {
|
|
5906
|
+
return isMemoryImportPath(repoPath) || isInstructionImportPath(repoPath);
|
|
5907
|
+
}
|
|
5908
|
+
function isRepoLocalToolMemoryPath(repoPath) {
|
|
5909
|
+
return isRepoLocalMemoryOrInstructionPath(repoPath);
|
|
5910
|
+
}
|
|
5911
|
+
function isMemoryImportPath(repoPath) {
|
|
5912
|
+
const lowerPath = normalizeRepoPath4(repoPath).toLowerCase();
|
|
5913
|
+
return /^(docs\/memory|memory|memories|\.memory|\.memories)(\/|$)/.test(lowerPath);
|
|
5914
|
+
}
|
|
5915
|
+
function isInstructionImportPath(repoPath) {
|
|
5916
|
+
const normalized = normalizeRepoPath4(repoPath);
|
|
5917
|
+
const lowerPath = normalized.toLowerCase();
|
|
5918
|
+
const segments = lowerPath.split("/");
|
|
5919
|
+
const basename = segments.at(-1) ?? lowerPath;
|
|
5920
|
+
if (segments.length === 1 && rootAgentGuidanceFiles.has(basename)) return true;
|
|
5921
|
+
if (extensionlessInstructionFiles.has(basename)) return true;
|
|
5922
|
+
if (lowerPath === ".github/copilot-instructions.md") return true;
|
|
5923
|
+
if (lowerPath.startsWith(".github/instructions/") && lowerPath.endsWith(".instructions.md")) return true;
|
|
5924
|
+
if (lowerPath.startsWith(".cursor/rules/") && /\.(md|mdc)$/i.test(lowerPath)) return true;
|
|
5925
|
+
if (lowerPath.startsWith(".windsurf/rules/") && lowerPath.endsWith(".md")) return true;
|
|
5926
|
+
if (lowerPath.startsWith(".cline/") && lowerPath.endsWith(".md")) return true;
|
|
5927
|
+
if (lowerPath.startsWith(".roo/") && lowerPath.endsWith(".md")) return true;
|
|
5928
|
+
if (lowerPath.startsWith(".claude/") && lowerPath.endsWith(".md")) return true;
|
|
5929
|
+
if (lowerPath.startsWith(".gemini/") && lowerPath.endsWith(".md")) return true;
|
|
5930
|
+
if (lowerPath.startsWith(".vscode/") && lowerPath.endsWith(".instructions.md")) return true;
|
|
5931
|
+
return false;
|
|
5932
|
+
}
|
|
5933
|
+
function hasMemoryCue(repoPath, content) {
|
|
5934
|
+
const haystack = `${repoPath} ${inferTitle2(content, repoPath)}`.toLowerCase();
|
|
5935
|
+
return /\b(memory|memories|lesson|lessons|mistake|mistakes|learning|retro|retrospective|observation|observations)\b/.test(haystack);
|
|
5936
|
+
}
|
|
5862
5937
|
function isCanonicalControlPlanePath(repoPath) {
|
|
5863
5938
|
const [firstSegment, secondSegment, thirdSegment] = normalizeRepoPath4(repoPath).split("/");
|
|
5864
5939
|
return firstSegment === "docs" && Boolean(secondSegment === "html" && thirdSegment && controlPlaneRoots2.includes(thirdSegment) || secondSegment && controlPlaneRoots2.includes(secondSegment));
|
|
@@ -5884,7 +5959,7 @@ function stripFrontmatter(content) {
|
|
|
5884
5959
|
return closingLineEnd === -1 ? "" : content.slice(closingLineEnd + 1);
|
|
5885
5960
|
}
|
|
5886
5961
|
function slugFromPath(repoPath) {
|
|
5887
|
-
const withoutExtension = repoPath.replace(/\.(md|mdx|html?)$/i, "");
|
|
5962
|
+
const withoutExtension = repoPath.replace(/\.(md|mdx|mdc|html?)$/i, "");
|
|
5888
5963
|
const slug = withoutExtension.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 90);
|
|
5889
5964
|
return slug || "imported-document";
|
|
5890
5965
|
}
|