@cluesmith/codev 2.1.5 → 3.0.0-rc.1
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/bin/team.js +7 -0
- package/dashboard/dist/assets/index-CiIBsixF.js +194 -0
- package/dashboard/dist/assets/index-CiIBsixF.js.map +1 -0
- package/dashboard/dist/assets/{index-CXX5mK4v.css → index-nr0cXxtf.css} +1 -1
- package/dashboard/dist/index.html +2 -2
- package/dist/agent-farm/cli.d.ts.map +1 -1
- package/dist/agent-farm/cli.js +49 -0
- package/dist/agent-farm/cli.js.map +1 -1
- package/dist/agent-farm/commands/index.d.ts +1 -0
- package/dist/agent-farm/commands/index.d.ts.map +1 -1
- package/dist/agent-farm/commands/index.js +1 -0
- package/dist/agent-farm/commands/index.js.map +1 -1
- package/dist/agent-farm/commands/spawn-worktree.d.ts.map +1 -1
- package/dist/agent-farm/commands/spawn-worktree.js +13 -10
- package/dist/agent-farm/commands/spawn-worktree.js.map +1 -1
- package/dist/agent-farm/commands/team-update.d.ts +26 -0
- package/dist/agent-farm/commands/team-update.d.ts.map +1 -0
- package/dist/agent-farm/commands/team-update.js +120 -0
- package/dist/agent-farm/commands/team-update.js.map +1 -0
- package/dist/agent-farm/commands/team.d.ts +20 -0
- package/dist/agent-farm/commands/team.d.ts.map +1 -0
- package/dist/agent-farm/commands/team.js +92 -0
- package/dist/agent-farm/commands/team.js.map +1 -0
- package/dist/agent-farm/commands/tower.d.ts +1 -0
- package/dist/agent-farm/commands/tower.d.ts.map +1 -1
- package/dist/agent-farm/commands/tower.js +52 -1
- package/dist/agent-farm/commands/tower.js.map +1 -1
- package/dist/agent-farm/servers/tower-instances.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-instances.js +9 -2
- package/dist/agent-farm/servers/tower-instances.js.map +1 -1
- package/dist/agent-farm/servers/tower-routes.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-routes.js +41 -0
- package/dist/agent-farm/servers/tower-routes.js.map +1 -1
- package/dist/agent-farm/servers/tower-server.js +14 -0
- package/dist/agent-farm/servers/tower-server.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +78 -0
- package/dist/cli.js.map +1 -1
- package/dist/lib/team-github.d.ts +58 -0
- package/dist/lib/team-github.d.ts.map +1 -0
- package/dist/lib/team-github.js +134 -0
- package/dist/lib/team-github.js.map +1 -0
- package/dist/lib/team.d.ts +68 -0
- package/dist/lib/team.d.ts.map +1 -0
- package/dist/lib/team.js +215 -0
- package/dist/lib/team.js.map +1 -0
- package/package.json +2 -1
- package/dashboard/dist/assets/index-8ijoXpCt.js +0 -194
- package/dashboard/dist/assets/index-8ijoXpCt.js.map +0 -1
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub data enrichment for team members.
|
|
3
|
+
*
|
|
4
|
+
* Fetches assigned issues, open PRs, and recent activity for each
|
|
5
|
+
* team member using a single batched GraphQL query via `gh api graphql`.
|
|
6
|
+
*
|
|
7
|
+
* Spec 587: Team Tab in Tower Right Panel.
|
|
8
|
+
*/
|
|
9
|
+
import type { TeamMember } from './team.js';
|
|
10
|
+
export interface TeamMemberGitHubData {
|
|
11
|
+
assignedIssues: {
|
|
12
|
+
number: number;
|
|
13
|
+
title: string;
|
|
14
|
+
url: string;
|
|
15
|
+
}[];
|
|
16
|
+
openPRs: {
|
|
17
|
+
number: number;
|
|
18
|
+
title: string;
|
|
19
|
+
url: string;
|
|
20
|
+
}[];
|
|
21
|
+
recentActivity: {
|
|
22
|
+
mergedPRs: {
|
|
23
|
+
number: number;
|
|
24
|
+
title: string;
|
|
25
|
+
mergedAt: string;
|
|
26
|
+
}[];
|
|
27
|
+
closedIssues: {
|
|
28
|
+
number: number;
|
|
29
|
+
title: string;
|
|
30
|
+
closedAt: string;
|
|
31
|
+
}[];
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export declare function getRepoInfo(cwd?: string): Promise<{
|
|
35
|
+
owner: string;
|
|
36
|
+
name: string;
|
|
37
|
+
} | null>;
|
|
38
|
+
/**
|
|
39
|
+
* Build a batched GraphQL query that fetches assigned issues, authored PRs,
|
|
40
|
+
* and recent activity for all team members in one request.
|
|
41
|
+
*
|
|
42
|
+
* Owner/name are interpolated directly into search strings because
|
|
43
|
+
* GraphQL variables are not substituted inside string literals.
|
|
44
|
+
*/
|
|
45
|
+
export declare function buildTeamGraphQLQuery(members: TeamMember[], owner: string, name: string): string;
|
|
46
|
+
/**
|
|
47
|
+
* Parse the GraphQL response into a map of github handle → TeamMemberGitHubData.
|
|
48
|
+
*/
|
|
49
|
+
export declare function parseTeamGraphQLResponse(data: Record<string, unknown>, members: TeamMember[]): Map<string, TeamMemberGitHubData>;
|
|
50
|
+
/**
|
|
51
|
+
* Fetch GitHub data for all team members in a single batched GraphQL request.
|
|
52
|
+
* Returns null on failure (graceful degradation).
|
|
53
|
+
*/
|
|
54
|
+
export declare function fetchTeamGitHubData(members: TeamMember[], cwd?: string): Promise<{
|
|
55
|
+
data: Map<string, TeamMemberGitHubData>;
|
|
56
|
+
error?: string;
|
|
57
|
+
}>;
|
|
58
|
+
//# sourceMappingURL=team-github.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"team-github.d.ts","sourceRoot":"","sources":["../../src/lib/team-github.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAQ5C,MAAM,WAAW,oBAAoB;IACnC,cAAc,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACjE,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC1D,cAAc,EAAE;QACd,SAAS,EAAE;YAAE,MAAM,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;QACjE,YAAY,EAAE;YAAE,MAAM,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;KACrE,CAAC;CACH;AAMD,wBAAsB,WAAW,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAU/F;AAqBD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,UAAU,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CA2BhG;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,EAAE,UAAU,EAAE,GACpB,GAAG,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAuBnC;AAMD;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,UAAU,EAAE,EACrB,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC;IAAE,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CA6BtE"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub data enrichment for team members.
|
|
3
|
+
*
|
|
4
|
+
* Fetches assigned issues, open PRs, and recent activity for each
|
|
5
|
+
* team member using a single batched GraphQL query via `gh api graphql`.
|
|
6
|
+
*
|
|
7
|
+
* Spec 587: Team Tab in Tower Right Panel.
|
|
8
|
+
*/
|
|
9
|
+
import { execFile } from 'node:child_process';
|
|
10
|
+
import { promisify } from 'node:util';
|
|
11
|
+
import { isValidGitHubHandle } from './team.js';
|
|
12
|
+
const execFileAsync = promisify(execFile);
|
|
13
|
+
// =============================================================================
|
|
14
|
+
// Repo Detection
|
|
15
|
+
// =============================================================================
|
|
16
|
+
export async function getRepoInfo(cwd) {
|
|
17
|
+
try {
|
|
18
|
+
const { stdout } = await execFileAsync('gh', [
|
|
19
|
+
'repo', 'view', '--json', 'owner,name',
|
|
20
|
+
], { cwd });
|
|
21
|
+
const repo = JSON.parse(stdout);
|
|
22
|
+
return { owner: repo.owner.login, name: repo.name };
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
// =============================================================================
|
|
29
|
+
// GraphQL Query Building
|
|
30
|
+
// =============================================================================
|
|
31
|
+
function sevenDaysAgo() {
|
|
32
|
+
const d = new Date();
|
|
33
|
+
d.setDate(d.getDate() - 7);
|
|
34
|
+
return d.toISOString().split('T')[0]; // YYYY-MM-DD
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Sanitize a GitHub handle for use as a GraphQL alias.
|
|
38
|
+
* Replaces hyphens with underscores and prefixes with `u_` to avoid
|
|
39
|
+
* aliases starting with a digit (invalid in GraphQL).
|
|
40
|
+
*/
|
|
41
|
+
function toAlias(handle) {
|
|
42
|
+
return `u_${handle.replace(/-/g, '_')}`;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Build a batched GraphQL query that fetches assigned issues, authored PRs,
|
|
46
|
+
* and recent activity for all team members in one request.
|
|
47
|
+
*
|
|
48
|
+
* Owner/name are interpolated directly into search strings because
|
|
49
|
+
* GraphQL variables are not substituted inside string literals.
|
|
50
|
+
*/
|
|
51
|
+
export function buildTeamGraphQLQuery(members, owner, name) {
|
|
52
|
+
const since = sevenDaysAgo();
|
|
53
|
+
const repo = `${owner}/${name}`;
|
|
54
|
+
const fragments = members
|
|
55
|
+
.filter(m => isValidGitHubHandle(m.github))
|
|
56
|
+
.map((m) => {
|
|
57
|
+
const alias = toAlias(m.github);
|
|
58
|
+
return `
|
|
59
|
+
${alias}_assigned: search(query: "repo:${repo} assignee:${m.github} is:issue is:open", type: ISSUE, first: 20) {
|
|
60
|
+
nodes { ... on Issue { number title url } }
|
|
61
|
+
}
|
|
62
|
+
${alias}_prs: search(query: "repo:${repo} author:${m.github} is:pr is:open", type: ISSUE, first: 20) {
|
|
63
|
+
nodes { ... on PullRequest { number title url } }
|
|
64
|
+
}
|
|
65
|
+
${alias}_merged: search(query: "repo:${repo} author:${m.github} is:pr is:merged merged:>=${since}", type: ISSUE, first: 20) {
|
|
66
|
+
nodes { ... on PullRequest { number title mergedAt } }
|
|
67
|
+
}
|
|
68
|
+
${alias}_closed: search(query: "repo:${repo} assignee:${m.github} is:issue is:closed closed:>=${since}", type: ISSUE, first: 20) {
|
|
69
|
+
nodes { ... on Issue { number title closedAt } }
|
|
70
|
+
}`;
|
|
71
|
+
})
|
|
72
|
+
.join('\n');
|
|
73
|
+
return `{
|
|
74
|
+
${fragments}
|
|
75
|
+
}`;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Parse the GraphQL response into a map of github handle → TeamMemberGitHubData.
|
|
79
|
+
*/
|
|
80
|
+
export function parseTeamGraphQLResponse(data, members) {
|
|
81
|
+
const result = new Map();
|
|
82
|
+
for (const member of members) {
|
|
83
|
+
if (!isValidGitHubHandle(member.github))
|
|
84
|
+
continue;
|
|
85
|
+
const alias = toAlias(member.github);
|
|
86
|
+
const assigned = data[`${alias}_assigned`];
|
|
87
|
+
const prs = data[`${alias}_prs`];
|
|
88
|
+
const merged = data[`${alias}_merged`];
|
|
89
|
+
const closed = data[`${alias}_closed`];
|
|
90
|
+
result.set(member.github, {
|
|
91
|
+
assignedIssues: (assigned?.nodes ?? []).map(n => ({ number: n.number, title: n.title, url: n.url })),
|
|
92
|
+
openPRs: (prs?.nodes ?? []).map(n => ({ number: n.number, title: n.title, url: n.url })),
|
|
93
|
+
recentActivity: {
|
|
94
|
+
mergedPRs: (merged?.nodes ?? []).map(n => ({ number: n.number, title: n.title, mergedAt: n.mergedAt })),
|
|
95
|
+
closedIssues: (closed?.nodes ?? []).map(n => ({ number: n.number, title: n.title, closedAt: n.closedAt })),
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
return result;
|
|
100
|
+
}
|
|
101
|
+
// =============================================================================
|
|
102
|
+
// Main Fetch Function
|
|
103
|
+
// =============================================================================
|
|
104
|
+
/**
|
|
105
|
+
* Fetch GitHub data for all team members in a single batched GraphQL request.
|
|
106
|
+
* Returns null on failure (graceful degradation).
|
|
107
|
+
*/
|
|
108
|
+
export async function fetchTeamGitHubData(members, cwd) {
|
|
109
|
+
const validMembers = members.filter(m => isValidGitHubHandle(m.github));
|
|
110
|
+
if (validMembers.length === 0) {
|
|
111
|
+
return { data: new Map() };
|
|
112
|
+
}
|
|
113
|
+
const repo = await getRepoInfo(cwd);
|
|
114
|
+
if (!repo) {
|
|
115
|
+
return { data: new Map(), error: 'Could not determine repository (is gh CLI authenticated?)' };
|
|
116
|
+
}
|
|
117
|
+
const query = buildTeamGraphQLQuery(validMembers, repo.owner, repo.name);
|
|
118
|
+
try {
|
|
119
|
+
const { stdout } = await execFileAsync('gh', [
|
|
120
|
+
'api', 'graphql',
|
|
121
|
+
'-f', `query=${query}`,
|
|
122
|
+
], { cwd });
|
|
123
|
+
const response = JSON.parse(stdout);
|
|
124
|
+
if (!response.data) {
|
|
125
|
+
return { data: new Map(), error: 'GitHub GraphQL returned no data' };
|
|
126
|
+
}
|
|
127
|
+
return { data: parseTeamGraphQLResponse(response.data, validMembers) };
|
|
128
|
+
}
|
|
129
|
+
catch (err) {
|
|
130
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
131
|
+
return { data: new Map(), error: `GitHub API request failed: ${message}` };
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=team-github.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"team-github.js","sourceRoot":"","sources":["../../src/lib/team-github.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Team directory infrastructure for Codev.
|
|
3
|
+
*
|
|
4
|
+
* Reads team member files from codev/team/people/*.md (YAML frontmatter)
|
|
5
|
+
* and messages from codev/team/messages.md (append-only log).
|
|
6
|
+
*
|
|
7
|
+
* Spec 587: Team Tab in Tower Right Panel.
|
|
8
|
+
*/
|
|
9
|
+
export interface TeamMember {
|
|
10
|
+
name: string;
|
|
11
|
+
github: string;
|
|
12
|
+
role: string;
|
|
13
|
+
filePath: string;
|
|
14
|
+
}
|
|
15
|
+
export interface TeamMessage {
|
|
16
|
+
author: string;
|
|
17
|
+
timestamp: string;
|
|
18
|
+
body: string;
|
|
19
|
+
channel: string;
|
|
20
|
+
}
|
|
21
|
+
export interface MessageChannel {
|
|
22
|
+
name: string;
|
|
23
|
+
getMessages(): Promise<TeamMessage[]>;
|
|
24
|
+
}
|
|
25
|
+
export interface LoadResult<T> {
|
|
26
|
+
items: T[];
|
|
27
|
+
warnings: string[];
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Parse YAML frontmatter from a markdown file content string.
|
|
31
|
+
* Splits on `---` delimiters and parses the middle section with js-yaml.
|
|
32
|
+
*/
|
|
33
|
+
export declare function parseFrontmatter(content: string): Record<string, unknown> | null;
|
|
34
|
+
export declare function isValidGitHubHandle(handle: string): boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Load team members from codev/team/people/*.md files.
|
|
37
|
+
* Returns parsed members and any warnings encountered.
|
|
38
|
+
*/
|
|
39
|
+
export declare function loadTeamMembers(teamDir: string): Promise<LoadResult<TeamMember>>;
|
|
40
|
+
/**
|
|
41
|
+
* Parse a single message block (text between --- separators).
|
|
42
|
+
* Expected format:
|
|
43
|
+
* **author** | timestamp
|
|
44
|
+
* body text
|
|
45
|
+
*/
|
|
46
|
+
export declare function parseMessageBlock(block: string): TeamMessage | null;
|
|
47
|
+
/**
|
|
48
|
+
* Load messages from an append-only messages.md file.
|
|
49
|
+
* Each message is separated by `---`.
|
|
50
|
+
*/
|
|
51
|
+
export declare function loadMessages(messagesPath: string): Promise<LoadResult<TeamMessage>>;
|
|
52
|
+
/**
|
|
53
|
+
* Check if a valid team exists (codev/team/ with 2+ valid member files in people/).
|
|
54
|
+
* Reads and validates frontmatter to ensure members have required fields.
|
|
55
|
+
*/
|
|
56
|
+
export declare function hasTeam(teamDir: string): Promise<boolean>;
|
|
57
|
+
/**
|
|
58
|
+
* Append a message to the messages.md file.
|
|
59
|
+
* Creates the file with header if it doesn't exist.
|
|
60
|
+
*/
|
|
61
|
+
export declare function appendMessage(messagesPath: string, author: string, text: string): Promise<void>;
|
|
62
|
+
export declare class FileMessageChannel implements MessageChannel {
|
|
63
|
+
name: string;
|
|
64
|
+
private messagesPath;
|
|
65
|
+
constructor(messagesPath: string);
|
|
66
|
+
getMessages(): Promise<TeamMessage[]>;
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=team.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"team.d.ts","sourceRoot":"","sources":["../../src/lib/team.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAUH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAMD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAiBhF;AAWD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAE3D;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CA0DtF;AAQD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAcnE;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CA4BzF;AAMD;;;GAGG;AACH,wBAAsB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAG/D;AAWD;;;GAGG;AACH,wBAAsB,aAAa,CACjC,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC,CAkBf;AAMD,qBAAa,kBAAmB,YAAW,cAAc;IACvD,IAAI,SAAU;IACd,OAAO,CAAC,YAAY,CAAS;gBAEjB,YAAY,EAAE,MAAM;IAI1B,WAAW,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;CAI5C"}
|
package/dist/lib/team.js
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Team directory infrastructure for Codev.
|
|
3
|
+
*
|
|
4
|
+
* Reads team member files from codev/team/people/*.md (YAML frontmatter)
|
|
5
|
+
* and messages from codev/team/messages.md (append-only log).
|
|
6
|
+
*
|
|
7
|
+
* Spec 587: Team Tab in Tower Right Panel.
|
|
8
|
+
*/
|
|
9
|
+
import * as fs from 'node:fs/promises';
|
|
10
|
+
import * as path from 'node:path';
|
|
11
|
+
import * as yaml from 'js-yaml';
|
|
12
|
+
// =============================================================================
|
|
13
|
+
// Frontmatter Parsing
|
|
14
|
+
// =============================================================================
|
|
15
|
+
/**
|
|
16
|
+
* Parse YAML frontmatter from a markdown file content string.
|
|
17
|
+
* Splits on `---` delimiters and parses the middle section with js-yaml.
|
|
18
|
+
*/
|
|
19
|
+
export function parseFrontmatter(content) {
|
|
20
|
+
const trimmed = content.trimStart();
|
|
21
|
+
if (!trimmed.startsWith('---'))
|
|
22
|
+
return null;
|
|
23
|
+
const secondDash = trimmed.indexOf('---', 3);
|
|
24
|
+
if (secondDash === -1)
|
|
25
|
+
return null;
|
|
26
|
+
const frontmatterStr = trimmed.slice(3, secondDash).trim();
|
|
27
|
+
if (!frontmatterStr)
|
|
28
|
+
return null;
|
|
29
|
+
try {
|
|
30
|
+
const parsed = yaml.load(frontmatterStr);
|
|
31
|
+
if (typeof parsed !== 'object' || parsed === null)
|
|
32
|
+
return null;
|
|
33
|
+
return parsed;
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
// =============================================================================
|
|
40
|
+
// Team Members
|
|
41
|
+
// =============================================================================
|
|
42
|
+
// GitHub's documented rules say no trailing hyphens or consecutive hyphens,
|
|
43
|
+
// but real accounts like "timeleft--" exist. Match what GitHub actually allows:
|
|
44
|
+
// starts with alphanumeric, then any mix of alphanumeric and hyphens.
|
|
45
|
+
const GITHUB_HANDLE_RE = /^[a-zA-Z0-9][a-zA-Z0-9-]*$/;
|
|
46
|
+
export function isValidGitHubHandle(handle) {
|
|
47
|
+
return GITHUB_HANDLE_RE.test(handle) && handle.length <= 39;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Load team members from codev/team/people/*.md files.
|
|
51
|
+
* Returns parsed members and any warnings encountered.
|
|
52
|
+
*/
|
|
53
|
+
export async function loadTeamMembers(teamDir) {
|
|
54
|
+
const peopleDir = path.join(teamDir, 'people');
|
|
55
|
+
const warnings = [];
|
|
56
|
+
const members = [];
|
|
57
|
+
const seenHandles = new Set();
|
|
58
|
+
let files;
|
|
59
|
+
try {
|
|
60
|
+
const entries = await fs.readdir(peopleDir);
|
|
61
|
+
files = entries.filter(f => f.endsWith('.md')).sort();
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return { items: [], warnings: [`people/ directory not found: ${peopleDir}`] };
|
|
65
|
+
}
|
|
66
|
+
for (const file of files) {
|
|
67
|
+
const filePath = path.join(peopleDir, file);
|
|
68
|
+
let content;
|
|
69
|
+
try {
|
|
70
|
+
content = await fs.readFile(filePath, 'utf-8');
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
warnings.push(`Could not read ${file}`);
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
const frontmatter = parseFrontmatter(content);
|
|
77
|
+
if (!frontmatter) {
|
|
78
|
+
warnings.push(`Malformed YAML frontmatter in ${file}`);
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
const name = typeof frontmatter.name === 'string' ? frontmatter.name.trim() : '';
|
|
82
|
+
const github = typeof frontmatter.github === 'string' ? frontmatter.github.trim() : '';
|
|
83
|
+
const role = typeof frontmatter.role === 'string' ? frontmatter.role.trim() : 'member';
|
|
84
|
+
if (!name) {
|
|
85
|
+
warnings.push(`Missing 'name' field in ${file}`);
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (!github) {
|
|
89
|
+
warnings.push(`Missing 'github' field in ${file}`);
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
if (!isValidGitHubHandle(github)) {
|
|
93
|
+
warnings.push(`Invalid GitHub handle '${github}' in ${file} (skipped)`);
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
const handleLower = github.toLowerCase();
|
|
97
|
+
if (seenHandles.has(handleLower)) {
|
|
98
|
+
warnings.push(`Duplicate GitHub handle '${github}' in ${file} (skipped)`);
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
seenHandles.add(handleLower);
|
|
102
|
+
members.push({ name, github, role, filePath });
|
|
103
|
+
}
|
|
104
|
+
return { items: members, warnings };
|
|
105
|
+
}
|
|
106
|
+
// =============================================================================
|
|
107
|
+
// Messages
|
|
108
|
+
// =============================================================================
|
|
109
|
+
const MESSAGE_HEADER_RE = /^\*\*([^*]+)\*\*\s*\|\s*(.+)$/;
|
|
110
|
+
/**
|
|
111
|
+
* Parse a single message block (text between --- separators).
|
|
112
|
+
* Expected format:
|
|
113
|
+
* **author** | timestamp
|
|
114
|
+
* body text
|
|
115
|
+
*/
|
|
116
|
+
export function parseMessageBlock(block) {
|
|
117
|
+
const lines = block.trim().split('\n');
|
|
118
|
+
if (lines.length === 0)
|
|
119
|
+
return null;
|
|
120
|
+
const headerMatch = lines[0].match(MESSAGE_HEADER_RE);
|
|
121
|
+
if (!headerMatch)
|
|
122
|
+
return null;
|
|
123
|
+
const author = headerMatch[1].trim();
|
|
124
|
+
const timestamp = headerMatch[2].trim();
|
|
125
|
+
const body = lines.slice(1).join('\n').trim();
|
|
126
|
+
if (!author || !timestamp)
|
|
127
|
+
return null;
|
|
128
|
+
return { author, timestamp, body, channel: 'file' };
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Load messages from an append-only messages.md file.
|
|
132
|
+
* Each message is separated by `---`.
|
|
133
|
+
*/
|
|
134
|
+
export async function loadMessages(messagesPath) {
|
|
135
|
+
const warnings = [];
|
|
136
|
+
let content;
|
|
137
|
+
try {
|
|
138
|
+
content = await fs.readFile(messagesPath, 'utf-8');
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
return { items: [], warnings: [] };
|
|
142
|
+
}
|
|
143
|
+
const blocks = content.split(/^---$/m);
|
|
144
|
+
const messages = [];
|
|
145
|
+
for (const block of blocks) {
|
|
146
|
+
const trimmed = block.trim();
|
|
147
|
+
if (!trimmed)
|
|
148
|
+
continue;
|
|
149
|
+
// Skip the header line (# Team Messages) and comments
|
|
150
|
+
if (trimmed.startsWith('#') || trimmed.startsWith('<!--'))
|
|
151
|
+
continue;
|
|
152
|
+
const message = parseMessageBlock(trimmed);
|
|
153
|
+
if (message) {
|
|
154
|
+
messages.push(message);
|
|
155
|
+
}
|
|
156
|
+
else if (trimmed.length > 0 && !trimmed.startsWith('#') && !trimmed.startsWith('<!--')) {
|
|
157
|
+
warnings.push(`Malformed message block skipped: ${trimmed.slice(0, 50)}...`);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return { items: messages, warnings };
|
|
161
|
+
}
|
|
162
|
+
// =============================================================================
|
|
163
|
+
// Team Detection
|
|
164
|
+
// =============================================================================
|
|
165
|
+
/**
|
|
166
|
+
* Check if a valid team exists (codev/team/ with 2+ valid member files in people/).
|
|
167
|
+
* Reads and validates frontmatter to ensure members have required fields.
|
|
168
|
+
*/
|
|
169
|
+
export async function hasTeam(teamDir) {
|
|
170
|
+
const result = await loadTeamMembers(teamDir);
|
|
171
|
+
return result.items.length >= 2;
|
|
172
|
+
}
|
|
173
|
+
// =============================================================================
|
|
174
|
+
// Message Appending
|
|
175
|
+
// =============================================================================
|
|
176
|
+
const MESSAGES_HEADER = `# Team Messages
|
|
177
|
+
|
|
178
|
+
<!-- Append new messages below. Do not edit or delete existing entries. -->
|
|
179
|
+
`;
|
|
180
|
+
/**
|
|
181
|
+
* Append a message to the messages.md file.
|
|
182
|
+
* Creates the file with header if it doesn't exist.
|
|
183
|
+
*/
|
|
184
|
+
export async function appendMessage(messagesPath, author, text) {
|
|
185
|
+
const timestamp = new Date().toISOString().replace('T', ' ').replace(/\.\d+Z$/, ' UTC');
|
|
186
|
+
let exists = false;
|
|
187
|
+
try {
|
|
188
|
+
await fs.access(messagesPath);
|
|
189
|
+
exists = true;
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
// File doesn't exist — will create it
|
|
193
|
+
}
|
|
194
|
+
if (!exists) {
|
|
195
|
+
await fs.mkdir(path.dirname(messagesPath), { recursive: true });
|
|
196
|
+
await fs.writeFile(messagesPath, MESSAGES_HEADER, 'utf-8');
|
|
197
|
+
}
|
|
198
|
+
const entry = `\n---\n**${author}** | ${timestamp}\n${text}\n`;
|
|
199
|
+
await fs.appendFile(messagesPath, entry, 'utf-8');
|
|
200
|
+
}
|
|
201
|
+
// =============================================================================
|
|
202
|
+
// FileMessageChannel
|
|
203
|
+
// =============================================================================
|
|
204
|
+
export class FileMessageChannel {
|
|
205
|
+
name = 'file';
|
|
206
|
+
messagesPath;
|
|
207
|
+
constructor(messagesPath) {
|
|
208
|
+
this.messagesPath = messagesPath;
|
|
209
|
+
}
|
|
210
|
+
async getMessages() {
|
|
211
|
+
const result = await loadMessages(this.messagesPath);
|
|
212
|
+
return result.items;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=team.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"team.js","sourceRoot":"","sources":["../../src/lib/team.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cluesmith/codev",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0-rc.1",
|
|
4
4
|
"description": "Codev CLI - AI-assisted software development framework",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
"porch": "./bin/porch.js",
|
|
9
9
|
"af": "./bin/af.js",
|
|
10
10
|
"consult": "./bin/consult.js",
|
|
11
|
+
"team": "./bin/team.js",
|
|
11
12
|
"generate-image": "./bin/generate-image.js"
|
|
12
13
|
},
|
|
13
14
|
"files": [
|