@fuzzle/opencode-accountant 0.10.6-next.1 → 0.10.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -270,15 +270,6 @@ The pipeline automatically manages account declarations:
270
270
 
271
271
  **No manual account setup required.** Account declarations are created proactively before import attempts.
272
272
 
273
- #### Commodity Declarations
274
-
275
- For Swissquote investment imports, the pipeline automatically manages commodity declarations:
276
-
277
- - Collects all stock ticker symbols from trades, dividends, and corporate actions
278
- - Writes sorted `commodity "SYMBOL"` declarations to `ledger/investments/commodities.journal`
279
- - Merges with existing declarations (idempotent)
280
- - Ensures `hledger check --strict` validation passes for quoted commodity symbols
281
-
282
273
  #### Unknown Postings
283
274
 
284
275
  When a transaction doesn't match any `if` pattern in the rules file, hledger assigns it to `income:unknown` or `expenses:unknown` depending on the transaction direction. The pipeline will fail at the validation step, reporting the unknown postings so you can add appropriate rules before retrying.
@@ -164,15 +164,6 @@ The import pipeline automatically:
164
164
  - Prevents `hledger check --strict` failures due to missing account declarations
165
165
  - No manual account setup required
166
166
 
167
- ### Automatic Commodity Declarations
168
-
169
- For Swissquote investment imports, the pipeline automatically:
170
-
171
- - Collects all stock ticker symbols from trades, dividends, and corporate actions
172
- - Writes sorted `commodity "SYMBOL"` declarations to `ledger/investments/commodities.journal`
173
- - Merges with existing declarations (idempotent)
174
- - Prevents `hledger check --strict` failures due to missing commodity declarations
175
-
176
167
  ### Automatic Balance Detection
177
168
 
178
169
  The reconciliation step attempts to extract closing balance from:
package/dist/index.js CHANGED
@@ -4533,7 +4533,7 @@ var init_accountSuggester = __esm(() => {
4533
4533
 
4534
4534
  // src/index.ts
4535
4535
  init_agentLoader();
4536
- import { dirname as dirname7, join as join15 } from "path";
4536
+ import { dirname as dirname6, join as join15 } from "path";
4537
4537
  import { fileURLToPath as fileURLToPath3 } from "url";
4538
4538
 
4539
4539
  // node_modules/zod/v4/classic/external.js
@@ -17051,38 +17051,6 @@ function ensureYearJournalExists(directory, year) {
17051
17051
  }
17052
17052
  return yearJournalPath;
17053
17053
  }
17054
- function ensureCommodityDeclarations(commodityJournalPath, symbols, logger) {
17055
- const existing = new Set;
17056
- if (fs4.existsSync(commodityJournalPath)) {
17057
- const content2 = fs4.readFileSync(commodityJournalPath, "utf-8");
17058
- for (const line of content2.split(`
17059
- `)) {
17060
- const match = line.trim().match(/^commodity\s+"(.+)"/);
17061
- if (match) {
17062
- existing.add(match[1]);
17063
- }
17064
- }
17065
- }
17066
- const missing = [];
17067
- for (const symbol2 of symbols) {
17068
- const upper = symbol2.toUpperCase();
17069
- if (!existing.has(upper)) {
17070
- missing.push(upper);
17071
- existing.add(upper);
17072
- }
17073
- }
17074
- if (missing.length === 0) {
17075
- return { added: [], updated: false };
17076
- }
17077
- const sorted = Array.from(existing).sort((a, b) => a.localeCompare(b));
17078
- const content = sorted.map((s) => `commodity "${s}"`).join(`
17079
- `) + `
17080
- `;
17081
- ensureDirectory(path3.dirname(commodityJournalPath));
17082
- fs4.writeFileSync(commodityJournalPath, content);
17083
- logger?.info(`Commodity declarations: added ${missing.length} (${missing.join(", ")})`);
17084
- return { added: missing.sort(), updated: true };
17085
- }
17086
17054
 
17087
17055
  // src/utils/dateUtils.ts
17088
17056
  function formatDateISO(date5) {
@@ -25048,9 +25016,6 @@ function formatDate(dateStr) {
25048
25016
  function escapeDescription(desc) {
25049
25017
  return desc.replace(/[;|]/g, "-").trim();
25050
25018
  }
25051
- function formatCommodity(symbol2) {
25052
- return `"${symbol2.toUpperCase()}"`;
25053
- }
25054
25019
  function formatQuantity(qty) {
25055
25020
  return qty.toFixed(6).replace(/\.?0+$/, "");
25056
25021
  }
@@ -25068,12 +25033,11 @@ function generateBuyEntry(trade, logger) {
25068
25033
  const fees = trade.costs;
25069
25034
  const cashOut = totalCost + fees;
25070
25035
  logger?.debug(`Generating Buy entry: ${qty} ${trade.symbol} @ ${price} ${trade.currency}`);
25071
- const commodity = formatCommodity(trade.symbol);
25072
25036
  let entry = `${date5} ${description}
25073
25037
  `;
25074
25038
  entry += ` ; swissquote:order:${trade.orderNum} isin:${trade.isin}
25075
25039
  `;
25076
- entry += ` assets:investments:stocks:${trade.symbol} ${qty} ${commodity} @ ${price} ${trade.currency}
25040
+ entry += ` assets:investments:stocks:${trade.symbol} ${qty} @ ${price} ${trade.currency}
25077
25041
  `;
25078
25042
  if (fees > 0) {
25079
25043
  entry += ` expenses:fees:trading:swissquote ${formatAmount2(fees, trade.currency)}
@@ -25093,7 +25057,6 @@ function generateSellEntry(trade, consumed, logger) {
25093
25057
  const cashIn = saleProceeds - fees;
25094
25058
  const gain = calculateCapitalGain(consumed, salePrice, trade.quantity);
25095
25059
  logger?.debug(`Generating Sell entry: ${qty} ${trade.symbol} @ ${salePrice} ${trade.currency}, gain: ${gain.toFixed(2)}`);
25096
- const commodity = formatCommodity(trade.symbol);
25097
25060
  let entry = `${date5} ${description}
25098
25061
  `;
25099
25062
  entry += ` ; swissquote:order:${trade.orderNum} isin:${trade.isin}
@@ -25104,7 +25067,7 @@ function generateSellEntry(trade, consumed, logger) {
25104
25067
  for (const c of consumed) {
25105
25068
  const lotQty = formatQuantity(c.quantity);
25106
25069
  const lotPrice = formatPrice(c.lot.costBasis);
25107
- entry += ` assets:investments:stocks:${trade.symbol} -${lotQty} ${commodity} @ ${lotPrice} ${trade.currency}
25070
+ entry += ` assets:investments:stocks:${trade.symbol} -${lotQty} @ ${lotPrice} ${trade.currency}
25108
25071
  `;
25109
25072
  }
25110
25073
  entry += ` assets:broker:swissquote:${trade.currency.toLowerCase()} ${formatAmount2(cashIn, trade.currency)}
@@ -25152,14 +25115,13 @@ function generateSplitEntry(action, oldQuantity, newQuantity, logger) {
25152
25115
  `;
25153
25116
  entry += ` ; Ratio: ${ratio.toFixed(4)} (${oldQuantity} -> ${newQuantity})
25154
25117
  `;
25155
- const commodity = formatCommodity(action.symbol);
25156
- entry += ` assets:investments:stocks:${action.symbol} -${formatQuantity(oldQuantity)} ${commodity}
25118
+ entry += ` assets:investments:stocks:${action.symbol} -${formatQuantity(oldQuantity)}
25157
25119
  `;
25158
- entry += ` equity:conversion ${formatQuantity(oldQuantity)} ${commodity}
25120
+ entry += ` equity:conversion ${formatQuantity(oldQuantity)}
25159
25121
  `;
25160
- entry += ` equity:conversion -${formatQuantity(newQuantity)} ${commodity}
25122
+ entry += ` equity:conversion -${formatQuantity(newQuantity)}
25161
25123
  `;
25162
- entry += ` assets:investments:stocks:${action.symbol} ${formatQuantity(newQuantity)} ${commodity}
25124
+ entry += ` assets:investments:stocks:${action.symbol} ${formatQuantity(newQuantity)}
25163
25125
  `;
25164
25126
  return entry;
25165
25127
  }
@@ -25176,11 +25138,10 @@ function generateWorthlessEntry(action, removedLots, logger) {
25176
25138
  `;
25177
25139
  entry += ` ; Total loss: ${totalCost.toFixed(2)} ${currency}
25178
25140
  `;
25179
- const commodity = formatCommodity(action.symbol);
25180
25141
  for (const lot of removedLots) {
25181
25142
  const qty = formatQuantity(lot.quantity);
25182
25143
  const price = formatPrice(lot.costBasis);
25183
- entry += ` assets:investments:stocks:${action.symbol} -${qty} ${commodity} @ ${price} ${currency}
25144
+ entry += ` assets:investments:stocks:${action.symbol} -${qty} @ ${price} ${currency}
25184
25145
  `;
25185
25146
  }
25186
25147
  entry += ` expenses:losses:capital ${formatAmount2(totalCost, currency)}
@@ -25205,18 +25166,16 @@ function generateMultiWayMergerEntry(group, crossCurrencyOutgoingSymbols, logger
25205
25166
  }
25206
25167
  for (const out of group.outgoing) {
25207
25168
  const qty = formatQuantity(Math.abs(out.quantity));
25208
- const commodity = formatCommodity(out.symbol);
25209
- entry += ` assets:investments:stocks:${out.symbol} -${qty} ${commodity}
25169
+ entry += ` assets:investments:stocks:${out.symbol} -${qty}
25210
25170
  `;
25211
- entry += ` equity:conversion ${qty} ${commodity}
25171
+ entry += ` equity:conversion ${qty}
25212
25172
  `;
25213
25173
  }
25214
25174
  for (const inc of group.incoming) {
25215
25175
  const qty = formatQuantity(Math.abs(inc.quantity));
25216
- const commodity = formatCommodity(inc.symbol);
25217
- entry += ` equity:conversion -${qty} ${commodity}
25176
+ entry += ` equity:conversion -${qty}
25218
25177
  `;
25219
- entry += ` assets:investments:stocks:${inc.symbol} ${qty} ${commodity}
25178
+ entry += ` assets:investments:stocks:${inc.symbol} ${qty}
25220
25179
  `;
25221
25180
  }
25222
25181
  return entry;
@@ -25226,12 +25185,11 @@ function generateRightsDistributionEntry(action, logger) {
25226
25185
  const qty = formatQuantity(Math.abs(action.quantity));
25227
25186
  const description = escapeDescription(`Rights Distribution: ${action.symbol} - ${action.name}`);
25228
25187
  logger?.debug(`Generating Rights Distribution entry: ${qty} ${action.symbol}`);
25229
- const commodity = formatCommodity(action.symbol);
25230
25188
  let entry = `${date5} ${description}
25231
25189
  `;
25232
25190
  entry += ` ; swissquote:order:${action.orderNum} isin:${action.isin}
25233
25191
  `;
25234
- entry += ` assets:investments:stocks:${action.symbol} ${qty} ${commodity} @ 0.00 CAD
25192
+ entry += ` assets:investments:stocks:${action.symbol} ${qty} @ 0.00 CAD
25235
25193
  `;
25236
25194
  entry += ` income:capital-gains:rights-distribution 0.00 CAD
25237
25195
  `;
@@ -25799,23 +25757,6 @@ async function preprocessSwissquote(csvPath, projectDir, currency, year, lotInve
25799
25757
  logger?.logStep("write-journal", "success", `Created ${path13.basename(journalFile)} with ${journalEntries.length} entries`);
25800
25758
  }
25801
25759
  }
25802
- const stockSymbols = new Set;
25803
- for (const trade of trades) {
25804
- stockSymbols.add(trade.symbol);
25805
- }
25806
- for (const dividend of dividends) {
25807
- stockSymbols.add(dividend.symbol);
25808
- }
25809
- for (const action of corporateActions) {
25810
- stockSymbols.add(action.symbol);
25811
- if (action.newSymbol) {
25812
- stockSymbols.add(action.newSymbol);
25813
- }
25814
- }
25815
- if (stockSymbols.size > 0) {
25816
- const commodityJournalPath = path13.join(projectDir, "ledger", "investments", "commodities.journal");
25817
- ensureCommodityDeclarations(commodityJournalPath, stockSymbols, logger);
25818
- }
25819
25760
  logger?.logResult({
25820
25761
  totalRows: stats.totalRows,
25821
25762
  simpleTransactions: stats.simpleTransactions,
@@ -26744,7 +26685,7 @@ to produce equity conversion entries for Bitcoin purchases.
26744
26685
  }
26745
26686
  });
26746
26687
  // src/index.ts
26747
- var __dirname2 = dirname7(fileURLToPath3(import.meta.url));
26688
+ var __dirname2 = dirname6(fileURLToPath3(import.meta.url));
26748
26689
  var AGENT_FILE = join15(__dirname2, "..", "agent", "accountant.md");
26749
26690
  var AccountantPlugin = async () => {
26750
26691
  const agent = loadAgent(AGENT_FILE);
@@ -220,8 +220,7 @@ See [classify-statements](classify-statements.md) for details.
220
220
  - **Rights Distributions**: adds shares at zero cost basis
221
221
  - **Cross-currency mergers**: saves outgoing side to pending state, loads when incoming side is processed
222
222
  8. Generates per-year investment journal entries (`ledger/investments/{year}-{currency}.journal`) based on the CSV filename's date range
223
- 9. Collects all stock ticker symbols and writes commodity declarations to `ledger/investments/commodities.journal` (merged with existing, sorted, idempotent)
224
- 10. Outputs filtered CSV (simple transactions only) for hledger rules import
223
+ 9. Outputs filtered CSV (simple transactions only) for hledger rules import
225
224
 
226
225
  **Symbol Map**: Maps Swissquote's internal symbol names (e.g., `GOLD ROYALTY RG`, `VIZSLA WT 12.25`) to canonical ticker symbols (e.g., `GROY`, `VROY-WT`). Applied before any processing, so journal entries, lot inventory filenames, and account names all use the mapped symbols. See [Symbol Map Configuration](../configuration/symbol-map.md).
227
226
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fuzzle/opencode-accountant",
3
- "version": "0.10.6-next.1",
3
+ "version": "0.10.6",
4
4
  "description": "An OpenCode accounting agent, specialized in double-entry-bookkepping with hledger",
5
5
  "author": {
6
6
  "name": "ali bengali",