@basou/core 0.32.0 → 0.34.0
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/index.d.ts +467 -185
- package/dist/index.js +830 -510
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1080,7 +1080,7 @@ function isLazyExpired(approval, now) {
|
|
|
1080
1080
|
}
|
|
1081
1081
|
|
|
1082
1082
|
// src/decisions/decisions-renderer.ts
|
|
1083
|
-
import { lstat } from "fs/promises";
|
|
1083
|
+
import { lstat as lstat2 } from "fs/promises";
|
|
1084
1084
|
import { dirname as dirname2, join as join6, resolve } from "path";
|
|
1085
1085
|
|
|
1086
1086
|
// src/events/event-replay.ts
|
|
@@ -1367,6 +1367,598 @@ async function readAllEvents(sessionDir, options = {}) {
|
|
|
1367
1367
|
return out;
|
|
1368
1368
|
}
|
|
1369
1369
|
|
|
1370
|
+
// src/project/relative-path.ts
|
|
1371
|
+
function normalizeRelativePath(p) {
|
|
1372
|
+
const trimmed = p.trim();
|
|
1373
|
+
const absolute = trimmed.startsWith("/");
|
|
1374
|
+
const out = [];
|
|
1375
|
+
for (const seg of trimmed.split("/")) {
|
|
1376
|
+
if (seg === "" || seg === ".") continue;
|
|
1377
|
+
if (seg === "..") {
|
|
1378
|
+
const top = out[out.length - 1];
|
|
1379
|
+
if (top !== void 0 && top !== "..") {
|
|
1380
|
+
out.pop();
|
|
1381
|
+
} else if (!absolute) {
|
|
1382
|
+
out.push("..");
|
|
1383
|
+
}
|
|
1384
|
+
continue;
|
|
1385
|
+
}
|
|
1386
|
+
out.push(seg);
|
|
1387
|
+
}
|
|
1388
|
+
const joined = out.join("/");
|
|
1389
|
+
if (absolute) return `/${joined}`;
|
|
1390
|
+
return joined.length === 0 ? "." : joined;
|
|
1391
|
+
}
|
|
1392
|
+
|
|
1393
|
+
// src/storage/manifest.ts
|
|
1394
|
+
import { lstat } from "fs/promises";
|
|
1395
|
+
|
|
1396
|
+
// src/schemas/manifest.schema.ts
|
|
1397
|
+
import { z as z4 } from "zod";
|
|
1398
|
+
var ProjectSchema = z4.looseObject({
|
|
1399
|
+
name: z4.string().optional(),
|
|
1400
|
+
description: z4.string().optional()
|
|
1401
|
+
});
|
|
1402
|
+
var CapabilitiesSchema = z4.looseObject({
|
|
1403
|
+
enabled: z4.array(z4.string())
|
|
1404
|
+
});
|
|
1405
|
+
var ApprovalConfigSchema = z4.looseObject({
|
|
1406
|
+
required_for: z4.array(z4.string()).optional(),
|
|
1407
|
+
default_risk_level: z4.enum(["low", "medium", "high", "critical"])
|
|
1408
|
+
});
|
|
1409
|
+
var ClaudeCodeAdapterConfigSchema = z4.looseObject({
|
|
1410
|
+
enabled: z4.boolean(),
|
|
1411
|
+
config_path: z4.string().optional()
|
|
1412
|
+
});
|
|
1413
|
+
var AdaptersSchema = z4.looseObject({
|
|
1414
|
+
"claude-code": ClaudeCodeAdapterConfigSchema
|
|
1415
|
+
});
|
|
1416
|
+
var GitConfigSchema = z4.looseObject({
|
|
1417
|
+
events_log: z4.enum(["ignore", "commit"]).default("ignore")
|
|
1418
|
+
});
|
|
1419
|
+
var SOURCE_ROOT_PATTERN = /^(?![~/\\])(?![A-Za-z]:)(?!\s)[^\0\\]*[^\0\\\s]$/;
|
|
1420
|
+
var SourceRootSchema = z4.string().min(1).regex(SOURCE_ROOT_PATTERN, {
|
|
1421
|
+
message: "source_roots entries must be relative paths (no absolute path, '~', '\\', or null byte)"
|
|
1422
|
+
});
|
|
1423
|
+
var ImportConfigSchema = z4.looseObject({
|
|
1424
|
+
source_roots: z4.array(SourceRootSchema).min(1).optional()
|
|
1425
|
+
});
|
|
1426
|
+
var RepoVisibilitySchema = z4.enum(["public", "private", "future-public"]);
|
|
1427
|
+
var RepoLanguageSchema = z4.enum(["en", "ja", "en+ja"]);
|
|
1428
|
+
var PublishKindSchema = z4.enum(["web", "npm"]);
|
|
1429
|
+
var RepoInstructionsSchema = z4.enum(["hub", "self"]);
|
|
1430
|
+
var PublishTargetSchema = z4.looseObject({
|
|
1431
|
+
kind: PublishKindSchema,
|
|
1432
|
+
visibility: RepoVisibilitySchema.optional(),
|
|
1433
|
+
language: RepoLanguageSchema.optional()
|
|
1434
|
+
});
|
|
1435
|
+
var RepoEntrySchema = z4.looseObject({
|
|
1436
|
+
path: SourceRootSchema,
|
|
1437
|
+
visibility: RepoVisibilitySchema.optional(),
|
|
1438
|
+
language: RepoLanguageSchema.optional(),
|
|
1439
|
+
publishes: z4.array(PublishTargetSchema).optional(),
|
|
1440
|
+
instructions: RepoInstructionsSchema.optional()
|
|
1441
|
+
});
|
|
1442
|
+
var WorkspaceMetaSchema = z4.looseObject({
|
|
1443
|
+
id: WorkspaceIdSchema,
|
|
1444
|
+
name: z4.string().min(1),
|
|
1445
|
+
created_at: IsoTimestampSchema,
|
|
1446
|
+
updated_at: IsoTimestampSchema,
|
|
1447
|
+
/**
|
|
1448
|
+
* The generated workspace view: a throwaway directory that aggregates the
|
|
1449
|
+
* roster repos via symlinks (one `<repo-basename>` symlink per repo). A path
|
|
1450
|
+
* relative to the manifest root, reusing the machine-portable source-root
|
|
1451
|
+
* constraint. Absent for a solo project (no view needed); `basou project
|
|
1452
|
+
* workspace` reconciles the view's symlinks to the declared roster.
|
|
1453
|
+
*/
|
|
1454
|
+
view: SourceRootSchema.optional()
|
|
1455
|
+
});
|
|
1456
|
+
var ManifestSchema = z4.looseObject({
|
|
1457
|
+
schema_version: SchemaVersionSchema,
|
|
1458
|
+
// Same forward-compatible format gate as schema_version (accept 0.x.y, gate a
|
|
1459
|
+
// higher major with an upgrade error) rather than a hard literal. `basou_version`
|
|
1460
|
+
// is a format stamp, not the npm/product version; consolidating it with
|
|
1461
|
+
// schema_version is a candidate cleanup for the M4 freeze pass.
|
|
1462
|
+
basou_version: SchemaVersionSchema,
|
|
1463
|
+
workspace: WorkspaceMetaSchema,
|
|
1464
|
+
project: ProjectSchema,
|
|
1465
|
+
capabilities: CapabilitiesSchema,
|
|
1466
|
+
approval: ApprovalConfigSchema,
|
|
1467
|
+
adapters: AdaptersSchema,
|
|
1468
|
+
git: GitConfigSchema,
|
|
1469
|
+
import: ImportConfigSchema.optional(),
|
|
1470
|
+
repos: z4.array(RepoEntrySchema).min(1).optional()
|
|
1471
|
+
});
|
|
1472
|
+
var KNOWN_TOP_LEVEL_KEYS = new Set(Object.keys(ManifestSchema.shape));
|
|
1473
|
+
function unknownManifestKeys(manifest) {
|
|
1474
|
+
return Object.keys(manifest).filter((k) => !KNOWN_TOP_LEVEL_KEYS.has(k)).sort();
|
|
1475
|
+
}
|
|
1476
|
+
|
|
1477
|
+
// src/storage/manifest.ts
|
|
1478
|
+
function createManifest(input) {
|
|
1479
|
+
if (input.workspaceName.length === 0) {
|
|
1480
|
+
throw new Error("Workspace name is empty. Pass --name explicitly.");
|
|
1481
|
+
}
|
|
1482
|
+
const now = (input.now ?? /* @__PURE__ */ new Date()).toISOString();
|
|
1483
|
+
const workspaceId = input.workspaceId ?? prefixedUlid("ws");
|
|
1484
|
+
const project = {
|
|
1485
|
+
...input.projectName !== void 0 ? { name: input.projectName } : {},
|
|
1486
|
+
...input.projectDescription !== void 0 ? { description: input.projectDescription } : {}
|
|
1487
|
+
};
|
|
1488
|
+
const manifest = {
|
|
1489
|
+
schema_version: "0.1.0",
|
|
1490
|
+
basou_version: "0.1.0",
|
|
1491
|
+
workspace: {
|
|
1492
|
+
id: workspaceId,
|
|
1493
|
+
name: input.workspaceName,
|
|
1494
|
+
created_at: now,
|
|
1495
|
+
updated_at: now
|
|
1496
|
+
},
|
|
1497
|
+
project,
|
|
1498
|
+
capabilities: {
|
|
1499
|
+
enabled: ["core", "claude-code-adapter", "terminal-recording", "git-capability", "approval"]
|
|
1500
|
+
},
|
|
1501
|
+
approval: {
|
|
1502
|
+
required_for: ["destructive_command", "external_send"],
|
|
1503
|
+
default_risk_level: "medium"
|
|
1504
|
+
},
|
|
1505
|
+
adapters: {
|
|
1506
|
+
"claude-code": { enabled: true }
|
|
1507
|
+
},
|
|
1508
|
+
git: { events_log: "ignore" },
|
|
1509
|
+
...input.sourceRoots !== void 0 && input.sourceRoots.length > 0 ? { import: { source_roots: input.sourceRoots } } : {}
|
|
1510
|
+
};
|
|
1511
|
+
return ManifestSchema.parse(manifest);
|
|
1512
|
+
}
|
|
1513
|
+
async function writeManifest(paths, manifest, options) {
|
|
1514
|
+
const force = options?.force === true;
|
|
1515
|
+
const validated = ManifestSchema.parse(manifest);
|
|
1516
|
+
delete validated.project.repository_url;
|
|
1517
|
+
if (!force) {
|
|
1518
|
+
let existed = false;
|
|
1519
|
+
try {
|
|
1520
|
+
await lstat(paths.files.manifest);
|
|
1521
|
+
existed = true;
|
|
1522
|
+
} catch (error) {
|
|
1523
|
+
if (!hasErrorCode2(error) || error.code !== "ENOENT") {
|
|
1524
|
+
throw new Error("Failed to inspect existing manifest", { cause: error });
|
|
1525
|
+
}
|
|
1526
|
+
}
|
|
1527
|
+
if (existed) {
|
|
1528
|
+
throw new Error("Already initialized. Use --force to overwrite.");
|
|
1529
|
+
}
|
|
1530
|
+
}
|
|
1531
|
+
await writeYamlFile(paths.files.manifest, validated);
|
|
1532
|
+
}
|
|
1533
|
+
async function readManifest(paths) {
|
|
1534
|
+
const raw = await readYamlFile(paths.files.manifest);
|
|
1535
|
+
return ManifestSchema.parse(raw);
|
|
1536
|
+
}
|
|
1537
|
+
function hasErrorCode2(error) {
|
|
1538
|
+
if (!(error instanceof Error)) return false;
|
|
1539
|
+
return typeof error.code === "string";
|
|
1540
|
+
}
|
|
1541
|
+
|
|
1542
|
+
// src/lib/view-strings.ts
|
|
1543
|
+
function resolveViewLanguage(manifest) {
|
|
1544
|
+
if (manifest === null) return "en";
|
|
1545
|
+
const anchor = manifest.repos?.find((r) => normalizeRelativePath(r.path) === ".");
|
|
1546
|
+
return anchor?.language === "ja" ? "ja" : "en";
|
|
1547
|
+
}
|
|
1548
|
+
async function resolveViewLanguageFromPaths(paths) {
|
|
1549
|
+
try {
|
|
1550
|
+
return resolveViewLanguage(await readManifest(paths));
|
|
1551
|
+
} catch {
|
|
1552
|
+
return "en";
|
|
1553
|
+
}
|
|
1554
|
+
}
|
|
1555
|
+
function viewStrings(language) {
|
|
1556
|
+
return language === "ja" ? JA : EN;
|
|
1557
|
+
}
|
|
1558
|
+
function relativeAgeEn(startedAt, now) {
|
|
1559
|
+
if (startedAt === null) return "(unknown)";
|
|
1560
|
+
const ms = now.getTime() - Date.parse(startedAt);
|
|
1561
|
+
if (!Number.isFinite(ms) || ms < 0) return "just now";
|
|
1562
|
+
if (ms < 6e4) return "just now";
|
|
1563
|
+
const totalMin = Math.floor(ms / 6e4);
|
|
1564
|
+
const days = Math.floor(totalMin / 1440);
|
|
1565
|
+
const hours = Math.floor(totalMin % 1440 / 60);
|
|
1566
|
+
const mins = totalMin % 60;
|
|
1567
|
+
if (days > 0) return hours > 0 ? `${days}d ${hours}h ago` : `${days}d ago`;
|
|
1568
|
+
if (hours > 0) return mins > 0 ? `${hours}h ${mins}m ago` : `${hours}h ago`;
|
|
1569
|
+
return `${mins}m ago`;
|
|
1570
|
+
}
|
|
1571
|
+
function relativeAgeJa(startedAt, now) {
|
|
1572
|
+
if (startedAt === null) return "(\u4E0D\u660E)";
|
|
1573
|
+
const ms = now.getTime() - Date.parse(startedAt);
|
|
1574
|
+
if (!Number.isFinite(ms) || ms < 0) return "\u305F\u3063\u305F\u4ECA";
|
|
1575
|
+
if (ms < 6e4) return "\u305F\u3063\u305F\u4ECA";
|
|
1576
|
+
const totalMin = Math.floor(ms / 6e4);
|
|
1577
|
+
const days = Math.floor(totalMin / 1440);
|
|
1578
|
+
const hours = Math.floor(totalMin % 1440 / 60);
|
|
1579
|
+
const mins = totalMin % 60;
|
|
1580
|
+
if (days > 0) return hours > 0 ? `${days}\u65E5${hours}\u6642\u9593\u524D` : `${days}\u65E5\u524D`;
|
|
1581
|
+
if (hours > 0) return mins > 0 ? `${hours}\u6642\u9593${mins}\u5206\u524D` : `${hours}\u6642\u9593\u524D`;
|
|
1582
|
+
return `${mins}\u5206\u524D`;
|
|
1583
|
+
}
|
|
1584
|
+
var EN = {
|
|
1585
|
+
relativeAge: relativeAgeEn,
|
|
1586
|
+
common: {
|
|
1587
|
+
lastSessionLabel: "Last session",
|
|
1588
|
+
latestDecisionLabel: "Latest decision",
|
|
1589
|
+
recentFilesLabel: "Recently changed files",
|
|
1590
|
+
trackWhyLabel: "Why",
|
|
1591
|
+
decisionOtherSessionNote: (sid) => `Note: this decision comes from a different session [${sid}] than the last session.`
|
|
1592
|
+
},
|
|
1593
|
+
orientation: {
|
|
1594
|
+
headingWhere: "## Where you are now",
|
|
1595
|
+
headingRecent: (n) => `## Recent direction (last ${n} sessions)`,
|
|
1596
|
+
headingInFlight: "## What is in flight",
|
|
1597
|
+
headingForward: "## Where you are heading",
|
|
1598
|
+
headingCurrency: "## Is this current",
|
|
1599
|
+
inFlightTasksHeading: (n) => `### In-flight tasks (${n})`,
|
|
1600
|
+
pendingApprovalsHeading: (n) => `### Pending approvals (${n})`,
|
|
1601
|
+
suspectSessionsHeading: (n) => `### Suspect sessions (${n})`,
|
|
1602
|
+
openTracksHeading: (n) => `### Open tracks (shown until closed) (${n})`,
|
|
1603
|
+
decisionStaleNote: (age) => `Note: this is the latest *recorded* decision. The latest activity (${age}) is more recent, so the current direction may not be reflected here (conversational decisions are not captured automatically; record this session's decisions with \`basou decision capture\`).`,
|
|
1604
|
+
outOfRootWarning: (count, files) => `\u26A0 ${count} outside source_roots (possibly another project): ${files}`,
|
|
1605
|
+
recentEmpty: "(no records yet)",
|
|
1606
|
+
recentDecisionsLabel: "Decisions",
|
|
1607
|
+
recentNextStepLabel: "Next step",
|
|
1608
|
+
recentChangedLabel: "Changed",
|
|
1609
|
+
trackCloseInstruction: "When finished, close it with `basou decision void <decision_id>`. It stays listed here every time until closed.",
|
|
1610
|
+
nextStepRecordedLabel: (age) => `Next step (recorded, ${age})`,
|
|
1611
|
+
noteStaleNote: (age) => `Note: work continued after this was recorded (latest activity ${age}), so this starting point may be stale.`,
|
|
1612
|
+
fallbackStaleDirection: "- (no planned tasks or recorded next step \u2014 the latest activity postdates the latest decision; ask the user for the continuation point)",
|
|
1613
|
+
fallbackStaleReferenceLabel: "Reference (possibly stale \u2014 not the current direction)",
|
|
1614
|
+
trackNudge: 'Once the next essential direction is settled, record it as a track with `basou decision capture` (`"kind":"track"`) / `basou decision record --track` \u2014 it stays surfaced here every session until closed.',
|
|
1615
|
+
federatedFreshnessNote: "Note: the freshness verdict covers only this machine's local store. Missed work on other hosts cannot be assessed here (run `basou refresh` on each host to sync).",
|
|
1616
|
+
bannerUnverifiable: (n) => `> \u26A0\uFE0F **Re-import needed** \u2014 ${n} session(s) changed in the native logs but cannot be imported by a plain refresh. Re-import with \`basou refresh --force\` (details under "Is this current" at the bottom).`,
|
|
1617
|
+
bannerStale: (parts) => `> \u26A0\uFE0F **Stale (uncaptured: ${parts})** \u2014 run \`basou refresh\` before starting work (details under "Is this current" at the bottom).`,
|
|
1618
|
+
partNew: (n) => `${n} new`,
|
|
1619
|
+
partUpdated: (n) => `${n} updated`,
|
|
1620
|
+
partsJoiner: ", ",
|
|
1621
|
+
verdictUnverifiable: (n) => [
|
|
1622
|
+
`\u26A0\uFE0F The native logs changed, but ${n} session(s) cannot be safely re-imported by a plain \`basou refresh\` (non-append changes, prior-chain mismatch, etc.).`,
|
|
1623
|
+
"Re-import with `basou refresh --force`. (`basou verify` is a different check \u2014 it inspects already-imported data for tampering/corruption, a separate axis from the suspect count in the header. A clean verify can still leave uncaptured work.)"
|
|
1624
|
+
],
|
|
1625
|
+
verdictStale: (parts) => [
|
|
1626
|
+
`\u26A0\uFE0F Stale. There is uncaptured work since the last import (${parts}).`,
|
|
1627
|
+
"Run `basou refresh` before starting work."
|
|
1628
|
+
],
|
|
1629
|
+
verdictUpdatedOnly: (n) => [
|
|
1630
|
+
`\u26A0\uFE0F ${n} session(s) have been updated. \`basou refresh\` can import them.`,
|
|
1631
|
+
"(A session still in progress keeps growing after each import, so it will keep appearing here \u2014 that is normal.)"
|
|
1632
|
+
],
|
|
1633
|
+
verdictSuspectsAlso: (n) => `There are also ${n} suspect session(s) (see "Suspect sessions" above).`,
|
|
1634
|
+
verdictEmpty: [
|
|
1635
|
+
"\u2139\uFE0F No records yet.",
|
|
1636
|
+
"Work in this workspace and your current position will appear here."
|
|
1637
|
+
],
|
|
1638
|
+
verdictUnprobed: (rel, tool) => [
|
|
1639
|
+
`\u2139\uFE0F Showing the last imported state. Last work: ${rel} (${tool}).`,
|
|
1640
|
+
"Run `basou refresh` to confirm this is current."
|
|
1641
|
+
],
|
|
1642
|
+
verdictCurrent: (rel, tool, hasHosts) => hasHosts ? `\u2705 The capture on this host (local) is current. Last work: ${rel} (${tool}). No uncaptured native sessions.` : `\u2705 The capture is current. Last work: ${rel} (${tool}). No uncaptured native sessions.`,
|
|
1643
|
+
verdictSuspectsCaveat: (n) => `However, ${n} suspect session(s) need attention (see "Suspect sessions" above).`,
|
|
1644
|
+
verdictScopeDisclaimer: "Note: this verdict only checks whether captured native sessions are current and whether any are suspect. It does not detect planning-implementation drift or unrecorded decisions.",
|
|
1645
|
+
toolTerminal: "terminal",
|
|
1646
|
+
toolHuman: "manual note",
|
|
1647
|
+
toolImport: "another workspace",
|
|
1648
|
+
toolUnknown: "unknown"
|
|
1649
|
+
},
|
|
1650
|
+
handoff: {
|
|
1651
|
+
headingCurrentState: "## Current state",
|
|
1652
|
+
headingRecentFiles: "## Recently changed files",
|
|
1653
|
+
headingLatestDecision: "## Latest decision",
|
|
1654
|
+
headingOpenTracks: "## Open tracks (shown until closed)",
|
|
1655
|
+
headingUnresolved: "## Unresolved items",
|
|
1656
|
+
headingReadNext: "## Files to read next",
|
|
1657
|
+
headingNextWork: "## Work to do next",
|
|
1658
|
+
headingSessions: "## Sessions",
|
|
1659
|
+
lastTaskLabel: "Last task",
|
|
1660
|
+
decisionStaleNote: "Note: the latest activity postdates this decision. It may already be resolved in conversation \u2014 confirm the continuation point before resuming (conversational decisions are not captured automatically; record them with `basou decision capture`).",
|
|
1661
|
+
trackCloseInstruction: "When finished, close it with `basou decision void <decision_id>`."
|
|
1662
|
+
},
|
|
1663
|
+
decisions: {
|
|
1664
|
+
dateLabel: "date",
|
|
1665
|
+
trackKindLine: "- kind: track (stays in orient/handoff until closed)",
|
|
1666
|
+
decisionLabel: "decision"
|
|
1667
|
+
},
|
|
1668
|
+
report: {
|
|
1669
|
+
headingSummary: "## Summary",
|
|
1670
|
+
headingVolume: "## Work volume",
|
|
1671
|
+
headingDecisions: "## Decisions",
|
|
1672
|
+
headingApprovals: "## Approvals",
|
|
1673
|
+
headingTasks: "## Tasks",
|
|
1674
|
+
headingChangedFiles: "## Changed files",
|
|
1675
|
+
headingSessions: "## Sessions",
|
|
1676
|
+
headingIntegrity: "## Integrity"
|
|
1677
|
+
}
|
|
1678
|
+
};
|
|
1679
|
+
var JA = {
|
|
1680
|
+
relativeAge: relativeAgeJa,
|
|
1681
|
+
common: {
|
|
1682
|
+
lastSessionLabel: "\u6700\u7D42 session",
|
|
1683
|
+
latestDecisionLabel: "\u76F4\u8FD1\u306E\u5224\u65AD",
|
|
1684
|
+
recentFilesLabel: "\u76F4\u8FD1\u306E\u5909\u66F4\u30D5\u30A1\u30A4\u30EB",
|
|
1685
|
+
trackWhyLabel: "\u7406\u7531",
|
|
1686
|
+
decisionOtherSessionNote: (sid) => `\u6CE8: \u3053\u306E\u5224\u65AD\u306F\u6700\u7D42 session \u3068\u306F\u5225\u306E session [${sid}] \u306E\u3082\u306E\u3067\u3059\u3002`
|
|
1687
|
+
},
|
|
1688
|
+
orientation: {
|
|
1689
|
+
headingWhere: "## \u4ECA\u3069\u3053\u306B\u3044\u308B",
|
|
1690
|
+
headingRecent: (n) => `## \u6700\u8FD1\u306E\u6D41\u308C (\u76F4\u8FD1 ${n} session)`,
|
|
1691
|
+
headingInFlight: "## \u4F55\u304C\u52D5\u304F",
|
|
1692
|
+
headingForward: "## \u3069\u3053\u3078\u5411\u304B\u3046",
|
|
1693
|
+
headingCurrency: "## \u3053\u308C\u306F\u6700\u65B0\u304B",
|
|
1694
|
+
inFlightTasksHeading: (n) => `### \u9032\u884C\u4E2D task (${n})`,
|
|
1695
|
+
pendingApprovalsHeading: (n) => `### \u627F\u8A8D\u5F85\u3061 (${n})`,
|
|
1696
|
+
suspectSessionsHeading: (n) => `### \u8981\u6CE8\u610F session (${n})`,
|
|
1697
|
+
openTracksHeading: (n) => `### \u672A\u5B8C\u30C8\u30E9\u30C3\u30AF (close \u307E\u3067\u7D99\u7D9A\u8868\u793A) (${n})`,
|
|
1698
|
+
decisionStaleNote: (age) => `\u6CE8: \u3053\u308C\u306F\u6700\u5F8C\u306B\u300C\u8A18\u9332\u3055\u308C\u305F\u300D\u5224\u65AD\u3067\u3059\u3002\u6700\u7D42\u6D3B\u52D5 (${age}) \u306F\u3053\u308C\u3088\u308A\u5F8C\u306E\u305F\u3081\u3001\u73FE\u5728\u306E\u65B9\u91DD\u304C\u53CD\u6620\u3055\u308C\u3066\u3044\u306A\u3044\u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059(\u4F1A\u8A71\u3067\u306E\u610F\u601D\u6C7A\u5B9A\u306F\u81EA\u52D5\u8A18\u9332\u3055\u308C\u307E\u305B\u3093\u3002\`basou decision capture\` \u3067\u3053\u306E session \u306E\u5224\u65AD\u3092\u8A18\u9332\u3067\u304D\u307E\u3059)\u3002`,
|
|
1699
|
+
outOfRootWarning: (count, files) => `\u26A0 source_roots \u5916 ${count} \u4EF6 (\u5225\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u306E\u53EF\u80FD\u6027): ${files}`,
|
|
1700
|
+
recentEmpty: "(\u307E\u3060\u8A18\u9332\u304C\u3042\u308A\u307E\u305B\u3093)",
|
|
1701
|
+
recentDecisionsLabel: "\u5224\u65AD",
|
|
1702
|
+
recentNextStepLabel: "\u6B21\u306E\u8D77\u70B9",
|
|
1703
|
+
recentChangedLabel: "\u5909\u66F4",
|
|
1704
|
+
trackCloseInstruction: "\u5B8C\u4E86\u3057\u305F\u3089 `basou decision void <decision_id>` \u3067\u9589\u3058\u3066\u304F\u3060\u3055\u3044\u3002\u9589\u3058\u308B\u307E\u3067\u6BCE\u56DE\u3053\u3053\u306B\u8868\u793A\u3055\u308C\u307E\u3059\u3002",
|
|
1705
|
+
nextStepRecordedLabel: (age) => `\u6B21\u306E\u8D77\u70B9 (\u8A18\u9332\u6E08\u307F, ${age})`,
|
|
1706
|
+
noteStaleNote: (age) => `\u6CE8: \u3053\u306E\u8D77\u70B9\u306E\u8A18\u9332\u5F8C (\u6700\u7D42\u6D3B\u52D5 ${age}) \u3082\u4F5C\u696D\u304C\u7D9A\u3044\u3066\u3044\u307E\u3059\u3002\u518D\u958B\u70B9\u304C\u53E4\u3044\u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059\u3002`,
|
|
1707
|
+
fallbackStaleDirection: "- (no planned tasks or recorded next step \u2014 \u6700\u7D42\u6D3B\u52D5\u306F\u76F4\u8FD1\u306E\u5224\u65AD\u3088\u308A\u5F8C\u3067\u3059\u3002\u7D99\u7D9A\u70B9\u3092\u30E6\u30FC\u30B6\u306B\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044)",
|
|
1708
|
+
fallbackStaleReferenceLabel: "\u53C2\u8003 (\u53E4\u3044\u53EF\u80FD\u6027\u30FB\u65B9\u91DD\u3067\u306F\u306A\u3044)",
|
|
1709
|
+
trackNudge: '\u6B21\u306B\u4F5C\u308B\u3079\u304D\u672C\u8CEA\u7684\u306A\u65B9\u5411\u6027\u304C\u5B9A\u307E\u3063\u305F\u3089 `basou decision capture` (`"kind":"track"`) / `basou decision record --track` \u3067 track \u5316\u3059\u308B\u3068\u3001close \u307E\u3067\u6BCE session \u3053\u3053\u306B\u7D99\u7D9A\u8868\u793A\u3055\u308C\u307E\u3059\u3002',
|
|
1710
|
+
federatedFreshnessNote: "\u6CE8: \u9BAE\u5EA6\u5224\u5B9A\u306F\u3053\u306E\u30DE\u30B7\u30F3\u306E\u30ED\u30FC\u30AB\u30EB\u30B9\u30C8\u30A2\u306E\u307F\u304C\u5BFE\u8C61\u3067\u3059\u3002\u4ED6\u30DB\u30B9\u30C8\u306E\u53D6\u308A\u3053\u307C\u3057\u306F\u5224\u5B9A\u3067\u304D\u307E\u305B\u3093(\u5404\u30DB\u30B9\u30C8\u3067 basou refresh \u3092\u5B9F\u884C\u3057\u540C\u671F\u3057\u3066\u304F\u3060\u3055\u3044)\u3002",
|
|
1711
|
+
bannerUnverifiable: (n) => `> \u26A0\uFE0F **\u518D\u53D6\u308A\u8FBC\u307F\u304C\u5FC5\u8981** \u2014 native \u30ED\u30B0\u304C\u5909\u5316\u3057\u305F\u304C\u901A\u5E38\u306E refresh \u3067\u306F\u53D6\u308A\u8FBC\u3081\u306A\u3044\u30BB\u30C3\u30B7\u30E7\u30F3\u304C ${n} \u4EF6\u3042\u308A\u307E\u3059\u3002\`basou refresh --force\` \u3067\u518D\u53D6\u308A\u8FBC\u307F\u3057\u3066\u304F\u3060\u3055\u3044(\u8A73\u7D30\u306F\u672B\u5C3E\u300C\u3053\u308C\u306F\u6700\u65B0\u304B\u300D)\u3002`,
|
|
1712
|
+
bannerStale: (parts) => `> \u26A0\uFE0F **\u53E4\u3044\u3067\u3059\uFF08\u672A\u53D6\u308A\u8FBC\u307F ${parts}\uFF09** \u2014 \u7740\u624B\u524D\u306B\u5FC5\u305A \`basou refresh\` \u3092\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044(\u8A73\u7D30\u306F\u672B\u5C3E\u300C\u3053\u308C\u306F\u6700\u65B0\u304B\u300D)\u3002`,
|
|
1713
|
+
partNew: (n) => `\u65B0\u898F ${n} \u4EF6`,
|
|
1714
|
+
partUpdated: (n) => `\u66F4\u65B0 ${n} \u4EF6`,
|
|
1715
|
+
partsJoiner: "\u30FB",
|
|
1716
|
+
verdictUnverifiable: (n) => [
|
|
1717
|
+
`\u26A0\uFE0F native \u30ED\u30B0\u304C\u5909\u5316\u3057\u307E\u3057\u305F\u304C\u3001\u901A\u5E38\u306E \`basou refresh\` \u3067\u306F\u5B89\u5168\u306B\u518D\u53D6\u308A\u8FBC\u307F\u3067\u304D\u306A\u3044\u30BB\u30C3\u30B7\u30E7\u30F3\u304C ${n} \u4EF6\u3042\u308A\u307E\u3059(\u975E\u8FFD\u8A18\u5909\u66F4\u30FB\u524D\u30C1\u30A7\u30FC\u30F3\u4E0D\u6574\u5408\u306A\u3069)\u3002`,
|
|
1718
|
+
"`basou refresh --force` \u3067\u518D\u53D6\u308A\u8FBC\u307F\u3057\u3066\u304F\u3060\u3055\u3044\u3002(`basou verify` \u306F\u5225\u7269=\u53D6\u308A\u8FBC\u307F\u6E08\u307F\u30C7\u30FC\u30BF\u306E\u6539\u7AC4/\u7834\u640D\u691C\u67FB\u3067\u3001\u30D8\u30C3\u30C0\u306E suspect \u3068\u306F\u5225\u8EF8\u3067\u3059\u3002verify \u304C clean \u3067\u3082\u672A\u53D6\u308A\u8FBC\u307F\u306F\u6B8B\u308A\u5F97\u307E\u3059\u3002)"
|
|
1719
|
+
],
|
|
1720
|
+
verdictStale: (parts) => [
|
|
1721
|
+
`\u26A0\uFE0F \u53E4\u3044\u3067\u3059\u3002\u6700\u5F8C\u306E\u53D6\u308A\u8FBC\u307F\u4EE5\u964D\u306B\u672A\u53D6\u308A\u8FBC\u307F\u306E\u4F5C\u696D\u304C\u3042\u308A\u307E\u3059(${parts})\u3002`,
|
|
1722
|
+
"\u7740\u624B\u524D\u306B\u5FC5\u305A `basou refresh` \u3092\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002"
|
|
1723
|
+
],
|
|
1724
|
+
verdictUpdatedOnly: (n) => [
|
|
1725
|
+
`\u26A0\uFE0F \u66F4\u65B0\u3055\u308C\u305F\u30BB\u30C3\u30B7\u30E7\u30F3\u304C ${n} \u4EF6\u3042\u308A\u307E\u3059\u3002\`basou refresh\` \u3067\u53D6\u308A\u8FBC\u3081\u307E\u3059\u3002`,
|
|
1726
|
+
"(\u9032\u884C\u4E2D\u306E\u30BB\u30C3\u30B7\u30E7\u30F3\u304C\u3042\u308B\u5834\u5408\u3001\u305D\u308C\u81EA\u8EAB\u306F\u53D6\u308A\u8FBC\u307F\u5F8C\u3082\u5897\u3048\u7D9A\u3051\u308B\u305F\u3081\u6B8B\u308A\u307E\u3059\uFF1D\u6B63\u5E38\u3067\u3059\u3002)"
|
|
1727
|
+
],
|
|
1728
|
+
verdictSuspectsAlso: (n) => `\u307E\u305F\u8981\u6CE8\u610F\u30BB\u30C3\u30B7\u30E7\u30F3\u304C ${n} \u4EF6\u3042\u308A\u307E\u3059(\u4E0A\u8A18\u300C\u8981\u6CE8\u610F session\u300D\u53C2\u7167)\u3002`,
|
|
1729
|
+
verdictEmpty: [
|
|
1730
|
+
"\u2139\uFE0F \u307E\u3060\u8A18\u9332\u304C\u3042\u308A\u307E\u305B\u3093\u3002",
|
|
1731
|
+
"\u3053\u306E\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u3067\u4F5C\u696D\u3059\u308B\u3068\u3001\u3053\u3053\u306B\u73FE\u5728\u5730\u304C\u8868\u793A\u3055\u308C\u307E\u3059\u3002"
|
|
1732
|
+
],
|
|
1733
|
+
verdictUnprobed: (rel, tool) => [
|
|
1734
|
+
`\u2139\uFE0F \u53D6\u308A\u8FBC\u307F\u6E08\u307F\u306E\u72B6\u614B\u3092\u8868\u793A\u3057\u3066\u3044\u307E\u3059\u3002\u6700\u5F8C\u306E\u4F5C\u696D\u306F ${rel}(${tool})\u3002`,
|
|
1735
|
+
"\u6700\u65B0\u304B\u78BA\u8A8D\u3059\u308B\u306B\u306F `basou refresh` \u3092\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002"
|
|
1736
|
+
],
|
|
1737
|
+
verdictCurrent: (rel, tool, hasHosts) => `\u2705 ${hasHosts ? "\u3053\u306E\u30DB\u30B9\u30C8(\u30ED\u30FC\u30AB\u30EB)\u306E" : ""}\u53D6\u308A\u8FBC\u307F\u306F\u6700\u65B0\u3067\u3059\u3002\u6700\u5F8C\u306E\u4F5C\u696D\u306F ${rel}(${tool})\u3002\u672A\u53D6\u308A\u8FBC\u307F\u306E native \u30BB\u30C3\u30B7\u30E7\u30F3\u306F\u3042\u308A\u307E\u305B\u3093\u3002`,
|
|
1738
|
+
verdictSuspectsCaveat: (n) => `\u305F\u3060\u3057\u8981\u6CE8\u610F\u30BB\u30C3\u30B7\u30E7\u30F3\u304C ${n} \u4EF6\u3042\u308A\u307E\u3059(\u4E0A\u8A18\u300C\u8981\u6CE8\u610F session\u300D\u53C2\u7167)\u3002`,
|
|
1739
|
+
verdictScopeDisclaimer: "\u6CE8: \u3053\u306E\u5224\u5B9A\u306F\u53D6\u308A\u8FBC\u307F\u6E08\u307F native \u30BB\u30C3\u30B7\u30E7\u30F3\u306E\u9BAE\u5EA6\u3068 suspect \u306E\u6709\u7121\u3060\u3051\u3092\u898B\u307E\u3059\u3002\u8A08\u753B\u2194\u5B9F\u88C5\u306E\u30C9\u30EA\u30D5\u30C8\u3084\u672A\u8A18\u9332\u306E\u610F\u601D\u6C7A\u5B9A\u307E\u3067\u306F\u691C\u77E5\u3057\u307E\u305B\u3093\u3002",
|
|
1740
|
+
toolTerminal: "\u30BF\u30FC\u30DF\u30CA\u30EB",
|
|
1741
|
+
toolHuman: "\u624B\u52D5\u30E1\u30E2",
|
|
1742
|
+
toolImport: "\u4ED6\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9",
|
|
1743
|
+
toolUnknown: "\u4E0D\u660E"
|
|
1744
|
+
},
|
|
1745
|
+
handoff: {
|
|
1746
|
+
headingCurrentState: "## \u73FE\u5728\u306E\u72B6\u614B",
|
|
1747
|
+
headingRecentFiles: "## \u76F4\u8FD1\u306E\u5909\u66F4\u30D5\u30A1\u30A4\u30EB",
|
|
1748
|
+
headingLatestDecision: "## \u76F4\u8FD1\u306E\u5224\u65AD",
|
|
1749
|
+
headingOpenTracks: "## \u672A\u5B8C\u30C8\u30E9\u30C3\u30AF (close \u307E\u3067\u7D99\u7D9A\u8868\u793A)",
|
|
1750
|
+
headingUnresolved: "## \u672A\u6C7A\u4E8B\u9805",
|
|
1751
|
+
headingReadNext: "## \u6B21\u306B\u8AAD\u3080\u3079\u304D\u30D5\u30A1\u30A4\u30EB",
|
|
1752
|
+
headingNextWork: "## \u6B21\u306B\u5B9F\u884C\u3059\u3079\u304D\u4F5C\u696D",
|
|
1753
|
+
headingSessions: "## \u30BB\u30C3\u30B7\u30E7\u30F3\u4E00\u89A7",
|
|
1754
|
+
lastTaskLabel: "\u6700\u7D42 task",
|
|
1755
|
+
decisionStaleNote: "\u6CE8: \u6700\u7D42\u6D3B\u52D5\u306F\u3053\u306E\u5224\u65AD\u3088\u308A\u5F8C\u3067\u3059\u3002\u4F1A\u8A71\u3067\u65E2\u306B\u89E3\u6C7A\u6E08\u307F\u306E\u53EF\u80FD\u6027\u304C\u3042\u308B\u305F\u3081\u3001\u518D\u958B\u524D\u306B\u7D99\u7D9A\u70B9\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044(\u4F1A\u8A71\u3067\u306E\u610F\u601D\u6C7A\u5B9A\u306F\u81EA\u52D5\u8A18\u9332\u3055\u308C\u307E\u305B\u3093\u3002`basou decision capture` \u3067\u8A18\u9332\u3067\u304D\u307E\u3059)\u3002",
|
|
1756
|
+
trackCloseInstruction: "\u5B8C\u4E86\u3057\u305F\u3089 `basou decision void <decision_id>` \u3067\u9589\u3058\u3066\u304F\u3060\u3055\u3044\u3002"
|
|
1757
|
+
},
|
|
1758
|
+
decisions: {
|
|
1759
|
+
dateLabel: "\u6C7A\u5B9A\u65E5",
|
|
1760
|
+
trackKindLine: "- \u7A2E\u5225: track (close \u307E\u3067 orient/handoff \u306B\u7D99\u7D9A\u8868\u793A)",
|
|
1761
|
+
decisionLabel: "\u5224\u65AD"
|
|
1762
|
+
},
|
|
1763
|
+
report: {
|
|
1764
|
+
headingSummary: "## \u6982\u8981",
|
|
1765
|
+
headingVolume: "## \u4F5C\u696D\u91CF",
|
|
1766
|
+
headingDecisions: "## \u5224\u65AD",
|
|
1767
|
+
headingApprovals: "## \u627F\u8A8D",
|
|
1768
|
+
headingTasks: "## \u30BF\u30B9\u30AF",
|
|
1769
|
+
headingChangedFiles: "## \u5909\u66F4\u30D5\u30A1\u30A4\u30EB",
|
|
1770
|
+
headingSessions: "## \u30BB\u30C3\u30B7\u30E7\u30F3\u4E00\u89A7",
|
|
1771
|
+
headingIntegrity: "## \u6574\u5408\u6027"
|
|
1772
|
+
}
|
|
1773
|
+
};
|
|
1774
|
+
function resolveRepoContentLanguage(language) {
|
|
1775
|
+
return language === "ja" ? "ja" : "en";
|
|
1776
|
+
}
|
|
1777
|
+
function resolveAnchorContentLanguage(repos) {
|
|
1778
|
+
return resolveRepoContentLanguage(repos.find((r) => r.anchor === true)?.language);
|
|
1779
|
+
}
|
|
1780
|
+
function presetStrings(language) {
|
|
1781
|
+
return language === "ja" ? PRESET_JA : PRESET_EN;
|
|
1782
|
+
}
|
|
1783
|
+
var PRESET_EN = {
|
|
1784
|
+
repoBlock: {
|
|
1785
|
+
heading: "## Project configuration (generated by basou \u2014 the manifest is the source of truth)",
|
|
1786
|
+
intro: "This section is generated by `basou project preset` from the declarations in `.basou/manifest.yaml`. Edit the manifest, not this block (content outside the markers is preserved).",
|
|
1787
|
+
visibilityLabel: (v) => {
|
|
1788
|
+
switch (v) {
|
|
1789
|
+
case "public":
|
|
1790
|
+
return "public (the git history is public)";
|
|
1791
|
+
case "private":
|
|
1792
|
+
return "private (the git history is not public)";
|
|
1793
|
+
case "future-public":
|
|
1794
|
+
return "future-public (private today, planned to go public)";
|
|
1795
|
+
default:
|
|
1796
|
+
return "unset";
|
|
1797
|
+
}
|
|
1798
|
+
},
|
|
1799
|
+
sourceLanguageLabel: (l) => {
|
|
1800
|
+
switch (l) {
|
|
1801
|
+
case "en":
|
|
1802
|
+
return "en (commits, comments, and code in English)";
|
|
1803
|
+
case "ja":
|
|
1804
|
+
return "ja (commits, comments, and code in Japanese)";
|
|
1805
|
+
case "en+ja":
|
|
1806
|
+
return "en+ja (commits, comments, and code in English and Japanese)";
|
|
1807
|
+
default:
|
|
1808
|
+
return "unset";
|
|
1809
|
+
}
|
|
1810
|
+
},
|
|
1811
|
+
publishKindLabel: (k) => k === "web" ? "web (deployed)" : "npm (package)",
|
|
1812
|
+
publishVisibilityLabel: (v) => {
|
|
1813
|
+
switch (v) {
|
|
1814
|
+
case "public":
|
|
1815
|
+
return "public";
|
|
1816
|
+
case "private":
|
|
1817
|
+
return "private";
|
|
1818
|
+
case "future-public":
|
|
1819
|
+
return "future-public";
|
|
1820
|
+
default:
|
|
1821
|
+
return "visibility unset";
|
|
1822
|
+
}
|
|
1823
|
+
},
|
|
1824
|
+
contentLanguageLabel: (l) => l ?? "language unset",
|
|
1825
|
+
sourceVisibilityLabel: "Source visibility",
|
|
1826
|
+
sourceLanguageLineLabel: "Source language",
|
|
1827
|
+
publishesNone: "- Published surfaces: none",
|
|
1828
|
+
publishesHeader: "- Published surfaces:"
|
|
1829
|
+
},
|
|
1830
|
+
viewBlock: {
|
|
1831
|
+
heading: "## Workspace view layout (generated by basou \u2014 the manifest is the source of truth)",
|
|
1832
|
+
intro: "This section is generated by `basou project preset` from the declarations in `.basou/manifest.yaml`. Edit the manifest, not this block (content outside the markers is preserved).",
|
|
1833
|
+
selfNote: (viewName) => `This AGENTS.md is itself generated by basou (canonical: \`agents/${viewName}/AGENTS.md\`; content outside the markers is preserved).`,
|
|
1834
|
+
aggregates: (n) => `This directory is a **view** aggregating the ${n} declared repo(s) via symlinks. It holds no content of its own and is not under git.`,
|
|
1835
|
+
reposHeading: "### Aggregated repos",
|
|
1836
|
+
tableHeader: "| repo | visibility | language | instructions |",
|
|
1837
|
+
instructionsAnchor: "anchor (hand-maintained)",
|
|
1838
|
+
instructionsSelf: "self (the repo owns it)",
|
|
1839
|
+
instructionsHub: "hub (generated by basou)",
|
|
1840
|
+
unsetShort: "unset",
|
|
1841
|
+
commitHeading: "### Where to commit",
|
|
1842
|
+
commitBody: "You cannot commit in the view (it is not under git). Always `cd` into the actual repo before committing.",
|
|
1843
|
+
conventionsHeading: "### Required reading",
|
|
1844
|
+
conventionsBody: "The working conventions live in each repo's AGENTS.md. Read these before working.",
|
|
1845
|
+
principlesHeading: "### Key principles",
|
|
1846
|
+
principleStateless: "- This directory holds no state (not under git)",
|
|
1847
|
+
principleNoFiles: "- Do not place important files here directly (they belong in the repos)"
|
|
1848
|
+
},
|
|
1849
|
+
anchorStarter: {
|
|
1850
|
+
identityLine: (title) => `> This repository is the **planning master (anchor) of ${title}**. AI agents working here should read this file first.`,
|
|
1851
|
+
starterNote: "> This file is a starter that `basou project derive` generated **once** at greenfield bring-up. Hand-maintain it from here \u2014 basou never regenerates or overwrites it (there are no BASOU:GENERATED markers; edit freely).",
|
|
1852
|
+
basicsHeading: "## Project basics",
|
|
1853
|
+
basicsTodo: "<!-- TODO: these cannot be derived from the manifest. Fill them in. -->",
|
|
1854
|
+
commitHeading: "## Where to commit",
|
|
1855
|
+
commitPlanning: "- **This repository (the planning master)**: plans, designs, strategy docs.",
|
|
1856
|
+
commitImplementation: "- **Each implementation repo**: implementation code. Always `cd` into the target repo before committing.",
|
|
1857
|
+
commitView: "- **The workspace view**: not under git. You cannot commit in the view.",
|
|
1858
|
+
conventionsHeading: "## Required reading",
|
|
1859
|
+
conventionsBody: "The working conventions live in each repo's AGENTS.md. Read these before working.",
|
|
1860
|
+
viewPointerLine: (viewName) => `- ${viewName}/AGENTS.md (the workspace view, generated by basou) \u2014 **the authoritative, up-to-date repo roster (the live roster) lives there**`,
|
|
1861
|
+
policyHeading: "## Working policy (project specifics)",
|
|
1862
|
+
policyTodo: [
|
|
1863
|
+
"<!-- TODO: describe these for your project.",
|
|
1864
|
+
" - Current phase / key documents",
|
|
1865
|
+
" - Secrets handling (where NOT to write them)",
|
|
1866
|
+
" - Language policy (commits / comments / docs)",
|
|
1867
|
+
" - Commit discipline (avoid mixed commits, etc.)",
|
|
1868
|
+
"-->"
|
|
1869
|
+
]
|
|
1870
|
+
}
|
|
1871
|
+
};
|
|
1872
|
+
var PRESET_JA = {
|
|
1873
|
+
repoBlock: {
|
|
1874
|
+
heading: "## \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u69CB\u6210(basou \u304C\u751F\u6210 \u2014 manifest \u304C\u6B63\u672C)",
|
|
1875
|
+
intro: "\u3053\u306E\u30BB\u30AF\u30B7\u30E7\u30F3\u306F `.basou/manifest.yaml` \u306E\u5BA3\u8A00\u304B\u3089 `basou project preset` \u304C\u751F\u6210\u3057\u307E\u3059\u3002\u7DE8\u96C6\u306F manifest \u5074\u3067\u884C\u3063\u3066\u304F\u3060\u3055\u3044(\u30DE\u30FC\u30AB\u30FC\u5916\u306E\u8A18\u8FF0\u306F\u4FDD\u6301\u3055\u308C\u307E\u3059)\u3002",
|
|
1876
|
+
visibilityLabel: (v) => {
|
|
1877
|
+
switch (v) {
|
|
1878
|
+
case "public":
|
|
1879
|
+
return "public(git \u5C65\u6B74\u306F\u516C\u958B)";
|
|
1880
|
+
case "private":
|
|
1881
|
+
return "private(git \u5C65\u6B74\u306F\u975E\u516C\u958B)";
|
|
1882
|
+
case "future-public":
|
|
1883
|
+
return "future-public(\u73FE\u5728\u306F\u975E\u516C\u958B\u30FB\u5C06\u6765\u516C\u958B\u4E88\u5B9A)";
|
|
1884
|
+
default:
|
|
1885
|
+
return "\u672A\u8A2D\u5B9A";
|
|
1886
|
+
}
|
|
1887
|
+
},
|
|
1888
|
+
sourceLanguageLabel: (l) => {
|
|
1889
|
+
switch (l) {
|
|
1890
|
+
case "en":
|
|
1891
|
+
return "en(commit\u30FB\u30B3\u30E1\u30F3\u30C8\u30FB\u30B3\u30FC\u30C9\u306F\u82F1\u8A9E)";
|
|
1892
|
+
case "ja":
|
|
1893
|
+
return "ja(commit\u30FB\u30B3\u30E1\u30F3\u30C8\u30FB\u30B3\u30FC\u30C9\u306F\u65E5\u672C\u8A9E)";
|
|
1894
|
+
case "en+ja":
|
|
1895
|
+
return "en+ja(commit\u30FB\u30B3\u30E1\u30F3\u30C8\u30FB\u30B3\u30FC\u30C9\u306F\u65E5\u82F1)";
|
|
1896
|
+
default:
|
|
1897
|
+
return "\u672A\u8A2D\u5B9A";
|
|
1898
|
+
}
|
|
1899
|
+
},
|
|
1900
|
+
publishKindLabel: (k) => k === "web" ? "web(\u30C7\u30D7\u30ED\u30A4)" : "npm(\u30D1\u30C3\u30B1\u30FC\u30B8)",
|
|
1901
|
+
publishVisibilityLabel: (v) => {
|
|
1902
|
+
switch (v) {
|
|
1903
|
+
case "public":
|
|
1904
|
+
return "\u516C\u958B";
|
|
1905
|
+
case "private":
|
|
1906
|
+
return "\u975E\u516C\u958B";
|
|
1907
|
+
case "future-public":
|
|
1908
|
+
return "\u5C06\u6765\u516C\u958B";
|
|
1909
|
+
default:
|
|
1910
|
+
return "\u53EF\u8996\u6027\u672A\u8A2D\u5B9A";
|
|
1911
|
+
}
|
|
1912
|
+
},
|
|
1913
|
+
contentLanguageLabel: (l) => l ?? "\u8A00\u8A9E\u672A\u8A2D\u5B9A",
|
|
1914
|
+
sourceVisibilityLabel: "\u30BD\u30FC\u30B9\u53EF\u8996\u6027",
|
|
1915
|
+
sourceLanguageLineLabel: "\u30BD\u30FC\u30B9\u8A00\u8A9E",
|
|
1916
|
+
publishesNone: "- \u914D\u4FE1\u7269: \u306A\u3057",
|
|
1917
|
+
publishesHeader: "- \u914D\u4FE1\u7269:"
|
|
1918
|
+
},
|
|
1919
|
+
viewBlock: {
|
|
1920
|
+
heading: "## workspace view \u69CB\u6210(basou \u304C\u751F\u6210 \u2014 manifest \u304C\u6B63\u672C)",
|
|
1921
|
+
intro: "\u3053\u306E\u30BB\u30AF\u30B7\u30E7\u30F3\u306F `.basou/manifest.yaml` \u306E\u5BA3\u8A00\u304B\u3089 `basou project preset` \u304C\u751F\u6210\u3057\u307E\u3059\u3002\u7DE8\u96C6\u306F manifest \u5074\u3067\u884C\u3063\u3066\u304F\u3060\u3055\u3044(\u30DE\u30FC\u30AB\u30FC\u5916\u306E\u8A18\u8FF0\u306F\u4FDD\u6301\u3055\u308C\u307E\u3059)\u3002",
|
|
1922
|
+
selfNote: (viewName) => `\u3053\u306E AGENTS.md \u81EA\u8EAB\u3082 basou \u306E\u751F\u6210\u7269\u3067\u3059(\u5B9F\u4F53: \`agents/${viewName}/AGENTS.md\`\u3001\u30DE\u30FC\u30AB\u30FC\u5916\u306E\u8A18\u8FF0\u306F\u4FDD\u6301\u3055\u308C\u307E\u3059)\u3002`,
|
|
1923
|
+
aggregates: (n) => `\u3053\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306F\u3001\u5BA3\u8A00\u3055\u308C\u305F ${n} \u500B\u306E repo \u3092 symlink \u3067\u96C6\u7D04\u3059\u308B **view** \u3067\u3059\u3002\u5B9F\u4F53\u3092\u6301\u305F\u305A\u3001git \u7BA1\u7406\u5916\u3067\u3059\u3002`,
|
|
1924
|
+
reposHeading: "### \u96C6\u7D04\u3057\u3066\u3044\u308B repo",
|
|
1925
|
+
tableHeader: "| repo | \u53EF\u8996\u6027 | \u8A00\u8A9E | \u6307\u793A\u66F8 |",
|
|
1926
|
+
instructionsAnchor: "anchor(\u624B\u7BA1\u7406)",
|
|
1927
|
+
instructionsSelf: "self(repo \u304C\u81EA\u5DF1\u7BA1\u7406)",
|
|
1928
|
+
instructionsHub: "hub(basou \u304C\u751F\u6210)",
|
|
1929
|
+
unsetShort: "\u672A\u8A2D\u5B9A",
|
|
1930
|
+
commitHeading: "### \u3069\u3053\u3067 commit \u3059\u308B\u304B",
|
|
1931
|
+
commitBody: "view \u3067\u306F commit \u3067\u304D\u307E\u305B\u3093(git \u7BA1\u7406\u5916)\u3002\u5909\u66F4\u306F\u5FC5\u305A\u5B9F\u4F53\u306E repo \u306B `cd` \u3057\u3066\u304B\u3089 commit \u3057\u3066\u304F\u3060\u3055\u3044\u3002",
|
|
1932
|
+
conventionsHeading: "### \u5FC5\u305A\u8AAD\u3080\u3079\u304D\u898F\u7D04",
|
|
1933
|
+
conventionsBody: "\u4F5C\u696D\u898F\u7D04\u306F\u5404 repo \u306E AGENTS.md \u306B\u3042\u308A\u307E\u3059\u3002\u4EE5\u4E0B\u3092\u8AAD\u3093\u3067\u304B\u3089\u4F5C\u696D\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
|
|
1934
|
+
principlesHeading: "### \u91CD\u8981\u539F\u5247",
|
|
1935
|
+
principleStateless: "- \u3053\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306F\u72B6\u614B\u3092\u6301\u305F\u306A\u3044(git \u7BA1\u7406\u5916)",
|
|
1936
|
+
principleNoFiles: "- \u91CD\u8981\u306A\u30D5\u30A1\u30A4\u30EB\u3092\u3053\u3053\u306B\u76F4\u63A5\u7F6E\u304B\u306A\u3044(\u5B9F\u4F53\u306F\u5404 repo \u306B\u7F6E\u304F)"
|
|
1937
|
+
},
|
|
1938
|
+
anchorStarter: {
|
|
1939
|
+
identityLine: (title) => `> \u3053\u306E\u30EA\u30DD\u30B8\u30C8\u30EA\u306F **${title} \u306E planning master(anchor)** \u3067\u3059\u3002\u3053\u3053\u3067\u4F5C\u696D\u3059\u308B AI \u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u306F\u3001\u307E\u305A\u3053\u306E\u30D5\u30A1\u30A4\u30EB\u3092\u8AAD\u3093\u3067\u304F\u3060\u3055\u3044\u3002`,
|
|
1940
|
+
starterNote: "> \u3053\u306E\u30D5\u30A1\u30A4\u30EB\u306F `basou project derive` \u304C greenfield \u7ACB\u3061\u4E0A\u3052\u6642\u306B **\u4E00\u5EA6\u3060\u3051\u751F\u6210\u3057\u305F starter** \u3067\u3059\u3002\u4EE5\u5F8C\u306F\u624B\u7BA1\u7406\u3057\u3066\u304F\u3060\u3055\u3044 \u2014 basou \u306F\u518D\u751F\u6210\u3082\u4E0A\u66F8\u304D\u3082\u3057\u307E\u305B\u3093(BASOU:GENERATED \u30DE\u30FC\u30AB\u30FC\u306F\u7121\u304F\u3001\u81EA\u7531\u306B\u7DE8\u96C6\u3067\u304D\u307E\u3059)\u3002",
|
|
1941
|
+
basicsHeading: "## \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u306E\u57FA\u672C\u60C5\u5831",
|
|
1942
|
+
basicsTodo: "<!-- TODO: manifest \u304B\u3089\u306F\u5C0E\u51FA\u3067\u304D\u306A\u3044\u9805\u76EE\u3067\u3059\u3002\u57CB\u3081\u3066\u304F\u3060\u3055\u3044\u3002 -->",
|
|
1943
|
+
commitHeading: "## \u3069\u3053\u3067 commit \u3059\u308B\u304B",
|
|
1944
|
+
commitPlanning: "- **\u3053\u306E\u30EA\u30DD\u30B8\u30C8\u30EA(planning master)**: \u69CB\u60F3\u30FB\u8A08\u753B\u30FB\u8A2D\u8A08\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u3002",
|
|
1945
|
+
commitImplementation: "- **\u5404\u5B9F\u88C5 repo**: \u5B9F\u88C5\u30B3\u30FC\u30C9\u3002\u5FC5\u305A\u5BFE\u8C61 repo \u306B `cd` \u3057\u3066\u304B\u3089 commit \u3057\u3066\u304F\u3060\u3055\u3044\u3002",
|
|
1946
|
+
commitView: "- **workspace view**: git \u7BA1\u7406\u5916\u3002view \u3067\u306F commit \u3067\u304D\u307E\u305B\u3093\u3002",
|
|
1947
|
+
conventionsHeading: "## \u5FC5\u305A\u8AAD\u3080\u3079\u304D\u898F\u7D04",
|
|
1948
|
+
conventionsBody: "\u4F5C\u696D\u898F\u7D04\u306F\u5404 repo \u306E AGENTS.md \u306B\u3042\u308A\u307E\u3059\u3002\u4EE5\u4E0B\u3092\u8AAD\u3093\u3067\u304B\u3089\u4F5C\u696D\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
|
|
1949
|
+
viewPointerLine: (viewName) => `- ${viewName}/AGENTS.md(workspace view\u30FBbasou \u304C\u751F\u6210)\u2014 **\u6700\u65B0\u306E repo \u69CB\u6210(roster)\u306F\u3053\u3053\u3092\u6B63\u3068\u3059\u308B**`,
|
|
1950
|
+
policyHeading: "## \u4F5C\u696D\u65B9\u91DD(\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u56FA\u6709\u4E8B\u9805)",
|
|
1951
|
+
policyTodo: [
|
|
1952
|
+
"<!-- TODO: \u4EE5\u4E0B\u3092\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u306B\u5408\u308F\u305B\u3066\u8A18\u8FF0\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
|
|
1953
|
+
" - \u73FE\u5728\u306E\u30D5\u30A7\u30FC\u30BA / \u91CD\u8981\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8",
|
|
1954
|
+
" - \u6A5F\u5BC6\u60C5\u5831\u306E\u6271\u3044(\u3069\u3053\u306B\u66F8\u304B\u306A\u3044\u304B)",
|
|
1955
|
+
" - \u8A00\u8A9E\u30DD\u30EA\u30B7\u30FC(commit / \u30B3\u30E1\u30F3\u30C8 / \u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u306E\u8A00\u8A9E)",
|
|
1956
|
+
" - commit \u904B\u7528(\u6DF7\u5728\u30B3\u30DF\u30C3\u30C8\u3092\u907F\u3051\u308B \u7B49)",
|
|
1957
|
+
"-->"
|
|
1958
|
+
]
|
|
1959
|
+
}
|
|
1960
|
+
};
|
|
1961
|
+
|
|
1370
1962
|
// src/storage/sessions.ts
|
|
1371
1963
|
import { readdir as readdir2 } from "fs/promises";
|
|
1372
1964
|
import { join as join5 } from "path";
|
|
@@ -1573,8 +2165,8 @@ async function appendChainedEvent(paths, sessionId, event) {
|
|
|
1573
2165
|
}
|
|
1574
2166
|
|
|
1575
2167
|
// src/schemas/session.schema.ts
|
|
1576
|
-
import { z as
|
|
1577
|
-
var SessionStatusSchema =
|
|
2168
|
+
import { z as z5 } from "zod";
|
|
2169
|
+
var SessionStatusSchema = z5.enum([
|
|
1578
2170
|
"initialized",
|
|
1579
2171
|
"running",
|
|
1580
2172
|
"waiting_approval",
|
|
@@ -1584,7 +2176,7 @@ var SessionStatusSchema = z4.enum([
|
|
|
1584
2176
|
"imported",
|
|
1585
2177
|
"archived"
|
|
1586
2178
|
]);
|
|
1587
|
-
var SessionSourceKindSchema =
|
|
2179
|
+
var SessionSourceKindSchema = z5.enum([
|
|
1588
2180
|
"claude-code-adapter",
|
|
1589
2181
|
"claude-code-import",
|
|
1590
2182
|
"codex-adapter",
|
|
@@ -1593,13 +2185,13 @@ var SessionSourceKindSchema = z4.enum([
|
|
|
1593
2185
|
"import",
|
|
1594
2186
|
"terminal"
|
|
1595
2187
|
]);
|
|
1596
|
-
var SessionSourceSchema =
|
|
2188
|
+
var SessionSourceSchema = z5.looseObject({
|
|
1597
2189
|
kind: SessionSourceKindSchema,
|
|
1598
|
-
version:
|
|
2190
|
+
version: z5.literal("0.1.0"),
|
|
1599
2191
|
// Optional id of the originating session in the SOURCE tool's own
|
|
1600
2192
|
// namespace (e.g. the Claude Code session UUID for a `claude-code-import`).
|
|
1601
2193
|
// Lets re-imports of the same source be deduplicated; absent for live runs.
|
|
1602
|
-
external_id:
|
|
2194
|
+
external_id: z5.string().optional(),
|
|
1603
2195
|
// Byte size of the source native log at import time, recorded so a later
|
|
1604
2196
|
// import can detect that an append-only transcript GREW and re-import it
|
|
1605
2197
|
// (scoped, preserving the session id) instead of skipping it as already
|
|
@@ -1607,33 +2199,33 @@ var SessionSourceSchema = z4.looseObject({
|
|
|
1607
2199
|
// external_id, metrics). Absent on sessions imported before this field
|
|
1608
2200
|
// existed (treated as legacy: never auto-re-imported, populated on the next
|
|
1609
2201
|
// fresh import or `--force`).
|
|
1610
|
-
source_size_bytes:
|
|
2202
|
+
source_size_bytes: z5.number().int().nonnegative().optional()
|
|
1611
2203
|
});
|
|
1612
|
-
var InvocationSchema =
|
|
1613
|
-
command:
|
|
1614
|
-
args:
|
|
2204
|
+
var InvocationSchema = z5.looseObject({
|
|
2205
|
+
command: z5.string().min(1),
|
|
2206
|
+
args: z5.array(z5.string()).default([]),
|
|
1615
2207
|
// Nullable to record signal-terminated runs where the child has no exit
|
|
1616
2208
|
// code; the same nullability is mirrored in CommandExecutedEventSchema.
|
|
1617
|
-
exit_code:
|
|
2209
|
+
exit_code: z5.number().int().nullable()
|
|
1618
2210
|
});
|
|
1619
|
-
var SessionMetricsSchema =
|
|
1620
|
-
output_tokens:
|
|
1621
|
-
input_tokens:
|
|
1622
|
-
cached_input_tokens:
|
|
1623
|
-
reasoning_output_tokens:
|
|
1624
|
-
active_time_ms:
|
|
1625
|
-
active_intervals:
|
|
1626
|
-
active_gap_cap_ms:
|
|
1627
|
-
active_time_method:
|
|
1628
|
-
machine_active_time_ms:
|
|
2211
|
+
var SessionMetricsSchema = z5.looseObject({
|
|
2212
|
+
output_tokens: z5.number().int().nonnegative().optional(),
|
|
2213
|
+
input_tokens: z5.number().int().nonnegative().optional(),
|
|
2214
|
+
cached_input_tokens: z5.number().int().nonnegative().optional(),
|
|
2215
|
+
reasoning_output_tokens: z5.number().int().nonnegative().optional(),
|
|
2216
|
+
active_time_ms: z5.number().int().nonnegative().optional(),
|
|
2217
|
+
active_intervals: z5.array(z5.looseObject({ start: IsoTimestampSchema, end: IsoTimestampSchema })).optional(),
|
|
2218
|
+
active_gap_cap_ms: z5.number().int().nonnegative().optional(),
|
|
2219
|
+
active_time_method: z5.string().optional(),
|
|
2220
|
+
machine_active_time_ms: z5.number().int().nonnegative().optional()
|
|
1629
2221
|
});
|
|
1630
|
-
var SessionIntegritySchema =
|
|
1631
|
-
head_hash:
|
|
1632
|
-
event_count:
|
|
2222
|
+
var SessionIntegritySchema = z5.object({
|
|
2223
|
+
head_hash: z5.string(),
|
|
2224
|
+
event_count: z5.number().int().nonnegative()
|
|
1633
2225
|
}).strict();
|
|
1634
|
-
var SessionInnerSchema =
|
|
2226
|
+
var SessionInnerSchema = z5.looseObject({
|
|
1635
2227
|
id: SessionIdSchema,
|
|
1636
|
-
label:
|
|
2228
|
+
label: z5.string().optional(),
|
|
1637
2229
|
task_id: TaskIdSchema.nullable().optional(),
|
|
1638
2230
|
workspace_id: WorkspaceIdSchema,
|
|
1639
2231
|
source: SessionSourceSchema,
|
|
@@ -1641,15 +2233,15 @@ var SessionInnerSchema = z4.looseObject({
|
|
|
1641
2233
|
// ended_at is optional because initialized / running sessions have no end time yet.
|
|
1642
2234
|
ended_at: IsoTimestampSchema.optional(),
|
|
1643
2235
|
status: SessionStatusSchema,
|
|
1644
|
-
working_directory:
|
|
2236
|
+
working_directory: z5.string().min(1),
|
|
1645
2237
|
invocation: InvocationSchema,
|
|
1646
|
-
related_files:
|
|
1647
|
-
events_log:
|
|
1648
|
-
summary:
|
|
2238
|
+
related_files: z5.array(z5.string()).default([]),
|
|
2239
|
+
events_log: z5.string().default("events.jsonl"),
|
|
2240
|
+
summary: z5.string().nullable().optional(),
|
|
1649
2241
|
metrics: SessionMetricsSchema.optional(),
|
|
1650
2242
|
integrity: SessionIntegritySchema.optional()
|
|
1651
2243
|
});
|
|
1652
|
-
var SessionSchema =
|
|
2244
|
+
var SessionSchema = z5.looseObject({
|
|
1653
2245
|
schema_version: SchemaVersionSchema,
|
|
1654
2246
|
session: SessionInnerSchema
|
|
1655
2247
|
});
|
|
@@ -1855,7 +2447,7 @@ async function renderDecisions(input) {
|
|
|
1855
2447
|
const abs = resolve(repoRoot, relPath);
|
|
1856
2448
|
let exists;
|
|
1857
2449
|
try {
|
|
1858
|
-
await
|
|
2450
|
+
await lstat2(abs);
|
|
1859
2451
|
exists = true;
|
|
1860
2452
|
} catch {
|
|
1861
2453
|
exists = false;
|
|
@@ -1863,7 +2455,9 @@ async function renderDecisions(input) {
|
|
|
1863
2455
|
fileExistenceCache.set(relPath, exists);
|
|
1864
2456
|
return exists;
|
|
1865
2457
|
}
|
|
2458
|
+
const language = input.language ?? await resolveViewLanguageFromPaths(input.paths);
|
|
1866
2459
|
const body = await formatDecisionsBody({
|
|
2460
|
+
language,
|
|
1867
2461
|
nowIso: input.nowIso,
|
|
1868
2462
|
decisions,
|
|
1869
2463
|
knownEventIds,
|
|
@@ -1872,6 +2466,7 @@ async function renderDecisions(input) {
|
|
|
1872
2466
|
return { body, decisionCount: decisions.length };
|
|
1873
2467
|
}
|
|
1874
2468
|
async function formatDecisionsBody(args) {
|
|
2469
|
+
const t = viewStrings(args.language);
|
|
1875
2470
|
const lines = [];
|
|
1876
2471
|
lines.push("# Decisions");
|
|
1877
2472
|
lines.push("");
|
|
@@ -1894,12 +2489,12 @@ async function formatDecisionsBody(args) {
|
|
|
1894
2489
|
lines.push("");
|
|
1895
2490
|
}
|
|
1896
2491
|
const occurredDate = d.occurredAt.slice(0, 10);
|
|
1897
|
-
lines.push(`-
|
|
2492
|
+
lines.push(`- ${t.decisions.dateLabel}: ${occurredDate}`);
|
|
1898
2493
|
if (d.kind === "track" && d.voided === void 0) {
|
|
1899
|
-
lines.push(
|
|
2494
|
+
lines.push(t.decisions.trackKindLine);
|
|
1900
2495
|
}
|
|
1901
2496
|
lines.push(`- session: ${shortDecisionSessionId(d.sessionId)}`);
|
|
1902
|
-
lines.push(`-
|
|
2497
|
+
lines.push(`- ${t.decisions.decisionLabel}: ${d.title}`);
|
|
1903
2498
|
if (typeof d.rationale === "string" && d.rationale.length > 0) {
|
|
1904
2499
|
lines.push(`- rationale: ${d.rationale}`);
|
|
1905
2500
|
}
|
|
@@ -2147,27 +2742,27 @@ import { simpleGit } from "simple-git";
|
|
|
2147
2742
|
import * as fsp from "fs/promises";
|
|
2148
2743
|
|
|
2149
2744
|
// src/schemas/status.schema.ts
|
|
2150
|
-
import { z as
|
|
2151
|
-
var StatusSchema =
|
|
2745
|
+
import { z as z6 } from "zod";
|
|
2746
|
+
var StatusSchema = z6.object({
|
|
2152
2747
|
// status.json is a rebuildable cache: exact-match-or-rebuild, not the
|
|
2153
2748
|
// durable forward-compat gate.
|
|
2154
2749
|
schema_version: CacheVersionSchema,
|
|
2155
2750
|
generated_at: IsoTimestampSchema,
|
|
2156
|
-
workspace:
|
|
2751
|
+
workspace: z6.object({
|
|
2157
2752
|
id: WorkspaceIdSchema,
|
|
2158
|
-
name:
|
|
2753
|
+
name: z6.string().min(1),
|
|
2159
2754
|
// Mirrors the manifest's basou_version, so it uses the same
|
|
2160
2755
|
// forward-compatible format gate (accept 0.x.y) rather than a literal.
|
|
2161
2756
|
basou_version: SchemaVersionSchema
|
|
2162
2757
|
}).strict(),
|
|
2163
|
-
directories_present:
|
|
2164
|
-
sessions:
|
|
2165
|
-
tasks:
|
|
2166
|
-
approvals_pending:
|
|
2167
|
-
approvals_resolved:
|
|
2168
|
-
logs:
|
|
2169
|
-
raw:
|
|
2170
|
-
tmp:
|
|
2758
|
+
directories_present: z6.object({
|
|
2759
|
+
sessions: z6.boolean(),
|
|
2760
|
+
tasks: z6.boolean(),
|
|
2761
|
+
approvals_pending: z6.boolean(),
|
|
2762
|
+
approvals_resolved: z6.boolean(),
|
|
2763
|
+
logs: z6.boolean(),
|
|
2764
|
+
raw: z6.boolean(),
|
|
2765
|
+
tmp: z6.boolean()
|
|
2171
2766
|
}).strict()
|
|
2172
2767
|
}).strict();
|
|
2173
2768
|
|
|
@@ -2186,7 +2781,7 @@ async function assertBasouRootSafe(rootPath) {
|
|
|
2186
2781
|
try {
|
|
2187
2782
|
stat4 = await fsp.lstat(rootPath);
|
|
2188
2783
|
} catch (error) {
|
|
2189
|
-
if (
|
|
2784
|
+
if (hasErrorCode3(error) && error.code === "ENOENT") {
|
|
2190
2785
|
throw new Error("Basou workspace not found", { cause: error });
|
|
2191
2786
|
}
|
|
2192
2787
|
throw new Error("Failed to inspect .basou root", { cause: error });
|
|
@@ -2202,7 +2797,7 @@ async function dirPresent(path2) {
|
|
|
2202
2797
|
try {
|
|
2203
2798
|
return (await fsp.lstat(path2)).isDirectory();
|
|
2204
2799
|
} catch (error) {
|
|
2205
|
-
if (
|
|
2800
|
+
if (hasErrorCode3(error) && (error.code === "ENOENT" || error.code === "ENOTDIR")) {
|
|
2206
2801
|
return false;
|
|
2207
2802
|
}
|
|
2208
2803
|
throw new Error("Failed to inspect .basou subdirectory", { cause: error });
|
|
@@ -2243,7 +2838,7 @@ async function readStatus(paths) {
|
|
|
2243
2838
|
try {
|
|
2244
2839
|
body = await fsp.readFile(paths.files.status, "utf8");
|
|
2245
2840
|
} catch (error) {
|
|
2246
|
-
if (
|
|
2841
|
+
if (hasErrorCode3(error) && error.code === "ENOENT") {
|
|
2247
2842
|
throw new Error("Status file not found", { cause: error });
|
|
2248
2843
|
}
|
|
2249
2844
|
throw new Error("Failed to read status file", { cause: error });
|
|
@@ -2256,7 +2851,7 @@ async function readStatus(paths) {
|
|
|
2256
2851
|
}
|
|
2257
2852
|
return StatusSchema.parse(parsed);
|
|
2258
2853
|
}
|
|
2259
|
-
function
|
|
2854
|
+
function hasErrorCode3(error) {
|
|
2260
2855
|
if (!(error instanceof Error)) return false;
|
|
2261
2856
|
return typeof error.code === "string";
|
|
2262
2857
|
}
|
|
@@ -2513,15 +3108,15 @@ import { createHash as createHash2 } from "crypto";
|
|
|
2513
3108
|
import { mkdir as mkdir3, readdir as readdir4, readFile as readFile7, rename as rename2, stat as stat3, unlink as unlink3 } from "fs/promises";
|
|
2514
3109
|
import { join as join12 } from "path";
|
|
2515
3110
|
import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
|
|
2516
|
-
import { z as
|
|
3111
|
+
import { z as z9 } from "zod";
|
|
2517
3112
|
|
|
2518
3113
|
// src/schemas/task.schema.ts
|
|
2519
|
-
import { z as
|
|
2520
|
-
var TaskStatusSchema =
|
|
2521
|
-
var TaskInnerSchema =
|
|
3114
|
+
import { z as z7 } from "zod";
|
|
3115
|
+
var TaskStatusSchema = z7.enum(["planned", "in_progress", "done", "cancelled"]);
|
|
3116
|
+
var TaskInnerSchema = z7.looseObject({
|
|
2522
3117
|
id: TaskIdSchema,
|
|
2523
|
-
title:
|
|
2524
|
-
label:
|
|
3118
|
+
title: z7.string().min(1),
|
|
3119
|
+
label: z7.string().min(1).optional(),
|
|
2525
3120
|
status: TaskStatusSchema,
|
|
2526
3121
|
created_at: IsoTimestampSchema,
|
|
2527
3122
|
updated_at: IsoTimestampSchema,
|
|
@@ -2545,9 +3140,9 @@ var TaskInnerSchema = z6.looseObject({
|
|
|
2545
3140
|
* task.md and immediately see related sessions. Defaults to `[]` for
|
|
2546
3141
|
* backward compatibility.
|
|
2547
3142
|
*/
|
|
2548
|
-
linked_sessions:
|
|
3143
|
+
linked_sessions: z7.array(SessionIdSchema).default([])
|
|
2549
3144
|
});
|
|
2550
|
-
var TaskSchema =
|
|
3145
|
+
var TaskSchema = z7.looseObject({
|
|
2551
3146
|
schema_version: SchemaVersionSchema,
|
|
2552
3147
|
task: TaskInnerSchema
|
|
2553
3148
|
});
|
|
@@ -2789,17 +3384,17 @@ import { readFile as readFile6 } from "fs/promises";
|
|
|
2789
3384
|
import { join as join11 } from "path";
|
|
2790
3385
|
|
|
2791
3386
|
// src/schemas/task-index.schema.ts
|
|
2792
|
-
import { z as
|
|
2793
|
-
var TaskIndexEntrySchema =
|
|
3387
|
+
import { z as z8 } from "zod";
|
|
3388
|
+
var TaskIndexEntrySchema = z8.object({
|
|
2794
3389
|
id: TaskIdSchema,
|
|
2795
3390
|
status: TaskStatusSchema,
|
|
2796
|
-
label:
|
|
3391
|
+
label: z8.string().min(1).optional(),
|
|
2797
3392
|
updated_at: IsoTimestampSchema
|
|
2798
3393
|
}).strict();
|
|
2799
|
-
var TaskIndexSchema =
|
|
3394
|
+
var TaskIndexSchema = z8.object({
|
|
2800
3395
|
// Rebuildable cache: exact-match-or-rebuild, not the durable forward-compat gate.
|
|
2801
3396
|
schema_version: CacheVersionSchema,
|
|
2802
|
-
tasks:
|
|
3397
|
+
tasks: z8.array(TaskIndexEntrySchema),
|
|
2803
3398
|
last_rebuilt_at: IsoTimestampSchema
|
|
2804
3399
|
}).strict();
|
|
2805
3400
|
var TASK_INDEX_SCHEMA_VERSION = "0.1.0";
|
|
@@ -2885,8 +3480,8 @@ var DEFAULT_ATTACHABLE_STATUSES2 = /* @__PURE__ */ new Set([
|
|
|
2885
3480
|
"waiting_approval"
|
|
2886
3481
|
]);
|
|
2887
3482
|
var InitialTaskStatusSchema = TaskStatusSchema;
|
|
2888
|
-
var TaskTitleSchema =
|
|
2889
|
-
var TaskLabelSchema =
|
|
3483
|
+
var TaskTitleSchema = z9.string().min(1);
|
|
3484
|
+
var TaskLabelSchema = z9.string().min(1);
|
|
2890
3485
|
var CompletedAtSchema = IsoTimestampSchema;
|
|
2891
3486
|
var TERMINAL_TASK_STATUSES = /* @__PURE__ */ new Set(["done", "cancelled"]);
|
|
2892
3487
|
function isTerminalTaskStatus(status) {
|
|
@@ -4335,7 +4930,9 @@ async function renderHandoff(input) {
|
|
|
4335
4930
|
const firstEntry = entries[0];
|
|
4336
4931
|
const lastEntry = entries[entries.length - 1];
|
|
4337
4932
|
const sessionRange = firstEntry !== void 0 && lastEntry !== void 0 ? `${shortIdWithPrefix(firstEntry.sessionId)}..${shortIdWithPrefix(lastEntry.sessionId)}` : "";
|
|
4933
|
+
const language = input.language ?? await resolveViewLanguageFromPaths(input.paths);
|
|
4338
4934
|
const body = formatHandoffBody({
|
|
4935
|
+
language,
|
|
4339
4936
|
nowIso: input.nowIso,
|
|
4340
4937
|
sessionRange,
|
|
4341
4938
|
sessionCount: entries.length,
|
|
@@ -4365,6 +4962,7 @@ async function renderHandoff(input) {
|
|
|
4365
4962
|
};
|
|
4366
4963
|
}
|
|
4367
4964
|
function formatHandoffBody(args) {
|
|
4965
|
+
const t = viewStrings(args.language);
|
|
4368
4966
|
const lines = [];
|
|
4369
4967
|
lines.push("# Handoff");
|
|
4370
4968
|
lines.push("");
|
|
@@ -4374,32 +4972,32 @@ function formatHandoffBody(args) {
|
|
|
4374
4972
|
lines.push(`> Generated at ${args.nowIso}`);
|
|
4375
4973
|
}
|
|
4376
4974
|
lines.push("");
|
|
4377
|
-
lines.push(
|
|
4975
|
+
lines.push(t.handoff.headingCurrentState);
|
|
4378
4976
|
lines.push("");
|
|
4379
4977
|
if (args.latestSession !== void 0) {
|
|
4380
4978
|
const status = args.latestSession.session.session.status;
|
|
4381
4979
|
const label = args.latestSession.session.session.label;
|
|
4382
4980
|
const shortId2 = shortIdWithPrefix(args.latestSession.sessionId);
|
|
4383
4981
|
if (label !== void 0 && label !== "") {
|
|
4384
|
-
lines.push(`-
|
|
4982
|
+
lines.push(`- ${t.common.lastSessionLabel}: ${label} (${status}) [${shortId2}]`);
|
|
4385
4983
|
} else {
|
|
4386
|
-
lines.push(`-
|
|
4984
|
+
lines.push(`- ${t.common.lastSessionLabel}: ${shortId2} (${status})`);
|
|
4387
4985
|
}
|
|
4388
4986
|
} else {
|
|
4389
|
-
lines.push(
|
|
4987
|
+
lines.push(`- ${t.common.lastSessionLabel}: (no live sessions)`);
|
|
4390
4988
|
}
|
|
4391
4989
|
if (args.latestActivityRecord !== void 0) {
|
|
4392
4990
|
const statusLabel = args.latestTaskDoc !== void 0 ? args.latestTaskDoc.task.task.status : "status unknown \u2014 task.md missing or invalid";
|
|
4393
4991
|
const linkedCount = args.latestTaskDoc?.task.task.linked_sessions?.length;
|
|
4394
4992
|
const linkedSuffix = linkedCount !== void 0 && linkedCount > 1 ? `, linked_sessions: ${linkedCount}` : "";
|
|
4395
4993
|
lines.push(
|
|
4396
|
-
`-
|
|
4994
|
+
`- ${t.handoff.lastTaskLabel}: ${args.latestActivityRecord.title} (${statusLabel}${linkedSuffix}) [${shortIdWithPrefix(args.latestActivityRecord.taskId)}]`
|
|
4397
4995
|
);
|
|
4398
4996
|
} else {
|
|
4399
|
-
lines.push(
|
|
4997
|
+
lines.push(`- ${t.handoff.lastTaskLabel}: (no tasks recorded yet)`);
|
|
4400
4998
|
}
|
|
4401
4999
|
lines.push("");
|
|
4402
|
-
lines.push(
|
|
5000
|
+
lines.push(t.handoff.headingRecentFiles);
|
|
4403
5001
|
lines.push("");
|
|
4404
5002
|
if (args.displayedFiles.length === 0) {
|
|
4405
5003
|
lines.push("(no related files recorded)");
|
|
@@ -4408,7 +5006,7 @@ function formatHandoffBody(args) {
|
|
|
4408
5006
|
if (args.overflow > 0) lines.push(`- ... +${args.overflow} more`);
|
|
4409
5007
|
}
|
|
4410
5008
|
lines.push("");
|
|
4411
|
-
lines.push(
|
|
5009
|
+
lines.push(t.handoff.headingLatestDecision);
|
|
4412
5010
|
lines.push("");
|
|
4413
5011
|
if (args.latestDecision === void 0) {
|
|
4414
5012
|
lines.push("(no decisions recorded yet)");
|
|
@@ -4416,14 +5014,10 @@ function formatHandoffBody(args) {
|
|
|
4416
5014
|
const last = args.latestDecision;
|
|
4417
5015
|
lines.push(`- ${last.title} [${shortIdWithPrefix(last.decisionId)}]`);
|
|
4418
5016
|
if (args.latestActivityAt !== null && isTrailingStale(args.latestActivityAt, last.occurredAt)) {
|
|
4419
|
-
lines.push(
|
|
4420
|
-
" - \u6CE8: \u6700\u7D42\u6D3B\u52D5\u306F\u3053\u306E\u5224\u65AD\u3088\u308A\u5F8C\u3067\u3059\u3002\u4F1A\u8A71\u3067\u65E2\u306B\u89E3\u6C7A\u6E08\u307F\u306E\u53EF\u80FD\u6027\u304C\u3042\u308B\u305F\u3081\u3001\u518D\u958B\u524D\u306B\u7D99\u7D9A\u70B9\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044(\u4F1A\u8A71\u3067\u306E\u610F\u601D\u6C7A\u5B9A\u306F\u81EA\u52D5\u8A18\u9332\u3055\u308C\u307E\u305B\u3093\u3002`basou decision capture` \u3067\u8A18\u9332\u3067\u304D\u307E\u3059)\u3002"
|
|
4421
|
-
);
|
|
5017
|
+
lines.push(` - ${t.handoff.decisionStaleNote}`);
|
|
4422
5018
|
}
|
|
4423
5019
|
if (args.latestSession !== void 0 && last.sessionId !== args.latestSession.sessionId) {
|
|
4424
|
-
lines.push(
|
|
4425
|
-
` - \u6CE8: \u3053\u306E\u5224\u65AD\u306F\u6700\u7D42 session \u3068\u306F\u5225\u306E session [${shortIdWithPrefix(last.sessionId)}] \u306E\u3082\u306E\u3067\u3059\u3002`
|
|
4426
|
-
);
|
|
5020
|
+
lines.push(` - ${t.common.decisionOtherSessionNote(shortIdWithPrefix(last.sessionId))}`);
|
|
4427
5021
|
}
|
|
4428
5022
|
lines.push("");
|
|
4429
5023
|
lines.push(`(${args.decisions.length} decisions total \u2014 see decisions.md)`);
|
|
@@ -4433,20 +5027,20 @@ function formatHandoffBody(args) {
|
|
|
4433
5027
|
const TRACK_DISPLAY_LIMIT = 10;
|
|
4434
5028
|
const shown = args.openTracks.slice(0, TRACK_DISPLAY_LIMIT);
|
|
4435
5029
|
const overflow = args.openTracks.length - shown.length;
|
|
4436
|
-
lines.push(
|
|
5030
|
+
lines.push(t.handoff.headingOpenTracks);
|
|
4437
5031
|
lines.push("");
|
|
4438
|
-
for (const
|
|
4439
|
-
lines.push(`- ${
|
|
4440
|
-
if (
|
|
4441
|
-
lines.push(` -
|
|
5032
|
+
for (const track of shown) {
|
|
5033
|
+
lines.push(`- ${track.title} [${shortIdWithPrefix(track.decisionId)}]`);
|
|
5034
|
+
if (track.rationale !== null && track.rationale.trim() !== "") {
|
|
5035
|
+
lines.push(` - ${t.common.trackWhyLabel}: ${handoffRationale(track.rationale)}`);
|
|
4442
5036
|
}
|
|
4443
5037
|
}
|
|
4444
5038
|
if (overflow > 0) lines.push(`- ... +${overflow} more (see decisions.md)`);
|
|
4445
5039
|
lines.push("");
|
|
4446
|
-
lines.push(
|
|
5040
|
+
lines.push(t.handoff.trackCloseInstruction);
|
|
4447
5041
|
lines.push("");
|
|
4448
5042
|
}
|
|
4449
|
-
lines.push(
|
|
5043
|
+
lines.push(t.handoff.headingUnresolved);
|
|
4450
5044
|
lines.push("");
|
|
4451
5045
|
if (args.pendingApprovalsCount > 0) {
|
|
4452
5046
|
lines.push(`- ${args.pendingApprovalsCount} pending approvals`);
|
|
@@ -4458,19 +5052,19 @@ function formatHandoffBody(args) {
|
|
|
4458
5052
|
lines.push("(none)");
|
|
4459
5053
|
}
|
|
4460
5054
|
lines.push("");
|
|
4461
|
-
lines.push(
|
|
5055
|
+
lines.push(t.handoff.headingReadNext);
|
|
4462
5056
|
lines.push("");
|
|
4463
5057
|
lines.push("- .basou/decisions.md");
|
|
4464
5058
|
for (const f of args.displayedFiles.slice(0, 3)) lines.push(`- ${f}`);
|
|
4465
5059
|
lines.push("");
|
|
4466
|
-
lines.push(
|
|
5060
|
+
lines.push(t.handoff.headingNextWork);
|
|
4467
5061
|
lines.push("");
|
|
4468
5062
|
if (args.pendingTasks.length === 0) {
|
|
4469
5063
|
lines.push("(no pending tasks)");
|
|
4470
5064
|
} else {
|
|
4471
|
-
for (const
|
|
5065
|
+
for (const t2 of args.pendingTasks) {
|
|
4472
5066
|
lines.push(
|
|
4473
|
-
`- ${
|
|
5067
|
+
`- ${t2.task.task.title} (${t2.task.task.status}) [${shortIdWithPrefix(t2.task.task.id)}]`
|
|
4474
5068
|
);
|
|
4475
5069
|
}
|
|
4476
5070
|
}
|
|
@@ -4479,7 +5073,7 @@ function formatHandoffBody(args) {
|
|
|
4479
5073
|
const importedTableEntries = args.entries.filter(
|
|
4480
5074
|
(e) => e.session.session.source.kind === "import"
|
|
4481
5075
|
);
|
|
4482
|
-
lines.push(
|
|
5076
|
+
lines.push(t.handoff.headingSessions);
|
|
4483
5077
|
lines.push("");
|
|
4484
5078
|
if (args.entries.length === 0) {
|
|
4485
5079
|
lines.push("(no sessions yet)");
|
|
@@ -4728,157 +5322,6 @@ async function classifyFilesBySourceRoot(input) {
|
|
|
4728
5322
|
|
|
4729
5323
|
// src/orientation/orientation-renderer.ts
|
|
4730
5324
|
import { dirname as dirname4, join as join15 } from "path";
|
|
4731
|
-
|
|
4732
|
-
// src/storage/manifest.ts
|
|
4733
|
-
import { lstat as lstat3 } from "fs/promises";
|
|
4734
|
-
|
|
4735
|
-
// src/schemas/manifest.schema.ts
|
|
4736
|
-
import { z as z9 } from "zod";
|
|
4737
|
-
var ProjectSchema = z9.looseObject({
|
|
4738
|
-
name: z9.string().optional(),
|
|
4739
|
-
description: z9.string().optional()
|
|
4740
|
-
});
|
|
4741
|
-
var CapabilitiesSchema = z9.looseObject({
|
|
4742
|
-
enabled: z9.array(z9.string())
|
|
4743
|
-
});
|
|
4744
|
-
var ApprovalConfigSchema = z9.looseObject({
|
|
4745
|
-
required_for: z9.array(z9.string()).optional(),
|
|
4746
|
-
default_risk_level: z9.enum(["low", "medium", "high", "critical"])
|
|
4747
|
-
});
|
|
4748
|
-
var ClaudeCodeAdapterConfigSchema = z9.looseObject({
|
|
4749
|
-
enabled: z9.boolean(),
|
|
4750
|
-
config_path: z9.string().optional()
|
|
4751
|
-
});
|
|
4752
|
-
var AdaptersSchema = z9.looseObject({
|
|
4753
|
-
"claude-code": ClaudeCodeAdapterConfigSchema
|
|
4754
|
-
});
|
|
4755
|
-
var GitConfigSchema = z9.looseObject({
|
|
4756
|
-
events_log: z9.enum(["ignore", "commit"]).default("ignore")
|
|
4757
|
-
});
|
|
4758
|
-
var SOURCE_ROOT_PATTERN = /^(?![~/\\])(?![A-Za-z]:)(?!\s)[^\0\\]*[^\0\\\s]$/;
|
|
4759
|
-
var SourceRootSchema = z9.string().min(1).regex(SOURCE_ROOT_PATTERN, {
|
|
4760
|
-
message: "source_roots entries must be relative paths (no absolute path, '~', '\\', or null byte)"
|
|
4761
|
-
});
|
|
4762
|
-
var ImportConfigSchema = z9.looseObject({
|
|
4763
|
-
source_roots: z9.array(SourceRootSchema).min(1).optional()
|
|
4764
|
-
});
|
|
4765
|
-
var RepoVisibilitySchema = z9.enum(["public", "private", "future-public"]);
|
|
4766
|
-
var RepoLanguageSchema = z9.enum(["en", "ja", "en+ja"]);
|
|
4767
|
-
var PublishKindSchema = z9.enum(["web", "npm"]);
|
|
4768
|
-
var RepoInstructionsSchema = z9.enum(["hub", "self"]);
|
|
4769
|
-
var PublishTargetSchema = z9.looseObject({
|
|
4770
|
-
kind: PublishKindSchema,
|
|
4771
|
-
visibility: RepoVisibilitySchema.optional(),
|
|
4772
|
-
language: RepoLanguageSchema.optional()
|
|
4773
|
-
});
|
|
4774
|
-
var RepoEntrySchema = z9.looseObject({
|
|
4775
|
-
path: SourceRootSchema,
|
|
4776
|
-
visibility: RepoVisibilitySchema.optional(),
|
|
4777
|
-
language: RepoLanguageSchema.optional(),
|
|
4778
|
-
publishes: z9.array(PublishTargetSchema).optional(),
|
|
4779
|
-
instructions: RepoInstructionsSchema.optional()
|
|
4780
|
-
});
|
|
4781
|
-
var WorkspaceMetaSchema = z9.looseObject({
|
|
4782
|
-
id: WorkspaceIdSchema,
|
|
4783
|
-
name: z9.string().min(1),
|
|
4784
|
-
created_at: IsoTimestampSchema,
|
|
4785
|
-
updated_at: IsoTimestampSchema,
|
|
4786
|
-
/**
|
|
4787
|
-
* The generated workspace view: a throwaway directory that aggregates the
|
|
4788
|
-
* roster repos via symlinks (one `<repo-basename>` symlink per repo). A path
|
|
4789
|
-
* relative to the manifest root, reusing the machine-portable source-root
|
|
4790
|
-
* constraint. Absent for a solo project (no view needed); `basou project
|
|
4791
|
-
* workspace` reconciles the view's symlinks to the declared roster.
|
|
4792
|
-
*/
|
|
4793
|
-
view: SourceRootSchema.optional()
|
|
4794
|
-
});
|
|
4795
|
-
var ManifestSchema = z9.looseObject({
|
|
4796
|
-
schema_version: SchemaVersionSchema,
|
|
4797
|
-
// Same forward-compatible format gate as schema_version (accept 0.x.y, gate a
|
|
4798
|
-
// higher major with an upgrade error) rather than a hard literal. `basou_version`
|
|
4799
|
-
// is a format stamp, not the npm/product version; consolidating it with
|
|
4800
|
-
// schema_version is a candidate cleanup for the M4 freeze pass.
|
|
4801
|
-
basou_version: SchemaVersionSchema,
|
|
4802
|
-
workspace: WorkspaceMetaSchema,
|
|
4803
|
-
project: ProjectSchema,
|
|
4804
|
-
capabilities: CapabilitiesSchema,
|
|
4805
|
-
approval: ApprovalConfigSchema,
|
|
4806
|
-
adapters: AdaptersSchema,
|
|
4807
|
-
git: GitConfigSchema,
|
|
4808
|
-
import: ImportConfigSchema.optional(),
|
|
4809
|
-
repos: z9.array(RepoEntrySchema).min(1).optional()
|
|
4810
|
-
});
|
|
4811
|
-
var KNOWN_TOP_LEVEL_KEYS = new Set(Object.keys(ManifestSchema.shape));
|
|
4812
|
-
function unknownManifestKeys(manifest) {
|
|
4813
|
-
return Object.keys(manifest).filter((k) => !KNOWN_TOP_LEVEL_KEYS.has(k)).sort();
|
|
4814
|
-
}
|
|
4815
|
-
|
|
4816
|
-
// src/storage/manifest.ts
|
|
4817
|
-
function createManifest(input) {
|
|
4818
|
-
if (input.workspaceName.length === 0) {
|
|
4819
|
-
throw new Error("Workspace name is empty. Pass --name explicitly.");
|
|
4820
|
-
}
|
|
4821
|
-
const now = (input.now ?? /* @__PURE__ */ new Date()).toISOString();
|
|
4822
|
-
const workspaceId = input.workspaceId ?? prefixedUlid("ws");
|
|
4823
|
-
const project = {
|
|
4824
|
-
...input.projectName !== void 0 ? { name: input.projectName } : {},
|
|
4825
|
-
...input.projectDescription !== void 0 ? { description: input.projectDescription } : {}
|
|
4826
|
-
};
|
|
4827
|
-
const manifest = {
|
|
4828
|
-
schema_version: "0.1.0",
|
|
4829
|
-
basou_version: "0.1.0",
|
|
4830
|
-
workspace: {
|
|
4831
|
-
id: workspaceId,
|
|
4832
|
-
name: input.workspaceName,
|
|
4833
|
-
created_at: now,
|
|
4834
|
-
updated_at: now
|
|
4835
|
-
},
|
|
4836
|
-
project,
|
|
4837
|
-
capabilities: {
|
|
4838
|
-
enabled: ["core", "claude-code-adapter", "terminal-recording", "git-capability", "approval"]
|
|
4839
|
-
},
|
|
4840
|
-
approval: {
|
|
4841
|
-
required_for: ["destructive_command", "external_send"],
|
|
4842
|
-
default_risk_level: "medium"
|
|
4843
|
-
},
|
|
4844
|
-
adapters: {
|
|
4845
|
-
"claude-code": { enabled: true }
|
|
4846
|
-
},
|
|
4847
|
-
git: { events_log: "ignore" },
|
|
4848
|
-
...input.sourceRoots !== void 0 && input.sourceRoots.length > 0 ? { import: { source_roots: input.sourceRoots } } : {}
|
|
4849
|
-
};
|
|
4850
|
-
return ManifestSchema.parse(manifest);
|
|
4851
|
-
}
|
|
4852
|
-
async function writeManifest(paths, manifest, options) {
|
|
4853
|
-
const force = options?.force === true;
|
|
4854
|
-
const validated = ManifestSchema.parse(manifest);
|
|
4855
|
-
delete validated.project.repository_url;
|
|
4856
|
-
if (!force) {
|
|
4857
|
-
let existed = false;
|
|
4858
|
-
try {
|
|
4859
|
-
await lstat3(paths.files.manifest);
|
|
4860
|
-
existed = true;
|
|
4861
|
-
} catch (error) {
|
|
4862
|
-
if (!hasErrorCode3(error) || error.code !== "ENOENT") {
|
|
4863
|
-
throw new Error("Failed to inspect existing manifest", { cause: error });
|
|
4864
|
-
}
|
|
4865
|
-
}
|
|
4866
|
-
if (existed) {
|
|
4867
|
-
throw new Error("Already initialized. Use --force to overwrite.");
|
|
4868
|
-
}
|
|
4869
|
-
}
|
|
4870
|
-
await writeYamlFile(paths.files.manifest, validated);
|
|
4871
|
-
}
|
|
4872
|
-
async function readManifest(paths) {
|
|
4873
|
-
const raw = await readYamlFile(paths.files.manifest);
|
|
4874
|
-
return ManifestSchema.parse(raw);
|
|
4875
|
-
}
|
|
4876
|
-
function hasErrorCode3(error) {
|
|
4877
|
-
if (!(error instanceof Error)) return false;
|
|
4878
|
-
return typeof error.code === "string";
|
|
4879
|
-
}
|
|
4880
|
-
|
|
4881
|
-
// src/orientation/orientation-renderer.ts
|
|
4882
5325
|
async function summarizeOrientation(input) {
|
|
4883
5326
|
const limit = input.relatedFilesLimit ?? 10;
|
|
4884
5327
|
const now = new Date(input.nowIso);
|
|
@@ -5111,10 +5554,12 @@ async function summarizeOrientation(input) {
|
|
|
5111
5554
|
}
|
|
5112
5555
|
async function renderOrientation(input) {
|
|
5113
5556
|
const summary = await summarizeOrientation(input);
|
|
5557
|
+
const language = input.language ?? await resolveViewLanguageFromPaths(input.paths);
|
|
5114
5558
|
return {
|
|
5115
5559
|
body: formatOrientationBody(summary, {
|
|
5116
5560
|
staleness: input.staleness ?? null,
|
|
5117
|
-
verbose: input.verbose === true
|
|
5561
|
+
verbose: input.verbose === true,
|
|
5562
|
+
language
|
|
5118
5563
|
}),
|
|
5119
5564
|
sessionCount: summary.sessionCount,
|
|
5120
5565
|
pendingApprovalsCount: summary.pendingApprovals.length,
|
|
@@ -5125,6 +5570,7 @@ async function renderOrientation(input) {
|
|
|
5125
5570
|
};
|
|
5126
5571
|
}
|
|
5127
5572
|
function formatOrientationBody(summary, opts) {
|
|
5573
|
+
const t = viewStrings(opts.language);
|
|
5128
5574
|
const lines = [];
|
|
5129
5575
|
const now = new Date(summary.generatedAt);
|
|
5130
5576
|
const newestRel = relativeAge(summary.freshness.newestStartedAt ?? void 0, now);
|
|
@@ -5138,100 +5584,100 @@ function formatOrientationBody(summary, opts) {
|
|
|
5138
5584
|
lines.push(`> hosts: local, ${summary.hosts.join(", ")}`);
|
|
5139
5585
|
}
|
|
5140
5586
|
lines.push("");
|
|
5141
|
-
const banner = stalenessBanner(opts.staleness);
|
|
5587
|
+
const banner = stalenessBanner(opts.staleness, t);
|
|
5142
5588
|
if (banner.length > 0) {
|
|
5143
5589
|
for (const line of banner) lines.push(line);
|
|
5144
5590
|
lines.push("");
|
|
5145
5591
|
}
|
|
5146
|
-
lines.push(
|
|
5592
|
+
lines.push(t.orientation.headingWhere);
|
|
5147
5593
|
lines.push("");
|
|
5148
5594
|
if (summary.latestSession !== null) {
|
|
5149
5595
|
const s = summary.latestSession;
|
|
5150
5596
|
const sid = shortId(s.sessionId);
|
|
5151
5597
|
if (s.label !== null && s.label !== "") {
|
|
5152
|
-
lines.push(
|
|
5598
|
+
lines.push(
|
|
5599
|
+
`- ${t.common.lastSessionLabel}: ${s.label} (${s.status}) [${sid}]${hostSuffix(s.host)}`
|
|
5600
|
+
);
|
|
5153
5601
|
} else {
|
|
5154
|
-
lines.push(`-
|
|
5602
|
+
lines.push(`- ${t.common.lastSessionLabel}: ${sid} (${s.status})${hostSuffix(s.host)}`);
|
|
5155
5603
|
}
|
|
5156
5604
|
} else {
|
|
5157
|
-
lines.push(
|
|
5605
|
+
lines.push(`- ${t.common.lastSessionLabel}: (no live sessions)`);
|
|
5158
5606
|
}
|
|
5159
5607
|
if (summary.latestDecision !== null) {
|
|
5160
5608
|
const dec = summary.latestDecision;
|
|
5161
|
-
const decAge =
|
|
5609
|
+
const decAge = t.relativeAge(dec.occurredAt, now);
|
|
5162
5610
|
lines.push(
|
|
5163
|
-
`-
|
|
5611
|
+
`- ${t.common.latestDecisionLabel}: ${dec.title} [${shortId(dec.decisionId)}] (${decAge})${hostSuffix(dec.host)}`
|
|
5164
5612
|
);
|
|
5165
5613
|
const activityAt = summary.freshness.latestActivityAt;
|
|
5166
5614
|
if (activityAt !== null && isTrailingStale(activityAt, dec.occurredAt)) {
|
|
5167
|
-
lines.push(
|
|
5168
|
-
` - \u6CE8: \u3053\u308C\u306F\u6700\u5F8C\u306B\u300C\u8A18\u9332\u3055\u308C\u305F\u300D\u5224\u65AD\u3067\u3059\u3002\u6700\u7D42\u6D3B\u52D5 (${relativeAgeJa(activityAt, now)}) \u306F\u3053\u308C\u3088\u308A\u5F8C\u306E\u305F\u3081\u3001\u73FE\u5728\u306E\u65B9\u91DD\u304C\u53CD\u6620\u3055\u308C\u3066\u3044\u306A\u3044\u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059(\u4F1A\u8A71\u3067\u306E\u610F\u601D\u6C7A\u5B9A\u306F\u81EA\u52D5\u8A18\u9332\u3055\u308C\u307E\u305B\u3093\u3002\`basou decision capture\` \u3067\u3053\u306E session \u306E\u5224\u65AD\u3092\u8A18\u9332\u3067\u304D\u307E\u3059)\u3002`
|
|
5169
|
-
);
|
|
5615
|
+
lines.push(` - ${t.orientation.decisionStaleNote(t.relativeAge(activityAt, now))}`);
|
|
5170
5616
|
}
|
|
5171
5617
|
if (summary.latestSession !== null && dec.sessionId !== summary.latestSession.sessionId) {
|
|
5172
|
-
lines.push(
|
|
5173
|
-
` - \u6CE8: \u3053\u306E\u5224\u65AD\u306F\u6700\u7D42 session \u3068\u306F\u5225\u306E session [${shortId(dec.sessionId)}] \u306E\u3082\u306E\u3067\u3059\u3002`
|
|
5174
|
-
);
|
|
5618
|
+
lines.push(` - ${t.common.decisionOtherSessionNote(shortId(dec.sessionId))}`);
|
|
5175
5619
|
}
|
|
5176
5620
|
if (summary.decisionCount > 1) {
|
|
5177
5621
|
lines.push(` - ${summary.decisionCount} decisions total \u2014 see decisions.md`);
|
|
5178
5622
|
}
|
|
5179
5623
|
} else {
|
|
5180
|
-
lines.push(
|
|
5624
|
+
lines.push(
|
|
5625
|
+
`- ${t.common.latestDecisionLabel}: (no decisions recorded yet; capture with \`basou decision capture\`)`
|
|
5626
|
+
);
|
|
5181
5627
|
}
|
|
5182
5628
|
if (summary.relatedFiles.displayed.length > 0) {
|
|
5183
5629
|
const shown = summary.relatedFiles.displayed.join(", ");
|
|
5184
5630
|
const more = summary.relatedFiles.overflow > 0 ? ` (... +${summary.relatedFiles.overflow} more)` : "";
|
|
5185
|
-
lines.push(`-
|
|
5631
|
+
lines.push(`- ${t.common.recentFilesLabel}: ${shown}${more}`);
|
|
5186
5632
|
if (summary.relatedFiles.outOfRoot.length > 0) {
|
|
5187
5633
|
const OUT_OF_ROOT_DISPLAY = 10;
|
|
5188
5634
|
const out = summary.relatedFiles.outOfRoot;
|
|
5189
5635
|
const shownOut = out.slice(0, OUT_OF_ROOT_DISPLAY).join(", ");
|
|
5190
5636
|
const outMore = out.length > OUT_OF_ROOT_DISPLAY ? ` (... +${out.length - OUT_OF_ROOT_DISPLAY} more)` : "";
|
|
5191
|
-
lines.push(
|
|
5192
|
-
` - \u26A0 source_roots \u5916 ${out.length} \u4EF6 (\u5225\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u306E\u53EF\u80FD\u6027): ${shownOut}${outMore}`
|
|
5193
|
-
);
|
|
5637
|
+
lines.push(` - ${t.orientation.outOfRootWarning(out.length, `${shownOut}${outMore}`)}`);
|
|
5194
5638
|
}
|
|
5195
5639
|
} else {
|
|
5196
|
-
lines.push(
|
|
5640
|
+
lines.push(`- ${t.common.recentFilesLabel}: (none recorded)`);
|
|
5197
5641
|
}
|
|
5198
5642
|
lines.push("");
|
|
5199
|
-
lines.push(
|
|
5643
|
+
lines.push(t.orientation.headingRecent(RECENT_DIRECTION_SESSIONS));
|
|
5200
5644
|
lines.push("");
|
|
5201
5645
|
if (summary.recentDirection.length === 0) {
|
|
5202
|
-
lines.push(
|
|
5646
|
+
lines.push(`- ${t.orientation.recentEmpty}`);
|
|
5203
5647
|
} else {
|
|
5204
5648
|
for (const s of summary.recentDirection) {
|
|
5205
5649
|
const sid = shortId(s.sessionId);
|
|
5206
|
-
const age =
|
|
5650
|
+
const age = t.relativeAge(s.occurredAt, now);
|
|
5207
5651
|
const head = s.label !== null && s.label !== "" ? s.label : sid;
|
|
5208
5652
|
lines.push(`- ${head} (${age})${hostSuffix(s.host)}`);
|
|
5209
5653
|
if (s.decisions.length > 0) {
|
|
5210
5654
|
const more = s.decisionsOverflow > 0 ? ` (+${s.decisionsOverflow})` : "";
|
|
5211
|
-
lines.push(
|
|
5655
|
+
lines.push(
|
|
5656
|
+
` - ${t.orientation.recentDecisionsLabel}: ${s.decisions.map(noteSummary).join("; ")}${more}`
|
|
5657
|
+
);
|
|
5212
5658
|
}
|
|
5213
5659
|
for (const note of s.notes) {
|
|
5214
|
-
lines.push(` -
|
|
5660
|
+
lines.push(` - ${t.orientation.recentNextStepLabel}: ${noteSummary(note)}`);
|
|
5215
5661
|
}
|
|
5216
5662
|
if (s.files.length > 0) {
|
|
5217
|
-
lines.push(` -
|
|
5663
|
+
lines.push(` - ${t.orientation.recentChangedLabel}: ${s.files.join(", ")}`);
|
|
5218
5664
|
}
|
|
5219
5665
|
}
|
|
5220
5666
|
}
|
|
5221
5667
|
lines.push("");
|
|
5222
|
-
lines.push(
|
|
5668
|
+
lines.push(t.orientation.headingInFlight);
|
|
5223
5669
|
lines.push("");
|
|
5224
|
-
lines.push(
|
|
5670
|
+
lines.push(t.orientation.inFlightTasksHeading(summary.inFlightTasks.length));
|
|
5225
5671
|
if (summary.inFlightTasks.length === 0) {
|
|
5226
5672
|
lines.push("- (none)");
|
|
5227
5673
|
} else {
|
|
5228
|
-
for (const
|
|
5229
|
-
const linkedSuffix =
|
|
5230
|
-
lines.push(`- ${
|
|
5674
|
+
for (const t2 of summary.inFlightTasks) {
|
|
5675
|
+
const linkedSuffix = t2.linkedSessions > 1 ? ` \u2014 linked_sessions: ${t2.linkedSessions}` : "";
|
|
5676
|
+
lines.push(`- ${t2.title} (${t2.status}) [${shortId(t2.id)}]${linkedSuffix}`);
|
|
5231
5677
|
}
|
|
5232
5678
|
}
|
|
5233
5679
|
lines.push("");
|
|
5234
|
-
lines.push(
|
|
5680
|
+
lines.push(t.orientation.pendingApprovalsHeading(summary.pendingApprovals.length));
|
|
5235
5681
|
if (summary.pendingApprovals.length === 0) {
|
|
5236
5682
|
lines.push("- (none)");
|
|
5237
5683
|
} else {
|
|
@@ -5243,7 +5689,7 @@ function formatOrientationBody(summary, opts) {
|
|
|
5243
5689
|
}
|
|
5244
5690
|
}
|
|
5245
5691
|
lines.push("");
|
|
5246
|
-
lines.push(
|
|
5692
|
+
lines.push(t.orientation.suspectSessionsHeading(summary.suspects.length));
|
|
5247
5693
|
if (summary.suspects.length === 0) {
|
|
5248
5694
|
lines.push("- (none)");
|
|
5249
5695
|
} else {
|
|
@@ -5254,71 +5700,63 @@ function formatOrientationBody(summary, opts) {
|
|
|
5254
5700
|
}
|
|
5255
5701
|
}
|
|
5256
5702
|
lines.push("");
|
|
5257
|
-
lines.push(
|
|
5703
|
+
lines.push(t.orientation.headingForward);
|
|
5258
5704
|
lines.push("");
|
|
5259
5705
|
if (summary.openTracks.length > 0) {
|
|
5260
5706
|
const TRACK_DISPLAY_LIMIT = 10;
|
|
5261
5707
|
const shownTracks = summary.openTracks.slice(0, TRACK_DISPLAY_LIMIT);
|
|
5262
5708
|
const trackOverflow = summary.openTracks.length - shownTracks.length;
|
|
5263
|
-
lines.push(
|
|
5264
|
-
for (const
|
|
5265
|
-
const trackAge =
|
|
5266
|
-
lines.push(
|
|
5267
|
-
|
|
5268
|
-
|
|
5709
|
+
lines.push(t.orientation.openTracksHeading(summary.openTracks.length));
|
|
5710
|
+
for (const track of shownTracks) {
|
|
5711
|
+
const trackAge = t.relativeAge(track.occurredAt, now);
|
|
5712
|
+
lines.push(
|
|
5713
|
+
`- ${track.title} [${shortId(track.decisionId)}] (${trackAge})${hostSuffix(track.host)}`
|
|
5714
|
+
);
|
|
5715
|
+
if (track.rationale !== null && track.rationale.trim() !== "") {
|
|
5716
|
+
lines.push(` - ${t.common.trackWhyLabel}: ${trackRationale(track.rationale)}`);
|
|
5269
5717
|
}
|
|
5270
5718
|
}
|
|
5271
5719
|
if (trackOverflow > 0) {
|
|
5272
5720
|
lines.push(`- ... +${trackOverflow} more (see decisions.md)`);
|
|
5273
5721
|
}
|
|
5274
|
-
lines.push(
|
|
5275
|
-
"\u5B8C\u4E86\u3057\u305F\u3089 `basou decision void <decision_id>` \u3067\u9589\u3058\u3066\u304F\u3060\u3055\u3044\u3002\u9589\u3058\u308B\u307E\u3067\u6BCE\u56DE\u3053\u3053\u306B\u8868\u793A\u3055\u308C\u307E\u3059\u3002"
|
|
5276
|
-
);
|
|
5722
|
+
lines.push(t.orientation.trackCloseInstruction);
|
|
5277
5723
|
lines.push("");
|
|
5278
5724
|
}
|
|
5279
5725
|
if (summary.latestNote !== null) {
|
|
5280
|
-
const noteAge =
|
|
5726
|
+
const noteAge = t.relativeAge(summary.latestNote.occurredAt, now);
|
|
5281
5727
|
lines.push(
|
|
5282
|
-
`-
|
|
5728
|
+
`- ${t.orientation.nextStepRecordedLabel(noteAge)}: ${noteSummary(summary.latestNote.body)} [session ${shortId(summary.latestNote.sessionId)}]${hostSuffix(summary.latestNote.host)}`
|
|
5283
5729
|
);
|
|
5284
5730
|
const activityAt = summary.freshness.latestActivityAt;
|
|
5285
5731
|
if (activityAt !== null && isTrailingStale(activityAt, summary.latestNote.occurredAt)) {
|
|
5286
|
-
lines.push(
|
|
5287
|
-
` - \u6CE8: \u3053\u306E\u8D77\u70B9\u306E\u8A18\u9332\u5F8C (\u6700\u7D42\u6D3B\u52D5 ${relativeAgeJa(activityAt, now)}) \u3082\u4F5C\u696D\u304C\u7D9A\u3044\u3066\u3044\u307E\u3059\u3002\u518D\u958B\u70B9\u304C\u53E4\u3044\u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059\u3002`
|
|
5288
|
-
);
|
|
5732
|
+
lines.push(` - ${t.orientation.noteStaleNote(t.relativeAge(activityAt, now))}`);
|
|
5289
5733
|
}
|
|
5290
5734
|
}
|
|
5291
|
-
for (const
|
|
5292
|
-
lines.push(`- ${
|
|
5735
|
+
for (const task of summary.plannedTasks) {
|
|
5736
|
+
lines.push(`- ${task.title} [${shortId(task.id)}]`);
|
|
5293
5737
|
}
|
|
5294
5738
|
if (summary.openTracks.length === 0 && summary.latestNote === null && summary.plannedTasks.length === 0) {
|
|
5295
5739
|
const dec = summary.latestDecision;
|
|
5296
5740
|
if (dec === null) {
|
|
5297
5741
|
lines.push("- (no planned tasks or recorded next step yet)");
|
|
5298
5742
|
} else if (isTrailingStale(summary.freshness.latestActivityAt, dec.occurredAt)) {
|
|
5299
|
-
lines.push(
|
|
5300
|
-
|
|
5301
|
-
);
|
|
5302
|
-
lines.push(` - \u53C2\u8003 (\u53E4\u3044\u53EF\u80FD\u6027\u30FB\u65B9\u91DD\u3067\u306F\u306A\u3044): ${dec.title}`);
|
|
5743
|
+
lines.push(t.orientation.fallbackStaleDirection);
|
|
5744
|
+
lines.push(` - ${t.orientation.fallbackStaleReferenceLabel}: ${dec.title}`);
|
|
5303
5745
|
} else {
|
|
5304
5746
|
lines.push("- (no planned tasks \u2014 direction is inferred from recent decisions)");
|
|
5305
|
-
lines.push(` -
|
|
5747
|
+
lines.push(` - ${t.common.latestDecisionLabel}: ${dec.title}`);
|
|
5306
5748
|
}
|
|
5307
5749
|
if (dec !== null) {
|
|
5308
|
-
lines.push(
|
|
5309
|
-
' - \u6B21\u306B\u4F5C\u308B\u3079\u304D\u672C\u8CEA\u7684\u306A\u65B9\u5411\u6027\u304C\u5B9A\u307E\u3063\u305F\u3089 `basou decision capture` (`"kind":"track"`) / `basou decision record --track` \u3067 track \u5316\u3059\u308B\u3068\u3001close \u307E\u3067\u6BCE session \u3053\u3053\u306B\u7D99\u7D9A\u8868\u793A\u3055\u308C\u307E\u3059\u3002'
|
|
5310
|
-
);
|
|
5750
|
+
lines.push(` - ${t.orientation.trackNudge}`);
|
|
5311
5751
|
}
|
|
5312
5752
|
}
|
|
5313
5753
|
lines.push("");
|
|
5314
|
-
lines.push(
|
|
5754
|
+
lines.push(t.orientation.headingCurrency);
|
|
5315
5755
|
lines.push("");
|
|
5316
|
-
for (const line of freshnessVerdict(summary, opts.staleness, now)) lines.push(line);
|
|
5756
|
+
for (const line of freshnessVerdict(summary, opts.staleness, now, t)) lines.push(line);
|
|
5317
5757
|
if (summary.hosts.length > 0) {
|
|
5318
5758
|
lines.push("");
|
|
5319
|
-
lines.push(
|
|
5320
|
-
"\u6CE8: \u9BAE\u5EA6\u5224\u5B9A\u306F\u3053\u306E\u30DE\u30B7\u30F3\u306E\u30ED\u30FC\u30AB\u30EB\u30B9\u30C8\u30A2\u306E\u307F\u304C\u5BFE\u8C61\u3067\u3059\u3002\u4ED6\u30DB\u30B9\u30C8\u306E\u53D6\u308A\u3053\u307C\u3057\u306F\u5224\u5B9A\u3067\u304D\u307E\u305B\u3093(\u5404\u30DB\u30B9\u30C8\u3067 basou refresh \u3092\u5B9F\u884C\u3057\u540C\u671F\u3057\u3066\u304F\u3060\u3055\u3044)\u3002"
|
|
5321
|
-
);
|
|
5759
|
+
lines.push(t.orientation.federatedFreshnessNote);
|
|
5322
5760
|
}
|
|
5323
5761
|
if (opts.verbose) {
|
|
5324
5762
|
lines.push("");
|
|
@@ -5348,7 +5786,7 @@ function formatOrientationBody(summary, opts) {
|
|
|
5348
5786
|
}
|
|
5349
5787
|
return lines.join("\n");
|
|
5350
5788
|
}
|
|
5351
|
-
function toolDisplayName(kind) {
|
|
5789
|
+
function toolDisplayName(kind, t) {
|
|
5352
5790
|
switch (kind) {
|
|
5353
5791
|
case "claude-code-import":
|
|
5354
5792
|
case "claude-code-adapter":
|
|
@@ -5356,98 +5794,61 @@ function toolDisplayName(kind) {
|
|
|
5356
5794
|
case "codex-import":
|
|
5357
5795
|
return "Codex";
|
|
5358
5796
|
case "terminal":
|
|
5359
|
-
return
|
|
5797
|
+
return t.orientation.toolTerminal;
|
|
5360
5798
|
case "human":
|
|
5361
|
-
return
|
|
5799
|
+
return t.orientation.toolHuman;
|
|
5362
5800
|
case "import":
|
|
5363
|
-
return
|
|
5801
|
+
return t.orientation.toolImport;
|
|
5364
5802
|
default:
|
|
5365
|
-
return kind ??
|
|
5803
|
+
return kind ?? t.orientation.toolUnknown;
|
|
5366
5804
|
}
|
|
5367
5805
|
}
|
|
5368
|
-
function stalenessBanner(staleness) {
|
|
5806
|
+
function stalenessBanner(staleness, t) {
|
|
5369
5807
|
if (staleness === null) return [];
|
|
5370
5808
|
if ((staleness.unverifiableSessions ?? 0) > 0) {
|
|
5371
|
-
return [
|
|
5372
|
-
`> \u26A0\uFE0F **\u518D\u53D6\u308A\u8FBC\u307F\u304C\u5FC5\u8981** \u2014 native \u30ED\u30B0\u304C\u5909\u5316\u3057\u305F\u304C\u901A\u5E38\u306E refresh \u3067\u306F\u53D6\u308A\u8FBC\u3081\u306A\u3044\u30BB\u30C3\u30B7\u30E7\u30F3\u304C ${staleness.unverifiableSessions} \u4EF6\u3042\u308A\u307E\u3059\u3002\`basou refresh --force\` \u3067\u518D\u53D6\u308A\u8FBC\u307F\u3057\u3066\u304F\u3060\u3055\u3044(\u8A73\u7D30\u306F\u672B\u5C3E\u300C\u3053\u308C\u306F\u6700\u65B0\u304B\u300D)\u3002`
|
|
5373
|
-
];
|
|
5809
|
+
return [t.orientation.bannerUnverifiable(staleness.unverifiableSessions ?? 0)];
|
|
5374
5810
|
}
|
|
5375
5811
|
if (staleness.newSessions > 0) {
|
|
5376
|
-
const parts = [
|
|
5377
|
-
if (staleness.updatedSessions > 0)
|
|
5378
|
-
|
|
5379
|
-
|
|
5380
|
-
];
|
|
5812
|
+
const parts = [t.orientation.partNew(staleness.newSessions)];
|
|
5813
|
+
if (staleness.updatedSessions > 0)
|
|
5814
|
+
parts.push(t.orientation.partUpdated(staleness.updatedSessions));
|
|
5815
|
+
return [t.orientation.bannerStale(parts.join(t.orientation.partsJoiner))];
|
|
5381
5816
|
}
|
|
5382
5817
|
return [];
|
|
5383
5818
|
}
|
|
5384
|
-
function freshnessVerdict(summary, staleness, now) {
|
|
5819
|
+
function freshnessVerdict(summary, staleness, now, t) {
|
|
5385
5820
|
if (staleness !== null && (staleness.unverifiableSessions ?? 0) > 0) {
|
|
5386
|
-
return [
|
|
5387
|
-
`\u26A0\uFE0F native \u30ED\u30B0\u304C\u5909\u5316\u3057\u307E\u3057\u305F\u304C\u3001\u901A\u5E38\u306E \`basou refresh\` \u3067\u306F\u5B89\u5168\u306B\u518D\u53D6\u308A\u8FBC\u307F\u3067\u304D\u306A\u3044\u30BB\u30C3\u30B7\u30E7\u30F3\u304C ${staleness.unverifiableSessions} \u4EF6\u3042\u308A\u307E\u3059(\u975E\u8FFD\u8A18\u5909\u66F4\u30FB\u524D\u30C1\u30A7\u30FC\u30F3\u4E0D\u6574\u5408\u306A\u3069)\u3002`,
|
|
5388
|
-
"`basou refresh --force` \u3067\u518D\u53D6\u308A\u8FBC\u307F\u3057\u3066\u304F\u3060\u3055\u3044\u3002(`basou verify` \u306F\u5225\u7269=\u53D6\u308A\u8FBC\u307F\u6E08\u307F\u30C7\u30FC\u30BF\u306E\u6539\u7AC4/\u7834\u640D\u691C\u67FB\u3067\u3001\u30D8\u30C3\u30C0\u306E suspect \u3068\u306F\u5225\u8EF8\u3067\u3059\u3002verify \u304C clean \u3067\u3082\u672A\u53D6\u308A\u8FBC\u307F\u306F\u6B8B\u308A\u5F97\u307E\u3059\u3002)"
|
|
5389
|
-
];
|
|
5821
|
+
return [...t.orientation.verdictUnverifiable(staleness.unverifiableSessions ?? 0)];
|
|
5390
5822
|
}
|
|
5391
5823
|
if (staleness !== null && staleness.newSessions > 0) {
|
|
5392
|
-
const parts = [
|
|
5393
|
-
if (staleness.updatedSessions > 0)
|
|
5394
|
-
|
|
5395
|
-
|
|
5396
|
-
"\u7740\u624B\u524D\u306B\u5FC5\u305A `basou refresh` \u3092\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002"
|
|
5397
|
-
];
|
|
5824
|
+
const parts = [t.orientation.partNew(staleness.newSessions)];
|
|
5825
|
+
if (staleness.updatedSessions > 0)
|
|
5826
|
+
parts.push(t.orientation.partUpdated(staleness.updatedSessions));
|
|
5827
|
+
return [...t.orientation.verdictStale(parts.join(t.orientation.partsJoiner))];
|
|
5398
5828
|
}
|
|
5399
5829
|
if (staleness !== null && staleness.updatedSessions > 0) {
|
|
5400
|
-
const lines2 = [
|
|
5401
|
-
`\u26A0\uFE0F \u66F4\u65B0\u3055\u308C\u305F\u30BB\u30C3\u30B7\u30E7\u30F3\u304C ${staleness.updatedSessions} \u4EF6\u3042\u308A\u307E\u3059\u3002\`basou refresh\` \u3067\u53D6\u308A\u8FBC\u3081\u307E\u3059\u3002`,
|
|
5402
|
-
"(\u9032\u884C\u4E2D\u306E\u30BB\u30C3\u30B7\u30E7\u30F3\u304C\u3042\u308B\u5834\u5408\u3001\u305D\u308C\u81EA\u8EAB\u306F\u53D6\u308A\u8FBC\u307F\u5F8C\u3082\u5897\u3048\u7D9A\u3051\u308B\u305F\u3081\u6B8B\u308A\u307E\u3059\uFF1D\u6B63\u5E38\u3067\u3059\u3002)"
|
|
5403
|
-
];
|
|
5830
|
+
const lines2 = [...t.orientation.verdictUpdatedOnly(staleness.updatedSessions)];
|
|
5404
5831
|
if (summary.suspects.length > 0) {
|
|
5405
|
-
lines2.push(
|
|
5406
|
-
`\u307E\u305F\u8981\u6CE8\u610F\u30BB\u30C3\u30B7\u30E7\u30F3\u304C ${summary.suspects.length} \u4EF6\u3042\u308A\u307E\u3059(\u4E0A\u8A18\u300C\u8981\u6CE8\u610F session\u300D\u53C2\u7167)\u3002`
|
|
5407
|
-
);
|
|
5832
|
+
lines2.push(t.orientation.verdictSuspectsAlso(summary.suspects.length));
|
|
5408
5833
|
}
|
|
5409
5834
|
return lines2;
|
|
5410
5835
|
}
|
|
5411
5836
|
if (summary.freshness.newestStartedAt === null) {
|
|
5412
|
-
return [
|
|
5413
|
-
"\u2139\uFE0F \u307E\u3060\u8A18\u9332\u304C\u3042\u308A\u307E\u305B\u3093\u3002",
|
|
5414
|
-
"\u3053\u306E\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u3067\u4F5C\u696D\u3059\u308B\u3068\u3001\u3053\u3053\u306B\u73FE\u5728\u5730\u304C\u8868\u793A\u3055\u308C\u307E\u3059\u3002"
|
|
5415
|
-
];
|
|
5837
|
+
return [...t.orientation.verdictEmpty];
|
|
5416
5838
|
}
|
|
5417
|
-
const rel =
|
|
5418
|
-
const tool = toolDisplayName(summary.freshness.newestSource);
|
|
5839
|
+
const rel = t.relativeAge(summary.freshness.newestStartedAt, now);
|
|
5840
|
+
const tool = toolDisplayName(summary.freshness.newestSource, t);
|
|
5419
5841
|
const suspectCount = summary.suspects.length;
|
|
5420
5842
|
if (staleness === null) {
|
|
5421
|
-
return [
|
|
5422
|
-
`\u2139\uFE0F \u53D6\u308A\u8FBC\u307F\u6E08\u307F\u306E\u72B6\u614B\u3092\u8868\u793A\u3057\u3066\u3044\u307E\u3059\u3002\u6700\u5F8C\u306E\u4F5C\u696D\u306F ${rel}(${tool})\u3002`,
|
|
5423
|
-
"\u6700\u65B0\u304B\u78BA\u8A8D\u3059\u308B\u306B\u306F `basou refresh` \u3092\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002"
|
|
5424
|
-
];
|
|
5843
|
+
return [...t.orientation.verdictUnprobed(rel, tool)];
|
|
5425
5844
|
}
|
|
5426
|
-
const
|
|
5427
|
-
const lines = [
|
|
5428
|
-
`\u2705 ${localScope}\u53D6\u308A\u8FBC\u307F\u306F\u6700\u65B0\u3067\u3059\u3002\u6700\u5F8C\u306E\u4F5C\u696D\u306F ${rel}(${tool})\u3002\u672A\u53D6\u308A\u8FBC\u307F\u306E native \u30BB\u30C3\u30B7\u30E7\u30F3\u306F\u3042\u308A\u307E\u305B\u3093\u3002`
|
|
5429
|
-
];
|
|
5845
|
+
const lines = [t.orientation.verdictCurrent(rel, tool, summary.hosts.length > 0)];
|
|
5430
5846
|
if (suspectCount > 0) {
|
|
5431
|
-
lines.push(
|
|
5847
|
+
lines.push(t.orientation.verdictSuspectsCaveat(suspectCount));
|
|
5432
5848
|
}
|
|
5433
|
-
lines.push(
|
|
5434
|
-
"\u6CE8: \u3053\u306E\u5224\u5B9A\u306F\u53D6\u308A\u8FBC\u307F\u6E08\u307F native \u30BB\u30C3\u30B7\u30E7\u30F3\u306E\u9BAE\u5EA6\u3068 suspect \u306E\u6709\u7121\u3060\u3051\u3092\u898B\u307E\u3059\u3002\u8A08\u753B\u2194\u5B9F\u88C5\u306E\u30C9\u30EA\u30D5\u30C8\u3084\u672A\u8A18\u9332\u306E\u610F\u601D\u6C7A\u5B9A\u307E\u3067\u306F\u691C\u77E5\u3057\u307E\u305B\u3093\u3002"
|
|
5435
|
-
);
|
|
5849
|
+
lines.push(t.orientation.verdictScopeDisclaimer);
|
|
5436
5850
|
return lines;
|
|
5437
5851
|
}
|
|
5438
|
-
function relativeAgeJa(startedAt, now) {
|
|
5439
|
-
if (startedAt === null) return "(\u4E0D\u660E)";
|
|
5440
|
-
const ms = now.getTime() - Date.parse(startedAt);
|
|
5441
|
-
if (!Number.isFinite(ms) || ms < 0) return "\u305F\u3063\u305F\u4ECA";
|
|
5442
|
-
if (ms < 6e4) return "\u305F\u3063\u305F\u4ECA";
|
|
5443
|
-
const totalMin = Math.floor(ms / 6e4);
|
|
5444
|
-
const days = Math.floor(totalMin / 1440);
|
|
5445
|
-
const hours = Math.floor(totalMin % 1440 / 60);
|
|
5446
|
-
const mins = totalMin % 60;
|
|
5447
|
-
if (days > 0) return hours > 0 ? `${days}\u65E5${hours}\u6642\u9593\u524D` : `${days}\u65E5\u524D`;
|
|
5448
|
-
if (hours > 0) return mins > 0 ? `${hours}\u6642\u9593${mins}\u5206\u524D` : `${hours}\u6642\u9593\u524D`;
|
|
5449
|
-
return `${mins}\u5206\u524D`;
|
|
5450
|
-
}
|
|
5451
5852
|
function relativeAge(startedAt, now) {
|
|
5452
5853
|
if (startedAt === void 0) return "(unknown)";
|
|
5453
5854
|
const ms = now.getTime() - Date.parse(startedAt);
|
|
@@ -5483,21 +5884,18 @@ function shortId(id) {
|
|
|
5483
5884
|
|
|
5484
5885
|
// src/project/anchor-starter.ts
|
|
5485
5886
|
function renderAnchorStarter(input) {
|
|
5887
|
+
const t = presetStrings(resolveAnchorContentLanguage(input.repos)).anchorStarter;
|
|
5486
5888
|
const lines = [];
|
|
5487
5889
|
const title = input.projectName ?? input.anchorName;
|
|
5488
5890
|
lines.push(`# AGENTS.md (${input.anchorName})`);
|
|
5489
5891
|
lines.push("");
|
|
5490
|
-
lines.push(
|
|
5491
|
-
`> \u3053\u306E\u30EA\u30DD\u30B8\u30C8\u30EA\u306F **${title} \u306E planning master(anchor)** \u3067\u3059\u3002\u3053\u3053\u3067\u4F5C\u696D\u3059\u308B AI \u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u306F\u3001\u307E\u305A\u3053\u306E\u30D5\u30A1\u30A4\u30EB\u3092\u8AAD\u3093\u3067\u304F\u3060\u3055\u3044\u3002`
|
|
5492
|
-
);
|
|
5892
|
+
lines.push(t.identityLine(title));
|
|
5493
5893
|
lines.push(">");
|
|
5494
|
-
lines.push(
|
|
5495
|
-
"> \u3053\u306E\u30D5\u30A1\u30A4\u30EB\u306F `basou project derive` \u304C greenfield \u7ACB\u3061\u4E0A\u3052\u6642\u306B **\u4E00\u5EA6\u3060\u3051\u751F\u6210\u3057\u305F starter** \u3067\u3059\u3002\u4EE5\u5F8C\u306F\u624B\u7BA1\u7406\u3057\u3066\u304F\u3060\u3055\u3044 \u2014 basou \u306F\u518D\u751F\u6210\u3082\u4E0A\u66F8\u304D\u3082\u3057\u307E\u305B\u3093(BASOU:GENERATED \u30DE\u30FC\u30AB\u30FC\u306F\u7121\u304F\u3001\u81EA\u7531\u306B\u7DE8\u96C6\u3067\u304D\u307E\u3059)\u3002"
|
|
5496
|
-
);
|
|
5894
|
+
lines.push(t.starterNote);
|
|
5497
5895
|
lines.push("");
|
|
5498
|
-
lines.push(
|
|
5896
|
+
lines.push(t.basicsHeading);
|
|
5499
5897
|
lines.push("");
|
|
5500
|
-
lines.push(
|
|
5898
|
+
lines.push(t.basicsTodo);
|
|
5501
5899
|
lines.push("");
|
|
5502
5900
|
lines.push("```text");
|
|
5503
5901
|
lines.push(`Product name: ${input.projectName ?? "<!-- TODO -->"}`);
|
|
@@ -5508,61 +5906,31 @@ function renderAnchorStarter(input) {
|
|
|
5508
5906
|
lines.push("License: <!-- TODO -->");
|
|
5509
5907
|
lines.push("```");
|
|
5510
5908
|
lines.push("");
|
|
5511
|
-
lines.push(
|
|
5909
|
+
lines.push(t.commitHeading);
|
|
5512
5910
|
lines.push("");
|
|
5513
|
-
lines.push(
|
|
5514
|
-
lines.push(
|
|
5515
|
-
lines.push(
|
|
5911
|
+
lines.push(t.commitPlanning);
|
|
5912
|
+
lines.push(t.commitImplementation);
|
|
5913
|
+
lines.push(t.commitView);
|
|
5516
5914
|
lines.push("");
|
|
5517
|
-
lines.push(
|
|
5915
|
+
lines.push(t.conventionsHeading);
|
|
5518
5916
|
lines.push("");
|
|
5519
|
-
lines.push(
|
|
5917
|
+
lines.push(t.conventionsBody);
|
|
5520
5918
|
lines.push("");
|
|
5521
5919
|
for (const r of input.repos) {
|
|
5522
5920
|
if (r.anchor === true) continue;
|
|
5523
5921
|
lines.push(`- ${r.name}/AGENTS.md`);
|
|
5524
5922
|
}
|
|
5525
5923
|
if (input.viewName !== void 0) {
|
|
5526
|
-
lines.push(
|
|
5527
|
-
`- ${input.viewName}/AGENTS.md(workspace view\u30FBbasou \u304C\u751F\u6210)\u2014 **\u6700\u65B0\u306E repo \u69CB\u6210(roster)\u306F\u3053\u3053\u3092\u6B63\u3068\u3059\u308B**`
|
|
5528
|
-
);
|
|
5924
|
+
lines.push(t.viewPointerLine(input.viewName));
|
|
5529
5925
|
}
|
|
5530
5926
|
lines.push("");
|
|
5531
|
-
lines.push(
|
|
5927
|
+
lines.push(t.policyHeading);
|
|
5532
5928
|
lines.push("");
|
|
5533
|
-
lines.push(
|
|
5534
|
-
lines.push(" - \u73FE\u5728\u306E\u30D5\u30A7\u30FC\u30BA / \u91CD\u8981\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8");
|
|
5535
|
-
lines.push(" - \u6A5F\u5BC6\u60C5\u5831\u306E\u6271\u3044(\u3069\u3053\u306B\u66F8\u304B\u306A\u3044\u304B)");
|
|
5536
|
-
lines.push(" - \u8A00\u8A9E\u30DD\u30EA\u30B7\u30FC(commit / \u30B3\u30E1\u30F3\u30C8 / \u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u306E\u8A00\u8A9E)");
|
|
5537
|
-
lines.push(" - commit \u904B\u7528(\u6DF7\u5728\u30B3\u30DF\u30C3\u30C8\u3092\u907F\u3051\u308B \u7B49)");
|
|
5538
|
-
lines.push("-->");
|
|
5929
|
+
lines.push(...t.policyTodo);
|
|
5539
5930
|
return `${lines.join("\n")}
|
|
5540
5931
|
`;
|
|
5541
5932
|
}
|
|
5542
5933
|
|
|
5543
|
-
// src/project/relative-path.ts
|
|
5544
|
-
function normalizeRelativePath(p) {
|
|
5545
|
-
const trimmed = p.trim();
|
|
5546
|
-
const absolute = trimmed.startsWith("/");
|
|
5547
|
-
const out = [];
|
|
5548
|
-
for (const seg of trimmed.split("/")) {
|
|
5549
|
-
if (seg === "" || seg === ".") continue;
|
|
5550
|
-
if (seg === "..") {
|
|
5551
|
-
const top = out[out.length - 1];
|
|
5552
|
-
if (top !== void 0 && top !== "..") {
|
|
5553
|
-
out.pop();
|
|
5554
|
-
} else if (!absolute) {
|
|
5555
|
-
out.push("..");
|
|
5556
|
-
}
|
|
5557
|
-
continue;
|
|
5558
|
-
}
|
|
5559
|
-
out.push(seg);
|
|
5560
|
-
}
|
|
5561
|
-
const joined = out.join("/");
|
|
5562
|
-
if (absolute) return `/${joined}`;
|
|
5563
|
-
return joined.length === 0 ? "." : joined;
|
|
5564
|
-
}
|
|
5565
|
-
|
|
5566
5934
|
// src/project/archive.ts
|
|
5567
5935
|
function planArchive(input) {
|
|
5568
5936
|
const target = normalizeRelativePath(input.target);
|
|
@@ -5648,131 +6016,76 @@ function planGitignore(input) {
|
|
|
5648
6016
|
}
|
|
5649
6017
|
|
|
5650
6018
|
// src/project/preset.ts
|
|
5651
|
-
function visibilityLabel(v) {
|
|
5652
|
-
switch (v) {
|
|
5653
|
-
case "public":
|
|
5654
|
-
return "public(git \u5C65\u6B74\u306F\u516C\u958B)";
|
|
5655
|
-
case "private":
|
|
5656
|
-
return "private(git \u5C65\u6B74\u306F\u975E\u516C\u958B)";
|
|
5657
|
-
case "future-public":
|
|
5658
|
-
return "future-public(\u73FE\u5728\u306F\u975E\u516C\u958B\u30FB\u5C06\u6765\u516C\u958B\u4E88\u5B9A)";
|
|
5659
|
-
default:
|
|
5660
|
-
return "\u672A\u8A2D\u5B9A";
|
|
5661
|
-
}
|
|
5662
|
-
}
|
|
5663
|
-
function sourceLanguageLabel(l) {
|
|
5664
|
-
switch (l) {
|
|
5665
|
-
case "en":
|
|
5666
|
-
return "en(commit\u30FB\u30B3\u30E1\u30F3\u30C8\u30FB\u30B3\u30FC\u30C9\u306F\u82F1\u8A9E)";
|
|
5667
|
-
case "ja":
|
|
5668
|
-
return "ja(commit\u30FB\u30B3\u30E1\u30F3\u30C8\u30FB\u30B3\u30FC\u30C9\u306F\u65E5\u672C\u8A9E)";
|
|
5669
|
-
case "en+ja":
|
|
5670
|
-
return "en+ja(commit\u30FB\u30B3\u30E1\u30F3\u30C8\u30FB\u30B3\u30FC\u30C9\u306F\u65E5\u82F1)";
|
|
5671
|
-
default:
|
|
5672
|
-
return "\u672A\u8A2D\u5B9A";
|
|
5673
|
-
}
|
|
5674
|
-
}
|
|
5675
|
-
function publishKindLabel(k) {
|
|
5676
|
-
return k === "web" ? "web(\u30C7\u30D7\u30ED\u30A4)" : "npm(\u30D1\u30C3\u30B1\u30FC\u30B8)";
|
|
5677
|
-
}
|
|
5678
|
-
function publishVisibilityLabel(v) {
|
|
5679
|
-
switch (v) {
|
|
5680
|
-
case "public":
|
|
5681
|
-
return "\u516C\u958B";
|
|
5682
|
-
case "private":
|
|
5683
|
-
return "\u975E\u516C\u958B";
|
|
5684
|
-
case "future-public":
|
|
5685
|
-
return "\u5C06\u6765\u516C\u958B";
|
|
5686
|
-
default:
|
|
5687
|
-
return "\u53EF\u8996\u6027\u672A\u8A2D\u5B9A";
|
|
5688
|
-
}
|
|
5689
|
-
}
|
|
5690
|
-
function contentLanguageLabel(l) {
|
|
5691
|
-
return l ?? "\u8A00\u8A9E\u672A\u8A2D\u5B9A";
|
|
5692
|
-
}
|
|
5693
6019
|
function isRenderable(repo) {
|
|
5694
6020
|
return repo.visibility !== void 0 || repo.language !== void 0 || repo.publishes !== void 0 && repo.publishes.length > 0;
|
|
5695
6021
|
}
|
|
5696
6022
|
function renderPresetBlock(repo) {
|
|
6023
|
+
const t = presetStrings(resolveRepoContentLanguage(repo.language)).repoBlock;
|
|
5697
6024
|
const lines = [];
|
|
5698
|
-
lines.push(
|
|
6025
|
+
lines.push(t.heading);
|
|
5699
6026
|
lines.push("");
|
|
5700
|
-
lines.push(
|
|
5701
|
-
"\u3053\u306E\u30BB\u30AF\u30B7\u30E7\u30F3\u306F `.basou/manifest.yaml` \u306E\u5BA3\u8A00\u304B\u3089 `basou project preset` \u304C\u751F\u6210\u3057\u307E\u3059\u3002\u7DE8\u96C6\u306F manifest \u5074\u3067\u884C\u3063\u3066\u304F\u3060\u3055\u3044(\u30DE\u30FC\u30AB\u30FC\u5916\u306E\u8A18\u8FF0\u306F\u4FDD\u6301\u3055\u308C\u307E\u3059)\u3002"
|
|
5702
|
-
);
|
|
6027
|
+
lines.push(t.intro);
|
|
5703
6028
|
lines.push("");
|
|
5704
|
-
lines.push(`-
|
|
5705
|
-
lines.push(`-
|
|
6029
|
+
lines.push(`- ${t.sourceVisibilityLabel}: ${t.visibilityLabel(repo.visibility)}`);
|
|
6030
|
+
lines.push(`- ${t.sourceLanguageLineLabel}: ${t.sourceLanguageLabel(repo.language)}`);
|
|
5706
6031
|
const publishes = repo.publishes ?? [];
|
|
5707
6032
|
if (publishes.length === 0) {
|
|
5708
|
-
lines.push(
|
|
6033
|
+
lines.push(t.publishesNone);
|
|
5709
6034
|
} else {
|
|
5710
|
-
lines.push(
|
|
6035
|
+
lines.push(t.publishesHeader);
|
|
5711
6036
|
for (const p of publishes) {
|
|
5712
6037
|
lines.push(
|
|
5713
|
-
` - ${publishKindLabel(p.kind)} \u2014 ${publishVisibilityLabel(p.visibility)} / ${contentLanguageLabel(p.language)}`
|
|
6038
|
+
` - ${t.publishKindLabel(p.kind)} \u2014 ${t.publishVisibilityLabel(p.visibility)} / ${t.contentLanguageLabel(p.language)}`
|
|
5714
6039
|
);
|
|
5715
6040
|
}
|
|
5716
6041
|
}
|
|
5717
6042
|
return lines.join("\n");
|
|
5718
6043
|
}
|
|
5719
|
-
function visibilityShortLabel(v) {
|
|
5720
|
-
return v ?? "\u672A\u8A2D\u5B9A";
|
|
5721
|
-
}
|
|
5722
|
-
function languageShortLabel(l) {
|
|
5723
|
-
return l ?? "\u672A\u8A2D\u5B9A";
|
|
5724
|
-
}
|
|
5725
|
-
function instructionsLabel(repo) {
|
|
5726
|
-
if (repo.anchor === true) return "anchor(\u624B\u7BA1\u7406)";
|
|
5727
|
-
return repo.self === true ? "self(repo \u304C\u81EA\u5DF1\u7BA1\u7406)" : "hub(basou \u304C\u751F\u6210)";
|
|
5728
|
-
}
|
|
5729
6044
|
function renderViewPresetBlock(input) {
|
|
6045
|
+
const t = presetStrings(resolveAnchorContentLanguage(input.repos)).viewBlock;
|
|
6046
|
+
const shortLabel = (v) => v ?? t.unsetShort;
|
|
6047
|
+
const instructionsLabel = (repo) => {
|
|
6048
|
+
if (repo.anchor === true) return t.instructionsAnchor;
|
|
6049
|
+
return repo.self === true ? t.instructionsSelf : t.instructionsHub;
|
|
6050
|
+
};
|
|
5730
6051
|
const lines = [];
|
|
5731
|
-
lines.push(
|
|
6052
|
+
lines.push(t.heading);
|
|
5732
6053
|
lines.push("");
|
|
5733
|
-
lines.push(
|
|
5734
|
-
|
|
5735
|
-
);
|
|
5736
|
-
lines.push(
|
|
5737
|
-
`\u3053\u306E AGENTS.md \u81EA\u8EAB\u3082 basou \u306E\u751F\u6210\u7269\u3067\u3059(\u5B9F\u4F53: \`agents/${input.viewName}/AGENTS.md\`\u3001\u30DE\u30FC\u30AB\u30FC\u5916\u306E\u8A18\u8FF0\u306F\u4FDD\u6301\u3055\u308C\u307E\u3059)\u3002`
|
|
5738
|
-
);
|
|
6054
|
+
lines.push(t.intro);
|
|
6055
|
+
lines.push(t.selfNote(input.viewName));
|
|
5739
6056
|
lines.push("");
|
|
5740
|
-
lines.push(
|
|
5741
|
-
`\u3053\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306F\u3001\u5BA3\u8A00\u3055\u308C\u305F ${input.repos.length} \u500B\u306E repo \u3092 symlink \u3067\u96C6\u7D04\u3059\u308B **view** \u3067\u3059\u3002\u5B9F\u4F53\u3092\u6301\u305F\u305A\u3001git \u7BA1\u7406\u5916\u3067\u3059\u3002`
|
|
5742
|
-
);
|
|
6057
|
+
lines.push(t.aggregates(input.repos.length));
|
|
5743
6058
|
lines.push("");
|
|
5744
|
-
lines.push(
|
|
6059
|
+
lines.push(t.reposHeading);
|
|
5745
6060
|
lines.push("");
|
|
5746
|
-
lines.push(
|
|
6061
|
+
lines.push(t.tableHeader);
|
|
5747
6062
|
lines.push("|---|---|---|---|");
|
|
5748
6063
|
for (const r of input.repos) {
|
|
5749
6064
|
lines.push(
|
|
5750
|
-
`| ${r.name} | ${
|
|
6065
|
+
`| ${r.name} | ${shortLabel(r.visibility)} | ${shortLabel(r.language)} | ${instructionsLabel(r)} |`
|
|
5751
6066
|
);
|
|
5752
6067
|
}
|
|
5753
6068
|
lines.push("");
|
|
5754
|
-
lines.push(
|
|
6069
|
+
lines.push(t.commitHeading);
|
|
5755
6070
|
lines.push("");
|
|
5756
|
-
lines.push(
|
|
5757
|
-
"view \u3067\u306F commit \u3067\u304D\u307E\u305B\u3093(git \u7BA1\u7406\u5916)\u3002\u5909\u66F4\u306F\u5FC5\u305A\u5B9F\u4F53\u306E repo \u306B `cd` \u3057\u3066\u304B\u3089 commit \u3057\u3066\u304F\u3060\u3055\u3044\u3002"
|
|
5758
|
-
);
|
|
6071
|
+
lines.push(t.commitBody);
|
|
5759
6072
|
lines.push("");
|
|
5760
6073
|
for (const r of input.repos) {
|
|
5761
6074
|
lines.push(`- ${r.name} \u2192 \`cd ${r.name}\``);
|
|
5762
6075
|
}
|
|
5763
6076
|
lines.push("");
|
|
5764
|
-
lines.push(
|
|
6077
|
+
lines.push(t.conventionsHeading);
|
|
5765
6078
|
lines.push("");
|
|
5766
|
-
lines.push(
|
|
6079
|
+
lines.push(t.conventionsBody);
|
|
5767
6080
|
lines.push("");
|
|
5768
6081
|
for (const r of input.repos) {
|
|
5769
6082
|
lines.push(`- ${r.name}/AGENTS.md`);
|
|
5770
6083
|
}
|
|
5771
6084
|
lines.push("");
|
|
5772
|
-
lines.push(
|
|
6085
|
+
lines.push(t.principlesHeading);
|
|
5773
6086
|
lines.push("");
|
|
5774
|
-
lines.push(
|
|
5775
|
-
lines.push(
|
|
6087
|
+
lines.push(t.principleStateless);
|
|
6088
|
+
lines.push(t.principleNoFiles);
|
|
5776
6089
|
return lines.join("\n");
|
|
5777
6090
|
}
|
|
5778
6091
|
function normalizeBlock(s) {
|
|
@@ -6733,7 +7046,8 @@ async function renderReport(input) {
|
|
|
6733
7046
|
changedFiles,
|
|
6734
7047
|
integrity
|
|
6735
7048
|
};
|
|
6736
|
-
|
|
7049
|
+
const language = input.language ?? await resolveViewLanguageFromPaths(input.paths);
|
|
7050
|
+
return { body: formatReportBody(data, viewStrings(language)), data };
|
|
6737
7051
|
}
|
|
6738
7052
|
function computePeriod(entries, nowIso) {
|
|
6739
7053
|
if (entries.length === 0) return { from: null, to: null };
|
|
@@ -6760,7 +7074,7 @@ function tallyTaskStatus(items) {
|
|
|
6760
7074
|
count: counts.get(status)
|
|
6761
7075
|
}));
|
|
6762
7076
|
}
|
|
6763
|
-
function formatReportBody(data) {
|
|
7077
|
+
function formatReportBody(data, t) {
|
|
6764
7078
|
const lines = [];
|
|
6765
7079
|
const titleSuffix = data.title !== void 0 ? ` \u2014 ${data.title}` : "";
|
|
6766
7080
|
lines.push(`# Report${titleSuffix}`);
|
|
@@ -6768,14 +7082,14 @@ function formatReportBody(data) {
|
|
|
6768
7082
|
const periodSuffix = data.period.from !== null && data.period.to !== null ? ` (${data.period.from.slice(0, 10)}..${data.period.to.slice(0, 10)})` : "";
|
|
6769
7083
|
lines.push(`> Generated at ${data.generatedAt}${periodSuffix}`);
|
|
6770
7084
|
lines.push("");
|
|
6771
|
-
lines.push(
|
|
7085
|
+
lines.push(t.report.headingSummary);
|
|
6772
7086
|
lines.push("");
|
|
6773
7087
|
lines.push(`- ${formatSessionsLine(data)}`);
|
|
6774
7088
|
lines.push(
|
|
6775
7089
|
`- Active time ${formatDurationMs(data.time.activeMs)}, ${formatInt(data.volume.outputTokens)} output tokens`
|
|
6776
7090
|
);
|
|
6777
7091
|
lines.push("");
|
|
6778
|
-
lines.push(
|
|
7092
|
+
lines.push(t.report.headingVolume);
|
|
6779
7093
|
lines.push("");
|
|
6780
7094
|
const tokenCaveat = data.volume.tokensAvailable ? "" : " (no token data captured)";
|
|
6781
7095
|
lines.push(`- Output tokens: ${formatInt(data.volume.outputTokens)}${tokenCaveat}`);
|
|
@@ -6795,7 +7109,7 @@ function formatReportBody(data) {
|
|
|
6795
7109
|
}
|
|
6796
7110
|
lines.push(`- Span: ${formatDurationMs(data.time.spanMs)} (total elapsed)`);
|
|
6797
7111
|
lines.push("");
|
|
6798
|
-
lines.push(
|
|
7112
|
+
lines.push(t.report.headingDecisions);
|
|
6799
7113
|
lines.push("");
|
|
6800
7114
|
if (data.decisions.items.length === 0) {
|
|
6801
7115
|
lines.push("(no decisions recorded yet)");
|
|
@@ -6813,7 +7127,7 @@ function formatReportBody(data) {
|
|
|
6813
7127
|
}
|
|
6814
7128
|
}
|
|
6815
7129
|
lines.push("");
|
|
6816
|
-
lines.push(
|
|
7130
|
+
lines.push(t.report.headingApprovals);
|
|
6817
7131
|
lines.push("");
|
|
6818
7132
|
if (data.approvals.items.length === 0) {
|
|
6819
7133
|
lines.push("(none)");
|
|
@@ -6830,7 +7144,7 @@ function formatReportBody(data) {
|
|
|
6830
7144
|
if (overflow > 0) lines.push(`- ... +${overflow} more`);
|
|
6831
7145
|
}
|
|
6832
7146
|
lines.push("");
|
|
6833
|
-
lines.push(
|
|
7147
|
+
lines.push(t.report.headingTasks);
|
|
6834
7148
|
lines.push("");
|
|
6835
7149
|
if (data.tasks.items.length === 0) {
|
|
6836
7150
|
lines.push("(no tasks recorded yet)");
|
|
@@ -6845,7 +7159,7 @@ function formatReportBody(data) {
|
|
|
6845
7159
|
if (overflow > 0) lines.push(`- ... +${overflow} more`);
|
|
6846
7160
|
}
|
|
6847
7161
|
lines.push("");
|
|
6848
|
-
lines.push(
|
|
7162
|
+
lines.push(t.report.headingChangedFiles);
|
|
6849
7163
|
lines.push("");
|
|
6850
7164
|
if (data.changedFiles.length === 0) {
|
|
6851
7165
|
lines.push("(no related files recorded)");
|
|
@@ -6855,7 +7169,7 @@ function formatReportBody(data) {
|
|
|
6855
7169
|
if (overflow > 0) lines.push(`- ... +${overflow} more`);
|
|
6856
7170
|
}
|
|
6857
7171
|
lines.push("");
|
|
6858
|
-
lines.push(
|
|
7172
|
+
lines.push(t.report.headingSessions);
|
|
6859
7173
|
lines.push("");
|
|
6860
7174
|
if (data.sessions.items.length === 0) {
|
|
6861
7175
|
lines.push("(no sessions yet)");
|
|
@@ -6874,7 +7188,7 @@ function formatReportBody(data) {
|
|
|
6874
7188
|
}
|
|
6875
7189
|
}
|
|
6876
7190
|
lines.push("");
|
|
6877
|
-
lines.push(
|
|
7191
|
+
lines.push(t.report.headingIntegrity);
|
|
6878
7192
|
lines.push("");
|
|
6879
7193
|
const i = data.integrity;
|
|
6880
7194
|
lines.push(
|
|
@@ -8307,6 +8621,7 @@ export {
|
|
|
8307
8621
|
planRosterAdoption,
|
|
8308
8622
|
planWorkspaceView,
|
|
8309
8623
|
prefixedUlid,
|
|
8624
|
+
presetStrings,
|
|
8310
8625
|
readAllEvents,
|
|
8311
8626
|
readManifest,
|
|
8312
8627
|
readMarkdownFile,
|
|
@@ -8332,12 +8647,16 @@ export {
|
|
|
8332
8647
|
renderViewPresetBlock,
|
|
8333
8648
|
renderWithMarkers,
|
|
8334
8649
|
replayEvents,
|
|
8650
|
+
resolveAnchorContentLanguage,
|
|
8335
8651
|
resolveBasouRepositoryRoot,
|
|
8336
8652
|
resolveClaudeCodeCommand,
|
|
8337
8653
|
resolveCodexCommand,
|
|
8654
|
+
resolveRepoContentLanguage,
|
|
8338
8655
|
resolveRepositoryRoot,
|
|
8339
8656
|
resolveSessionId,
|
|
8340
8657
|
resolveTaskId,
|
|
8658
|
+
resolveViewLanguage,
|
|
8659
|
+
resolveViewLanguageFromPaths,
|
|
8341
8660
|
safeSimpleGit,
|
|
8342
8661
|
sanitizePath,
|
|
8343
8662
|
sanitizeRelatedFiles,
|
|
@@ -8359,6 +8678,7 @@ export {
|
|
|
8359
8678
|
updateTaskStatusWithEvent,
|
|
8360
8679
|
upsertStopHook,
|
|
8361
8680
|
verifyEventsChain,
|
|
8681
|
+
viewStrings,
|
|
8362
8682
|
writeEventsBulk,
|
|
8363
8683
|
writeManifest,
|
|
8364
8684
|
writeMarkdownFile,
|