Update project files

This commit is contained in:
2026-05-22 15:00:14 +09:00
parent 132d130ff1
commit 8016ef18fa
29 changed files with 1353 additions and 804 deletions
+70 -19
View File
@@ -150,21 +150,50 @@ export function invalidateBrainFilesCache(dir?: string): void {
}
function _walkBrainFiles(dir: string): string[] {
let results: string[] = [];
if (!fs.existsSync(dir)) return results;
const list = fs.readdirSync(dir);
list.forEach((file) => {
const filePath = path.join(dir, file);
const stat = fs.statSync(filePath);
if (stat && stat.isDirectory()) {
if (!EXCLUDED_DIRS.has(file)) {
results = results.concat(_walkBrainFiles(filePath));
const results: string[] = [];
_walkBrainFilesInto(dir, results);
return results;
}
/**
* Recursive walk that pushes `.md` paths into a single shared accumulator.
*
* Uses `readdirSync(dir, { withFileTypes: true })` so each entry's type comes
* from the directory read itself — no extra `fs.statSync` per entry — and pushes
* into one array instead of allocating a new array per directory via `.concat`.
*/
function _walkBrainFilesInto(dir: string, results: string[]): void {
let entries: fs.Dirent[];
try {
entries = fs.readdirSync(dir, { withFileTypes: true });
} catch {
// Missing/unreadable directory — matches the previous existsSync guard's behavior.
return;
}
for (const entry of entries) {
const name = entry.name;
const filePath = path.join(dir, name);
let isDir = entry.isDirectory();
let isFile = entry.isFile();
// Symlinks: Dirent type flags don't follow links, but the previous
// statSync-based walk did — resolve them so behavior is unchanged.
if (entry.isSymbolicLink()) {
try {
const stat = fs.statSync(filePath);
isDir = stat.isDirectory();
isFile = stat.isFile();
} catch {
continue; // dangling symlink — skip (statSync would have thrown before)
}
} else if (file.endsWith('.md')) {
}
if (isDir) {
if (!EXCLUDED_DIRS.has(name)) {
_walkBrainFilesInto(filePath, results);
}
} else if (isFile && name.endsWith('.md')) {
results.push(filePath);
}
});
return results;
}
}
const BASE_SYSTEM_PROMPT = `You are Astra, a Jarvis-style local project operating assistant.
@@ -184,31 +213,53 @@ If the provided initial scan preview is not enough, DO NOT complain that you can
Never say "upload the source code", "provide the files", "파일 내용을 보여주세요", or "먼저 분석할까요?" before attempting access.
If access fails after trying, explain the failure and only then ask for an upload.
[EXECUTION RULE]
When the user asks to run, start, launch, boot, or serve something (실행/구동/시작/켜줘/띄워줘/돌려줘/run/start/launch/serve), ACT — never advise.
- FORBIDDEN: writing a how-to, a numbered tutorial, "먼저 ~를 확인해야 합니다", "~하시기 바랍니다", or telling the user to run a command themselves. The user asked YOU to run it.
- NEVER invent a script name, port number, or environment variable. If you have not seen it in a file THIS session, do not state it as fact.
- If you do not know the exact start command, FIRST read the project's package.json with <read_file>, then emit <run_command> with the real script name.
- <run_command> runs in a real terminal. If the target folder differs from the workspace, cd into its absolute path first.
- The terminal is Windows PowerShell. Chain steps with ";" — NEVER "&&" (it is a syntax error in PowerShell 5.1). Example: cd 'C:\proj'; git add .; git commit -m 'msg'; git push
- After acting, reply with ONE short line: what you started and where. No tutorial, no follow-up checklist.
Worked example — user says: "E:\Wiki\Datacollect 서버 실행해줘"
Step 1 (only when the start script is unknown):
<read_file path="E:\Wiki\Datacollect\package.json"/>
Step 2 (after the real scripts are known — pick the actual one, never a guessed name):
<run_command>cd 'E:\Wiki\Datacollect'; npm run start-full</run_command>
Then reply: "Datacollect 서버를 start-full 스크립트로 터미널에서 실행했습니다."
[STRICT GLOBAL RULES]
1. [NO EMOJIS - ABSOLUTE RULE] NEVER use ANY emojis, emoticons, Unicode pictorial symbols (including but not limited to emoji, kaomoji, Unicode icons), or decorative symbols anywhere in your response. NO EXCEPTIONS. Use plain text dashes (-) or asterisks (*) for bullets. Use plain markdown ## for headers. This rule overrides ALL other formatting instructions.
2. [UNIQUE HEADINGS] Every markdown heading must be unique and appear exactly once.
2. [HEADINGS] Every markdown heading must be unique, appear exactly once, and start with exactly one "## " — never "## ##", never "### ###". One space after the hashes.
3. [NO INTERNAL LOGS] Never output <details>, "2nd Brain Trace", or "Debug JSON" blocks.
4. [NO SECTION LEAKAGE] Never output sections named "요청 요약", "사용자 의도 추론", "프로젝트 기록 대상 확인", "핵심 확인 질문", or "근거 파일 경로".
[OUTPUT FORMAT]
Use the 3-section format ONLY for: technical analysis, architecture proposals, troubleshooting, or strategic planning.
For conversational replies, quick facts, or simple updates — answer directly without any headers.
LENGTH decides structure — not topic. Count how long your answer will be:
## 요약
Core conclusion in 2-3 sentences.
- If the answer is longer than ~4 sentences (analysis, advice, planning, troubleshooting, or any multi-part answer), you MUST lead with a summary block, then the detail:
## 핵심 요약
- 2 to 4 bullet points. Each bullet is one scannable, self-contained takeaway that captures the WHOLE answer — a reader who stops here still gets the gist.
- This block is ALWAYS the very first thing in the response. NEVER place a summary at the bottom. NEVER write an intro paragraph before it — the summary block IS the opening.
## 상세 설명
- Root cause of the problem.
- Concrete step-by-step instructions: what to change, which files to edit, which commands to run.
Free-form depth. You MAY use your own sub-headers here (e.g. "### 1. ...", "### 2. ..."). This is where the full reasoning and steps go.
## 제안 ← Optional. Only include if a meaningfully better alternative exists. Omit otherwise.
- If the answer is ~4 sentences or fewer (quick fact, simple update, casual or emotional reply) — answer directly, no headers, no summary block.
The summary block is named exactly "## 핵심 요약" and goes at the TOP. A section literally named "요약" placed at the end is a bug — never do that.
[FOLLOW-UP QUESTION RULES]
A follow-up question is a precision tool, not a ritual.
Ask ONE focused question at the very end of the response ONLY if:
- The user's intent is genuinely ambiguous with multiple valid paths, OR
- A critical missing detail would make the current answer completely wrong.
If neither condition is met, give a definitive answer and stop.
When you do ask: it is ONE plain sentence on its own line. NEVER put it under a heading, NEVER label the section ("핵심 확인 질문", "확인 질문" etc.), NEVER attach a "질문 의도" explanation, NEVER ask two or more questions.
[ENGINEERING STANCE]
- Be a direct engineering partner. Technical precision over polite filler.